1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese, Pierpaolo Prazzoli
3 /******************************************************************************************
4 
5 Sengoku Mahjong (c) 1991 Sigma
6 
7 driver by Angelo Salese & Pierpaolo Prazzoli
8 
9 Uses the same Seibu custom chips of the D-Con HW.
10 
11 TODO:
12 - Find what the remaining video C.R.T. registers does;
13 - Fix sprites bugs at a start of a play;
14 - Check NVRAM boudaries;
15 - How the "SW Service Mode" (press F2 during gameplay) really works (inputs etc)? Nothing mapped works with it...
16 
17 Notes:
18 - Some strings written in the sound rom:
19   "SENGOKU-MAHJONG Z80 PROGRAM ROM VERSION 1.00 WRITTEN BY K.SAEKI" at location 0x00c0-0x00ff.
20   "Copyright 1990/1991 Sigma" at location 0x770-0x789.
21 - To bypass the startup message, toggle "Reset" dip-switch or reset with F3.
22 - If the Work RAM is not hooked-up (areas $67xx),a sound sample is played.I can't understand what it says though,
23   appears to japanese words for "RAM failed".
24 - Snippets of a non-BET Version are scattered thru the code (for example a credit display).
25   Might be either undumped revision or selectable somehow.
26 
27 CPU:    uPD70116C-8 (V30)
28 Sound:  Z80-A
29         YM3812
30         M6295
31 OSC:    14.31818MHz
32         16.000MHz
33 Chips:  SEI0100 (YM3931, main/sub cpu interface)
34         SEI0160
35         SEI0200 (tilemap chip)
36         SEI0210
37         SEI0220 (sprite chip)
38 
39 
40 MAH1-1-1.915  samples
41 
42 MAH1-2-1.013  sound prg. (ic1013:27c512)
43 
44 MM01-1-1.21   main prg.
45 MM01-2-1.24
46 
47 RS006.89      video timing?
48 
49 RSSENGO0.64   chr.
50 RSSENGO1.68
51 
52 RSSENGO2.72   chr.
53 
54 *******************************************************************************************/
55 
56 #include "emu.h"
57 #include "audio/seibu.h"
58 
59 #include "cpu/nec/nec.h"
60 #include "machine/nvram.h"
61 #include "sound/3812intf.h"
62 #include "sound/okim6295.h"
63 #include "video/seibu_crtc.h"
64 #include "emupal.h"
65 #include "screen.h"
66 #include "speaker.h"
67 #include "tilemap.h"
68 
69 
70 class sengokmj_state : public driver_device, public seibu_sound_common
71 {
72 public:
sengokmj_state(const machine_config & mconfig,device_type type,const char * tag)73 	sengokmj_state(const machine_config &mconfig, device_type type, const char *tag) :
74 		driver_device(mconfig, type, tag),
75 		m_maincpu(*this, "maincpu"),
76 		m_gfxdecode(*this, "gfxdecode"),
77 		m_palette(*this, "palette"),
78 		m_sc0_vram(*this, "sc0_vram"),
79 		m_sc1_vram(*this, "sc1_vram"),
80 		m_sc2_vram(*this, "sc2_vram"),
81 		m_sc3_vram(*this, "sc3_vram"),
82 		m_spriteram16(*this, "sprite_ram")
83 	{ }
84 
85 	void sengokmj(machine_config &config);
86 
87 protected:
88 	virtual void machine_start() override;
89 	virtual void video_start() override;
90 
91 private:
92 	required_device<cpu_device> m_maincpu;
93 	required_device<gfxdecode_device> m_gfxdecode;
94 	required_device<palette_device> m_palette;
95 
96 	required_shared_ptr<uint16_t> m_sc0_vram;
97 	required_shared_ptr<uint16_t> m_sc1_vram;
98 	required_shared_ptr<uint16_t> m_sc2_vram;
99 	required_shared_ptr<uint16_t> m_sc3_vram;
100 	required_shared_ptr<uint16_t> m_spriteram16;
101 
102 	tilemap_t *m_sc0_tilemap;
103 	tilemap_t *m_sc1_tilemap;
104 	tilemap_t *m_sc2_tilemap;
105 	tilemap_t *m_sc3_tilemap;
106 
107 	uint16_t m_mux_data;
108 	uint8_t m_hopper_io;
109 	uint16_t m_layer_en;
110 	uint16_t m_scrollram[6];
111 
112 	uint16_t mahjong_panel_r();
113 	void mahjong_panel_w(uint16_t data);
114 	void out_w(uint16_t data);
115 	uint16_t system_r();
116 	void seibucrtc_sc0vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
117 	void seibucrtc_sc1vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
118 	void seibucrtc_sc2vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
119 	void seibucrtc_sc3vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
120 	void layer_en_w(uint16_t data);
121 	void layer_scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
122 
123 	TILE_GET_INFO_MEMBER(seibucrtc_sc0_tile_info);
124 	TILE_GET_INFO_MEMBER(seibucrtc_sc1_tile_info);
125 	TILE_GET_INFO_MEMBER(seibucrtc_sc2_tile_info);
126 	TILE_GET_INFO_MEMBER(seibucrtc_sc3_tile_info);
127 
128 	DECLARE_WRITE_LINE_MEMBER(vblank_irq);
129 
130 	void draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect,int pri);
131 	uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
132 
133 	void sengokmj_io_map(address_map &map);
134 	void sengokmj_map(address_map &map);
135 };
136 
137 
138 /*******************************
139 *
140 * Macros for the video registers
141 *
142 *******************************/
143 
144 #define SEIBU_CRTC_ENABLE_SC0   (!(m_layer_en & 0x0001))
145 #define SEIBU_CRTC_ENABLE_SC2   (!(m_layer_en & 0x0002))
146 #define SEIBU_CRTC_ENABLE_SC1   (!(m_layer_en & 0x0004))
147 #define SEIBU_CRTC_ENABLE_SC3   (!(m_layer_en & 0x0008))
148 #define SEIBU_CRTC_ENABLE_SPR   (!(m_layer_en & 0x0010))
149 
150 /************************************
151 * 0x20 - Screen 0 (BG) scroll x
152 ************************************/
153 #define SEIBU_CRTC_SC0_SX   (m_scrollram[0])
154 
155 /************************************
156 * 0x22 - Screen 0 (BG) scroll y
157 ************************************/
158 #define SEIBU_CRTC_SC0_SY   (m_scrollram[1])
159 
160 /************************************
161 * 0x24 - Screen 1 (FG) scroll x
162 ************************************/
163 #define SEIBU_CRTC_SC1_SX   (m_scrollram[4])
164 
165 /************************************
166 * 0x26 - Screen 1 (FG) scroll y
167 ************************************/
168 #define SEIBU_CRTC_SC1_SY   (m_scrollram[5])
169 
170 /************************************
171 * 0x28 - Screen 2 (MD) scroll x
172 ************************************/
173 #define SEIBU_CRTC_SC2_SX   (m_scrollram[2])
174 
175 /************************************
176 * 0x2a - Screen 2 (MD) scroll y
177 ************************************/
178 #define SEIBU_CRTC_SC2_SY   (m_scrollram[3])
179 
180 #if 0
181 /*******************************
182 * 0x1a - Layer Dynamic Paging?
183 *******************************/
184 #define SEIBU_CRTC_DYN_PAGING   (m_seibucrtc_vregs[0x001a/2])
185 #define SEIBU_CRTC_SC3_PAGE_SEL (SEIBU_CRTC_DYN_PAGING & 0x0002)
186 
187 /*******************************
188 * 0x1c - Layer Enable
189 *******************************/
190 
191 
192 
193 /************************************
194 * 0x2c - Fix screen scroll x (global)
195 ************************************/
196 #define SEIBU_CRTC_FIX_SX   (m_seibucrtc_vregs[0x002c/2])
197 
198 /************************************
199 * 0x2e - Fix screen scroll y (global)
200 ************************************/
201 #define SEIBU_CRTC_FIX_SY   (m_seibucrtc_vregs[0x002e/2])
202 #endif
203 
204 /*******************************
205 *
206 * Write RAM accesses
207 *
208 *******************************/
209 
seibucrtc_sc0vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)210 void sengokmj_state::seibucrtc_sc0vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
211 {
212 	COMBINE_DATA(&m_sc0_vram[offset]);
213 	m_sc0_tilemap->mark_tile_dirty(offset);
214 }
215 
seibucrtc_sc2vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)216 void sengokmj_state::seibucrtc_sc2vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
217 {
218 	COMBINE_DATA(&m_sc2_vram[offset]);
219 	m_sc2_tilemap->mark_tile_dirty(offset);
220 }
221 
seibucrtc_sc1vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)222 void sengokmj_state::seibucrtc_sc1vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
223 {
224 	COMBINE_DATA(&m_sc1_vram[offset]);
225 	m_sc1_tilemap->mark_tile_dirty(offset);
226 }
227 
seibucrtc_sc3vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)228 void sengokmj_state::seibucrtc_sc3vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
229 {
230 	COMBINE_DATA(&m_sc3_vram[offset]);
231 	m_sc3_tilemap->mark_tile_dirty(offset);
232 }
233 
234 /*******************************
235 *
236 * Tilemap info accesses
237 *
238 *******************************/
239 
TILE_GET_INFO_MEMBER(sengokmj_state::seibucrtc_sc0_tile_info)240 TILE_GET_INFO_MEMBER( sengokmj_state::seibucrtc_sc0_tile_info )
241 {
242 	int tile = m_sc0_vram[tile_index] & 0xfff;
243 	int color = (m_sc0_vram[tile_index] >> 12) & 0x0f;
244 //  tile+=(m_seibucrtc_sc0bank<<12);
245 	tileinfo.set(1, tile, color, 0);
246 }
247 
TILE_GET_INFO_MEMBER(sengokmj_state::seibucrtc_sc2_tile_info)248 TILE_GET_INFO_MEMBER( sengokmj_state::seibucrtc_sc2_tile_info )
249 {
250 	int tile = m_sc2_vram[tile_index] & 0xfff;
251 	int color = (m_sc2_vram[tile_index] >> 12) & 0x0f;
252 	tileinfo.set(2, tile, color, 0);
253 }
254 
TILE_GET_INFO_MEMBER(sengokmj_state::seibucrtc_sc1_tile_info)255 TILE_GET_INFO_MEMBER( sengokmj_state::seibucrtc_sc1_tile_info )
256 {
257 	int tile = m_sc1_vram[tile_index] & 0xfff;
258 	int color = (m_sc1_vram[tile_index] >> 12) & 0x0f;
259 	tileinfo.set(3, tile, color, 0);
260 }
261 
TILE_GET_INFO_MEMBER(sengokmj_state::seibucrtc_sc3_tile_info)262 TILE_GET_INFO_MEMBER( sengokmj_state::seibucrtc_sc3_tile_info )
263 {
264 	int tile = m_sc3_vram[tile_index] & 0xfff;
265 	int color = (m_sc3_vram[tile_index] >> 12) & 0x0f;
266 	tileinfo.set(4, tile, color, 0);
267 }
268 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,int pri)269 void sengokmj_state::draw_sprites(bitmap_ind16 &bitmap,const rectangle &cliprect,int pri)
270 {
271 	int offs,fx,fy,x,y,color,sprite;
272 	int dx,dy,ax,ay;
273 
274 	for (offs = 0x400-4;offs >= 0;offs -= 4)
275 	{
276 		if ((m_spriteram16[offs+0]&0x8000)!=0x8000) continue;
277 		sprite = m_spriteram16[offs+1];
278 		if ((sprite>>14)!=pri) continue;
279 		sprite &= 0x1fff;
280 
281 		y = m_spriteram16[offs+3];
282 		x = m_spriteram16[offs+2];
283 
284 		if (x&0x8000) x=0-(0x200-(x&0x1ff));
285 		else x&=0x1ff;
286 		if (y&0x8000) y=0-(0x200-(y&0x1ff));
287 		else y&=0x1ff;
288 
289 		color = m_spriteram16[offs+0]&0x3f;
290 		fx = m_spriteram16[offs+0]&0x4000;
291 		fy = m_spriteram16[offs+0]&0x2000;
292 		dy=((m_spriteram16[offs+0]&0x0380)>>7)+1;
293 		dx=((m_spriteram16[offs+0]&0x1c00)>>10)+1;
294 
295 		for (ax=0; ax<dx; ax++)
296 			for (ay=0; ay<dy; ay++) {
297 				if (!fx)
298 					m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
299 						sprite++,
300 						color,fx,fy,x+ax*16,y+ay*16,15);
301 				else
302 					m_gfxdecode->gfx(0)->transpen(bitmap,cliprect,
303 						sprite++,
304 						color,fx,fy,x+(dx-1-ax)*16,y+ay*16,15);
305 			}
306 	}
307 }
308 
video_start()309 void sengokmj_state::video_start()
310 {
311 	m_sc0_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sengokmj_state::seibucrtc_sc0_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
312 	m_sc2_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sengokmj_state::seibucrtc_sc2_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
313 	m_sc1_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sengokmj_state::seibucrtc_sc1_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32);
314 	m_sc3_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sengokmj_state::seibucrtc_sc3_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
315 
316 	m_sc2_tilemap->set_transparent_pen(15);
317 	m_sc1_tilemap->set_transparent_pen(15);
318 	m_sc3_tilemap->set_transparent_pen(15);
319 
320 	save_item(NAME(m_layer_en));
321 	save_item(NAME(m_scrollram));
322 }
323 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)324 uint32_t sengokmj_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
325 {
326 	bitmap.fill(m_palette->pen(0x7ff), cliprect); //black pen
327 
328 	/* TODO: offsetted? */
329 	m_sc0_tilemap->set_scrollx(0, (SEIBU_CRTC_SC0_SX + 128) & 0x1ff );
330 	m_sc0_tilemap->set_scrolly(0, (SEIBU_CRTC_SC0_SY) & 0x1ff );
331 	m_sc2_tilemap->set_scrollx(0, (SEIBU_CRTC_SC2_SX + 128) & 0x1ff );
332 	m_sc2_tilemap->set_scrolly(0, (SEIBU_CRTC_SC2_SY) & 0x1ff );
333 	m_sc1_tilemap->set_scrollx(0, (SEIBU_CRTC_SC1_SX + 128) & 0x1ff );
334 	m_sc1_tilemap->set_scrolly(0, (SEIBU_CRTC_SC1_SY) & 0x1ff );
335 	m_sc3_tilemap->set_scrollx(0, (128) & 0x1ff );
336 	m_sc3_tilemap->set_scrolly(0, (0) & 0x1ff );
337 
338 	if(SEIBU_CRTC_ENABLE_SC0) { m_sc0_tilemap->draw(screen, bitmap, cliprect, 0,0); }
339 	if(SEIBU_CRTC_ENABLE_SPR) { draw_sprites(bitmap,cliprect, 2); }
340 	if(SEIBU_CRTC_ENABLE_SC2) { m_sc2_tilemap->draw(screen, bitmap, cliprect, 0,0); }
341 	if(SEIBU_CRTC_ENABLE_SPR) { draw_sprites(bitmap,cliprect, 1); }
342 	if(SEIBU_CRTC_ENABLE_SC1) { m_sc1_tilemap->draw(screen, bitmap, cliprect, 0,0); }
343 	if(SEIBU_CRTC_ENABLE_SPR) { draw_sprites(bitmap,cliprect, 0); }
344 	if(SEIBU_CRTC_ENABLE_SC3) { m_sc3_tilemap->draw(screen, bitmap, cliprect, 0,0); }
345 	if(SEIBU_CRTC_ENABLE_SPR) { draw_sprites(bitmap,cliprect, 3); }
346 
347 	return 0;
348 }
349 
350 
machine_start()351 void sengokmj_state::machine_start()
352 {
353 	save_item(NAME(m_mux_data));
354 	save_item(NAME(m_hopper_io));
355 }
356 
357 
358 /* Multiplexer device for the mahjong panel */
mahjong_panel_r()359 uint16_t sengokmj_state::mahjong_panel_r()
360 {
361 	const char *const mpnames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5" };
362 	int i;
363 	uint16_t res = 0xffff;
364 
365 	for(i=0;i<5;i++)
366 	{
367 		if(m_mux_data & 1 << i)
368 			res = ioport(mpnames[i])->read();
369 	}
370 
371 	return res;
372 }
373 
mahjong_panel_w(uint16_t data)374 void sengokmj_state::mahjong_panel_w(uint16_t data)
375 {
376 	m_mux_data = (data & 0x3f00) >> 8;
377 
378 	if(data & 0xc0ff)
379 		logerror("Write to mux %04x\n",data);
380 }
381 
out_w(uint16_t data)382 void sengokmj_state::out_w(uint16_t data)
383 {
384 	/* ---- ---- ---x ---- J.P. Signal (?)*/
385 	/* ---- ---- ---- -x-- Coin counter (done AFTER you press start)*/
386 	/* ---- ---- ---- --x- Cash enable (lockout)*/
387 	/* ---- ---- ---- ---x Hopper 10 */
388 	machine().bookkeeping().coin_lockout_w(0,~data & 2);
389 	machine().bookkeeping().coin_lockout_w(1,~data & 2);
390 	machine().bookkeeping().coin_counter_w(0,data & 4);
391 	m_hopper_io = ((data & 1)<<6);
392 //  popmessage("%02x",m_hopper_io);
393 }
394 
system_r()395 uint16_t sengokmj_state::system_r()
396 {
397 	return (ioport("SYSTEM")->read() & 0xffbf) | m_hopper_io;
398 }
399 
sengokmj_map(address_map & map)400 void sengokmj_state::sengokmj_map(address_map &map)
401 {
402 	map(0x00000, 0x07fff).ram();
403 	map(0x08000, 0x09fff).ram().share("nvram");
404 	map(0x0c000, 0x0c7ff).ram().w(FUNC(sengokmj_state::seibucrtc_sc0vram_w)).share("sc0_vram");
405 	map(0x0c800, 0x0cfff).ram().w(FUNC(sengokmj_state::seibucrtc_sc1vram_w)).share("sc1_vram");
406 	map(0x0d000, 0x0d7ff).ram().w(FUNC(sengokmj_state::seibucrtc_sc2vram_w)).share("sc2_vram");
407 	map(0x0d800, 0x0e7ff).ram().w(FUNC(sengokmj_state::seibucrtc_sc3vram_w)).share("sc3_vram");
408 	map(0x0e800, 0x0f7ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
409 	map(0x0f800, 0x0ffff).ram().share("sprite_ram");
410 	map(0xc0000, 0xfffff).rom();
411 }
412 
sengokmj_io_map(address_map & map)413 void sengokmj_state::sengokmj_io_map(address_map &map)
414 {
415 	map(0x4000, 0x400f).rw("seibu_sound", FUNC(seibu_sound_device::main_r), FUNC(seibu_sound_device::main_w)).umask16(0x00ff);
416 	/*Areas from 8000-804f are for the custom Seibu CRTC.*/
417 	map(0x8000, 0x804f).rw("crtc", FUNC(seibu_crtc_device::read), FUNC(seibu_crtc_device::write));
418 
419 //  map(0x8080, 0x8081) CRTC extra register?
420 //  map(0x80c0, 0x80c1) CRTC extra register?
421 //  map(0x8100, 0x8101).nopw(); // always 0
422 	map(0x8180, 0x8181).w(FUNC(sengokmj_state::out_w));
423 	map(0x8140, 0x8141).w(FUNC(sengokmj_state::mahjong_panel_w));
424 	map(0xc000, 0xc001).portr("DSW");
425 	map(0xc002, 0xc003).r(FUNC(sengokmj_state::mahjong_panel_r));
426 	map(0xc004, 0xc005).r(FUNC(sengokmj_state::system_r)); //switches
427 }
428 
429 
430 static INPUT_PORTS_START( sengokmj )
431 	SEIBU_COIN_INPUTS   /* coin inputs read through sound cpu */
432 
433 	PORT_START("DSW") // Names and locations from service mode
434 	PORT_DIPNAME( 0x0001, 0x0000, DEF_STR( Demo_Sounds ) )  PORT_DIPLOCATION("SW1:1")
435 	PORT_DIPSETTING(      0x0001, DEF_STR( Off ) )
436 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
437 	PORT_DIPNAME( 0x0002, 0x0002, "Re-start" )  PORT_DIPLOCATION("SW1:2")
438 	PORT_DIPSETTING(      0x0002, DEF_STR( Off ) )
439 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
440 	PORT_DIPNAME( 0x0004, 0x0004, "Double G" )  PORT_DIPLOCATION("SW1:3")
441 	PORT_DIPSETTING(      0x0004, DEF_STR( Off ) )
442 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
443 	PORT_DIPNAME( 0x0008, 0x0008, "Double L" )  PORT_DIPLOCATION("SW1:4")
444 	PORT_DIPSETTING(      0x0008, DEF_STR( Off ) )
445 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
446 	PORT_DIPNAME( 0x0010, 0x0010, "Kamon" )  PORT_DIPLOCATION("SW1:5")
447 	PORT_DIPSETTING(      0x0010, DEF_STR( Off ) )
448 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
449 	PORT_DIPUNUSED_DIPLOC( 0x0020, 0x0020, "SW1:6" )
450 	PORT_DIPNAME( 0x0040, 0x0040, "Out Sw" ) PORT_DIPLOCATION("SW1:7")
451 	PORT_DIPSETTING(      0x0040, DEF_STR( Off ) ) // One of these probably selects coins
452 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) ) // The other probably selects tickets
453 	PORT_DIPNAME( 0x0080, 0x0000, "Hopper" ) PORT_DIPLOCATION("SW1:8") //game gives hopper error with this off.
454 	PORT_DIPSETTING(      0x0080, DEF_STR( Off ) )
455 	PORT_DIPSETTING(      0x0000, DEF_STR( On ) )
456 	PORT_DIPUNUSED_DIPLOC( 0x0100, 0x0100, "SW2:1" )
457 	PORT_DIPUNUSED_DIPLOC( 0x0200, 0x0200, "SW2:2" )
458 	PORT_DIPUNUSED_DIPLOC( 0x0400, 0x0400, "SW2:3" )
459 	PORT_DIPUNUSED_DIPLOC( 0x0800, 0x0800, "SW2:4" )
460 	PORT_DIPUNUSED_DIPLOC( 0x1000, 0x1000, "SW2:5" )
461 	PORT_DIPUNUSED_DIPLOC( 0x2000, 0x2000, "SW2:6" )
462 	PORT_DIPUNUSED_DIPLOC( 0x4000, 0x4000, "SW2:7" )
463 	PORT_DIPUNUSED_DIPLOC( 0x8000, 0x8000, "SW2:8" )
464 
465 	PORT_START("KEY0")
466 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_MAHJONG_A ) // Internal code 0F0h
467 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MAHJONG_E ) // Internal code 0F4h
468 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_MAHJONG_I ) // Internal code 0F8h
469 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_MAHJONG_M ) // Internal code 0FCh
470 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_MAHJONG_KAN ) // Internal code 3h
471 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_START1 ) // Internal code 0Ah
472 	PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Bet 2") PORT_CODE(KEYCODE_4) // Internal code 0FFFFh; ignored in service mode but probably does something
473 	PORT_BIT( 0xff80, IP_ACTIVE_LOW, IPT_UNUSED )
474 
475 	PORT_START("KEY1")
476 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_MAHJONG_B ) // Internal code 0F1h
477 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MAHJONG_F ) // Internal code 0F5h
478 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_MAHJONG_J ) // Internal code 0F9h
479 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_MAHJONG_N ) // Internal code 0FBh
480 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_MAHJONG_REACH ) // Internal code 0Bh
481 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_MAHJONG_BET ) // Internal code 9h
482 	PORT_BIT( 0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )
483 
484 	PORT_START("KEY2")
485 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_MAHJONG_C ) // Internal code 0F2h
486 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MAHJONG_G ) // Internal code 0F6h
487 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_MAHJONG_K ) // Internal code 0FAh
488 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_MAHJONG_CHI ) // Internal code 1h
489 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_MAHJONG_RON ) // Internal code 0Ch
490 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
491 	PORT_BIT( 0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )
492 
493 	PORT_START("KEY3")
494 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_MAHJONG_D ) // Internal code 0F3h
495 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MAHJONG_H ) // Internal code 0F7h
496 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_MAHJONG_L ) // Internal code 0FBh
497 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_MAHJONG_PON ) // Internal code 2h
498 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN ) // Internal code 6h; not shown in service mode and probably does nothing
499 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
500 	PORT_BIT( 0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )
501 
502 	PORT_START("KEY4")
503 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_MAHJONG_LAST_CHANCE ) // Internal code 4h
504 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MAHJONG_SCORE ) // Internal code 8h
505 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_MAHJONG_DOUBLE_UP ) // Internal code 7h
506 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )
507 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Show Checksum") PORT_CODE(KEYCODE_X) // Internal code 5h; not shown in service mode but certainly does something
508 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
509 	PORT_BIT( 0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )
510 
511 	PORT_START("KEY5")
512 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED )
513 	PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED )
514 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_UNUSED )
515 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED )
516 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNUSED )
517 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED )
518 	PORT_BIT( 0xffc0, IP_ACTIVE_LOW, IPT_UNUSED )
519 
520 	PORT_START("SYSTEM")
521 	PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_GAMBLE_DOOR ) // Only used in service mode?
522 	PORT_SERVICE_NO_TOGGLE( 0x0002, IP_ACTIVE_LOW )
523 	PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_SERVICE4 ) PORT_NAME("Opt. 1st") // Only used in service mode?
524 	PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_MEMORY_RESET )
525 	PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNUSED )
526 	PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_NAME("Cash") // Only used in service mode?
527 //  0x40 Hopper
528 	PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_NAME("Meter")
529 	PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED )
530 INPUT_PORTS_END
531 
532 
533 static const gfx_layout tilelayout =
534 {
535 	16,16,  /* 16*16 sprites  */
536 	RGN_FRAC(1,1),
537 	4,  /* 4 bits per pixel */
538 	{ 8, 12, 0, 4 },
539 	{ 3, 2, 1, 0, 16+3, 16+2, 16+1, 16+0,
540 				3+32*16, 2+32*16, 1+32*16, 0+32*16, 16+3+32*16, 16+2+32*16, 16+1+32*16, 16+0+32*16 },
541 	{ 0*16, 2*16, 4*16, 6*16, 8*16, 10*16, 12*16, 14*16,
542 			16*16, 18*16, 20*16, 22*16, 24*16, 26*16, 28*16, 30*16 },
543 	128*8   /* every sprite takes 128 consecutive bytes */
544 };
545 
546 static const gfx_layout charlayout =
547 {
548 	8,8,
549 	RGN_FRAC(1,1),
550 	4,  /* 4 bits per pixel */
551 	{ 8, 12, 0, 4 },
552 	{ 3, 2, 1, 0, 16+3, 16+2, 16+1, 16+0 },
553 	{ 0*16, 2*16, 4*16, 6*16, 8*16, 10*16, 12*16, 14*16 },
554 	128*8   /* every sprite takes 128 consecutive bytes */
555 };
556 
557 static GFXDECODE_START( gfx_sengokmj )
558 	GFXDECODE_ENTRY( "spr_gfx",0, tilelayout, 0x000, 0x40 ) /* Sprites */
559 	GFXDECODE_ENTRY( "bg_gfx", 0, tilelayout, 0x400, 0x10 ) /* Tiles */
560 	GFXDECODE_ENTRY( "md_gfx", 0, tilelayout, 0x500, 0x10 ) /* Tiles */
561 	GFXDECODE_ENTRY( "fg_gfx", 0, tilelayout, 0x600, 0x10 ) /* Tiles */
562 	GFXDECODE_ENTRY( "tx_gfx", 0, charlayout, 0x700, 0x10 ) /* Text */
563 GFXDECODE_END
564 
WRITE_LINE_MEMBER(sengokmj_state::vblank_irq)565 WRITE_LINE_MEMBER(sengokmj_state::vblank_irq)
566 {
567 	if (state)
568 		m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xc8/4); // V30
569 }
570 
layer_en_w(uint16_t data)571 void sengokmj_state::layer_en_w(uint16_t data)
572 {
573 	m_layer_en = data;
574 }
575 
layer_scroll_w(offs_t offset,uint16_t data,uint16_t mem_mask)576 void sengokmj_state::layer_scroll_w(offs_t offset, uint16_t data, uint16_t mem_mask)
577 {
578 	COMBINE_DATA(&m_scrollram[offset]);
579 }
580 
581 
sengokmj(machine_config & config)582 void sengokmj_state::sengokmj(machine_config &config)
583 {
584 	/* basic machine hardware */
585 	V30(config, m_maincpu, 16000000/2); /* V30-8 */
586 	m_maincpu->set_addrmap(AS_PROGRAM, &sengokmj_state::sengokmj_map);
587 	m_maincpu->set_addrmap(AS_IO, &sengokmj_state::sengokmj_io_map);
588 
589 	z80_device &audiocpu(Z80(config, "audiocpu", 14318180/4));
590 	audiocpu.set_addrmap(AS_PROGRAM, &sengokmj_state::seibu_sound_map);
591 	audiocpu.set_irq_acknowledge_callback("seibu_sound", FUNC(seibu_sound_device::im0_vector_cb));
592 
593 	NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
594 
595 	/* video hardware */
596 	screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
597 	screen.set_refresh_hz(60);
598 	screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
599 	screen.set_size(64*8, 32*8);
600 	screen.set_visarea(0, 320-1, 16, 256-1); //TODO: dynamic resolution
601 	screen.set_screen_update(FUNC(sengokmj_state::screen_update));
602 	screen.set_palette(m_palette);
603 	screen.screen_vblank().set(FUNC(sengokmj_state::vblank_irq));
604 
605 	seibu_crtc_device &crtc(SEIBU_CRTC(config, "crtc", 0));
606 	crtc.layer_en_callback().set(FUNC(sengokmj_state::layer_en_w));
607 	crtc.layer_scroll_callback().set(FUNC(sengokmj_state::layer_scroll_w));
608 
609 	GFXDECODE(config, m_gfxdecode, m_palette, gfx_sengokmj);
610 	PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 0x800);
611 
612 	/* sound hardware */
613 	SPEAKER(config, "mono").front_center();
614 
615 	ym3812_device &ymsnd(YM3812(config, "ymsnd", 14318180/4));
616 	ymsnd.irq_handler().set("seibu_sound", FUNC(seibu_sound_device::fm_irqhandler));
617 	ymsnd.add_route(ALL_OUTPUTS, "mono", 1.0);
618 
619 	okim6295_device &oki(OKIM6295(config, "oki", 1320000, okim6295_device::PIN7_LOW));
620 	oki.add_route(ALL_OUTPUTS, "mono", 0.40);
621 
622 	seibu_sound_device &seibu_sound(SEIBU_SOUND(config, "seibu_sound", 0));
623 	seibu_sound.int_callback().set_inputline("audiocpu", 0);
624 	seibu_sound.set_rom_tag("audiocpu");
625 	seibu_sound.set_rombank_tag("seibu_bank1");
626 	seibu_sound.ym_read_callback().set("ymsnd", FUNC(ym3812_device::read));
627 	seibu_sound.ym_write_callback().set("ymsnd", FUNC(ym3812_device::write));
628 }
629 
630 
631 ROM_START( sengokmj )
632 	ROM_REGION( 0x100000, "maincpu", 0 ) /* V30 code */
633 	ROM_LOAD16_BYTE( "mm01-1-1.21",  0xc0000, 0x20000, CRC(74076b46) SHA1(64b0ed5a8c32e21157ae12fe40519e4c605b329c) )
634 	ROM_LOAD16_BYTE( "mm01-2-1.24",  0xc0001, 0x20000, CRC(f1a7c131) SHA1(d0fbbdedbff8f05da0e0296baa41369bc41a67e4) )
635 
636 	ROM_REGION( 0x20000, "audiocpu", 0 ) /* 64k code for sound Z80 */
637 	ROM_LOAD( "mah1-2-1.013", 0x000000, 0x08000, CRC(6a4f31b8) SHA1(5e1d7ed299c1fd65c7a43faa02831220f4251733) )
638 	ROM_CONTINUE(             0x010000, 0x08000 )
639 	ROM_COPY( "audiocpu", 0x000000,     0x018000, 0x08000 )
640 
641 	ROM_REGION( 0x100000, "spr_gfx", 0 ) /*Sprites gfx rom*/
642 	ROM_LOAD( "rssengo2.72", 0x00000, 0x100000, CRC(fb215ff8) SHA1(f98c0a53ad9b97d209dd1f85c994fc17ec585bd7) )
643 
644 	ROM_REGION( 0x200000, "gfx_tiles", 0 ) /*Tiles data,to be reloaded*/
645 	ROM_LOAD( "rssengo0.64", 0x000000, 0x100000, CRC(36924b71) SHA1(814b2c69ab9876ccc57774e5718c05059ea23150) )
646 	ROM_LOAD( "rssengo1.68", 0x100000, 0x100000, CRC(1bbd00e5) SHA1(86391323b8e0d3b7e09a5914d87fb2adc48e5af4) )
647 
648 	ROM_REGION( 0x080000, "bg_gfx", 0 )
649 	ROM_COPY( "gfx_tiles" , 0x000000, 0x00000, 0x080000)
650 
651 	ROM_REGION( 0x080000, "md_gfx", 0 )
652 	ROM_COPY( "gfx_tiles" , 0x080000, 0x00000, 0x080000)
653 
654 	ROM_REGION( 0x080000, "fg_gfx", 0 )
655 	ROM_COPY( "gfx_tiles" , 0x100000, 0x00000, 0x080000)
656 
657 	ROM_REGION( 0x080000, "tx_gfx", 0 )
658 	ROM_COPY( "gfx_tiles" , 0x180000, 0x00000, 0x080000)
659 
660 	ROM_REGION( 0x40000, "oki", 0 )  /* ADPCM samples */
661 	ROM_LOAD( "mah1-1-1.915", 0x00000, 0x20000, CRC(d4612e95) SHA1(937c5dbd25c89d4f4178b0bed510307020c5f40e) )
662 
663 	ROM_REGION( 0x200, "user1", 0 ) /* not used */
664 	ROM_LOAD( "rs006.89", 0x000, 0x200, CRC(96f7646e) SHA1(400a831b83d6ac4d2a46ef95b97b1ee237099e44) ) /* Priority */
665 ROM_END
666 
667 GAME( 1991, sengokmj, 0, sengokmj, sengokmj, sengokmj_state, empty_init, ROT0, "Sigma", "Sengoku Mahjong [BET] (Japan)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_SUPPORTS_SAVE )
668 /*Non-Bet Version?*/
669