diff options
Diffstat (limited to 'trunk/src/mame/drivers/ddealer.c')
-rw-r--r-- | trunk/src/mame/drivers/ddealer.c | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/ddealer.c b/trunk/src/mame/drivers/ddealer.c new file mode 100644 index 00000000000..3e81e0225a3 --- /dev/null +++ b/trunk/src/mame/drivers/ddealer.c @@ -0,0 +1,696 @@ +/* +Double Dealer (c)NMK 1991 + +driver by Angelo Salese & David Haywood,based on early work by Tomasz Slanina + +Appears to be a down-grade of the nmk16 HW + +TODO: +-When you use the "gun card" the game gives "minus" points,but points are always added,inaccurate protection? +-Understand better the video emulation and convert it to tilemaps; +-A Double Dealer manual is needed for the coinage settings and coin/credit simulation; +-Decap + emulate MCU, required if the random number generation is going to be accurate; + +-- + +pcb marked GD91071 + +68000P10 +YM2203C +91071-3 (Mask ROM) +NMK-110 8131 ( Mitsubishi M50747 MCU ?) +NMK 901 +NMK 902 +NMK 903 x2 +82S135N ("5") +82S129N ("6") +xtals 16.000 MHz and 6.000 MHz +DSW x2 + +-- + +Few words about protection: + +- Work RAM at $fe000 - $fffff is shared with MCU . Maybe whole $f0000-$fffff is shared ... +- After boot, game writes random-looking data to work RAM: + + 00052C: 33FC 1234 000F E086 move.w #$1234, $fe086.l + 000534: 33FC 5678 000F E164 move.w #$5678, $fe164.l + 00053C: 33FC 9CA3 000F E62E move.w #$9ca3, $fe62e.l + 000544: 33FC ABA2 000F E734 move.w #$aba2, $fe734.l + 00054C: 33FC B891 000F E828 move.w #$b891, $fe828.l + 000554: 33FC C760 000F E950 move.w #$c760, $fe950.l + 00055C: 33FC D45F 000F EA7C move.w #$d45f, $fea7c.l + 000564: 33FC E32E 000F ED4A move.w #$e32e, $fed4a.l + + Some (or maybe all ?) of above enables random generator at $fe010 - $fe017 + +- There's also MCU response (write/read/test) test just after these writes. + (probably data used in the check depends on above writes). It's similar to + jalmah.c tests, but num of responses is different, and shared ram is + used to communicate with MCU + +- After last check (or maybe durning tests ... no idea) + MCU writes $4ef900000604 (jmp $604) to $fe000 and game jumps to this address. + +- code at $604 writes $20.w to $fe018 and $1.w to $fe01e. + As result shared ram $fe000 - $fe007 is cleared. + + Also many, many other reads/writes from/to shared mem. + Few checks every interrupt: + + interrupt, lvl1 + + 000796: 007C 0700 ori #$700, SR + 00079A: 48E7 FFFE movem.l D0-D7/A0-A6, -(A7) + 00079E: 33FC 0001 000F E006 move.w #$1, $fe006.l ; shared ram W (watchdog ?) + 0007A6: 4A79 000F E000 tst.w $fe000.l ; shared ram R + 0007AC: 6600 0012 bne $7c0 + 0007B0: 4A79 000F 02FE tst.w $f02fe.l + 0007B6: 6600 0008 bne $7c0 + 0007BA: 4279 000F C880 clr.w $fc880.l ++-0007C0: 6100 0236 bsr $9f8 +| 0007C4: 4EB9 0003 0056 jsr $30056.l +| 0007CA: 33FC 00FF 000F C880 move.w #$ff, $fc880.l +| 0007D2: 007C 2000 ori #$2000, SR +| 0007D6: 4CDF 7FFF movem.l (A7)+, D0-D7/A0-A6 +| 0007DA: 4E73 rte +| +| ++->0009F8: 4A79 000F 02C0 tst.w $f02c0.l + 0009FE: 6700 0072 beq $a72 + 000A02: 4A79 000F 02F6 tst.w $f02f6.l + 000A08: 6600 0068 bne $a72 + 000A0C: 3439 000F E002 move.w $fe002.l, D2 ; shared ram R + 000A12: 3602 move.w D2, D3 + 000A14: 0242 00FF andi.w #$ff, D2 + 000A18: 0243 FF00 andi.w #$ff00, D3 + 000A1C: E04B lsr.w #8, D3 + 000A1E: 3039 000F E000 move.w $fe000.l, D0 ; shared ram R + 000A24: 3239 000F 0010 move.w $f0010.l, D1 + 000A2A: B041 cmp.w D1, D0 + 000A2C: 6200 002A bhi $a58 + 000A30: 6600 002E bne $a60 + 000A34: 3039 000F 0012 move.w $f0012.l, D0 + 000A3A: B440 cmp.w D0, D2 + 000A3C: 6200 001A bhi $a58 + 000A40: 6600 001E bne $a60 + 000A44: 3039 000F 0014 move.w $f0014.l, D0 + 000A4A: B640 cmp.w D0, D3 + 000A4C: 6200 000A bhi $a58 + 000A50: 6600 000E bne $a60 + 000A54: 6000 001C bra $a72 + 000A58: 33FC 0007 000F C880 move.w #$7, $fc880.l ; used later in the code... + 000A60: 33C0 000F 0010 move.w D0, $f0010.l ;update mem, used in next test + 000A66: 33C2 000F 0012 move.w D2, $f0012.l + 000A6C: 33C3 000F 0014 move.w D3, $f0014.l + 000A72: 4E75 rts + +*/ + + +#include "emu.h" +#include "cpu/m68000/m68000.h" +#include "sound/2203intf.h" + +class ddealer_state : public driver_device +{ +public: + ddealer_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) { } + + /* memory pointers */ + UINT16 * m_mcu_shared_ram; + UINT16 * m_work_ram; + UINT16 * m_back_vram; + UINT16 * m_left_fg_vram_top; + UINT16 * m_right_fg_vram_top; + UINT16 * m_left_fg_vram_bottom; + UINT16 * m_right_fg_vram_bottom; + UINT16 * m_vregs; +// UINT16 * m_paletteram16; // currently this uses generic palette handling + + /* video-related */ + tilemap_t *m_back_tilemap; + int m_respcount; + int m_flipscreen; + + /* misc */ + UINT8 m_input_pressed; + UINT16 m_coin_input; +}; + + + +static WRITE16_HANDLER( ddealer_flipscreen_w ) +{ + ddealer_state *state = space->machine().driver_data<ddealer_state>(); + state->m_flipscreen = data & 0x01; +} + +static TILE_GET_INFO( get_back_tile_info ) +{ + ddealer_state *state = machine.driver_data<ddealer_state>(); + int code = state->m_back_vram[tile_index]; + SET_TILE_INFO( + 0, + code & 0xfff, + code >> 12, + 0); +} + +static VIDEO_START( ddealer ) +{ + ddealer_state *state = machine.driver_data<ddealer_state>(); + state->m_flipscreen = 0; + state->m_back_tilemap = tilemap_create(machine, get_back_tile_info, tilemap_scan_cols, 8, 8, 64, 32); +} + +static void ddealer_draw_video_layer( running_machine &machine, UINT16* vreg_base, UINT16* top, UINT16* bottom, bitmap_t* bitmap, const rectangle *cliprect, int flipy) +{ + const gfx_element *gfx = machine.gfx[1]; + + INT16 sx, sy; + int x,y, count; + UINT16* src; + + sx = ((vreg_base[0x4 / 2] & 0xff)); + sx |= ((vreg_base[0x2 / 2] & 0xff) << 8); + + sx &= 0x7ff; + if (sx & 0x400) sx -= 0x800; + + sy = ((vreg_base[0x8 / 2] & 0xff)); + sy |= ((vreg_base[0x6 / 2] & 0xff) << 8); + + if (!flipy) + { + sx -= 64; // video shift + + /* the tilemaps seems to be split into top / bottom pieces */ + count = 0; + src = top; + for (x = 0; x < 128; x++) + { + for (y = 0; y < 16; y++) + { + UINT16 tile = (src[count] & 0x0fff); + UINT16 colr = (src[count] & 0xf000) >> 12; + count++; + drawgfx_transpen(bitmap, cliprect, gfx, tile, colr, 0, flipy, (x * 16) - sx, (y * 16) - sy, 15); + } + } + count = 0; + src = bottom; + sy -= 256; + for (x = 0; x < 128; x++) + { + for (y = 0; y < 16; y++) + { + UINT16 tile = (src[count] & 0x0fff); + UINT16 colr = (src[count] & 0xf000) >> 12; + count++; + drawgfx_transpen(bitmap, cliprect, gfx, tile, colr, 0, flipy, (x * 16) - sx, (y * 16) - sy, 15); + } + } + } + else + { + sx -= 0x6d0; + sy -= 16; + + /* the tilemaps seems to be split into top / bottom pieces */ + count = 0; + src = top; + for (x = 128; x > 0; x--) + { + for (y = 16; y > 0; y--) + { + UINT16 tile = (src[count] & 0x0fff); + UINT16 colr = (src[count] & 0xf000) >> 12; + count++; + drawgfx_transpen(bitmap, cliprect, gfx, tile, colr, flipy, flipy, (x * 16) + sx, (y * 16) + sy, 15); + } + } + count = 0; + src = bottom; + sy -= 256; + for (x = 128; x > 0; x--) + { + for (y = 16; y > 0; y--) + { + UINT16 tile = (src[count] & 0x0fff); + UINT16 colr = (src[count] & 0xf000) >> 12; + count++; + drawgfx_transpen(bitmap, cliprect, gfx, tile, colr, flipy, flipy, (x * 16) + sx, (y * 16) + sy, 15); + } + } + } +} + + +static SCREEN_UPDATE( ddealer ) +{ + ddealer_state *state = screen->machine().driver_data<ddealer_state>(); + tilemap_set_scrollx(state->m_back_tilemap, 0, state->m_flipscreen ? -192 : -64); + tilemap_set_flip(state->m_back_tilemap, state->m_flipscreen ? TILEMAP_FLIPY | TILEMAP_FLIPX : 0); + tilemap_draw(bitmap, cliprect, state->m_back_tilemap, 0, 0); + + /* the fg tilemap handling is a little hacky right now, + i'm not sure if it should be a single tilemap with + rowscroll / linescroll, or two tilemaps which can be + combined, the flipscreen case makes things more + difficult to understand */ + + if (!state->m_flipscreen) + { + if (state->m_vregs[0xcc / 2] & 0x80) + { + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0x1e0 / 2], state->m_left_fg_vram_top, state->m_left_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0xcc / 2], state->m_right_fg_vram_top, state->m_right_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + } + else + { + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0x1e0 / 2], state->m_left_fg_vram_top, state->m_left_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + } + } + else + { + if (state->m_vregs[0xcc / 2] & 0x80) + { + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0xcc / 2], state->m_left_fg_vram_top, state->m_left_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0x1e0 / 2], state->m_right_fg_vram_top, state->m_right_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + } + else + { + ddealer_draw_video_layer(screen->machine(), &state->m_vregs[0x1e0 / 2], state->m_left_fg_vram_top, state->m_left_fg_vram_bottom, bitmap, cliprect, state->m_flipscreen); + } + + } + + return 0; +} + +static TIMER_DEVICE_CALLBACK( ddealer_mcu_sim ) +{ + ddealer_state *state = timer.machine().driver_data<ddealer_state>(); + + /*coin/credit simulation*/ + /*$fe002 is used,might be for multiple coins for one credit settings.*/ + state->m_coin_input = (~(input_port_read(timer.machine(), "IN0"))); + + if (state->m_coin_input & 0x01)//coin 1 + { + if((state->m_input_pressed & 0x01) == 0) + state->m_mcu_shared_ram[0x000 / 2]++; + state->m_input_pressed = (state->m_input_pressed & 0xfe) | 1; + } + else + state->m_input_pressed = (state->m_input_pressed & 0xfe); + + if (state->m_coin_input & 0x02)//coin 2 + { + if ((state->m_input_pressed & 0x02) == 0) + state->m_mcu_shared_ram[0x000 / 2]++; + state->m_input_pressed = (state->m_input_pressed & 0xfd) | 2; + } + else + state->m_input_pressed = (state->m_input_pressed & 0xfd); + + if (state->m_coin_input & 0x04)//service 1 + { + if ((state->m_input_pressed & 0x04) == 0) + state->m_mcu_shared_ram[0x000 / 2]++; + state->m_input_pressed = (state->m_input_pressed & 0xfb) | 4; + } + else + state->m_input_pressed = (state->m_input_pressed & 0xfb); + + /*0x104/2 is some sort of "start-lock",i.e. used on the girl selection. + Without it,the game "steals" one credit if you press the start button on that.*/ + if (state->m_mcu_shared_ram[0x000 / 2] > 0 && state->m_work_ram[0x104 / 2] & 1) + { + if (state->m_coin_input & 0x08)//start 1 + { + if ((state->m_input_pressed & 0x08) == 0 && (~(state->m_work_ram[0x100 / 2] & 1))) + state->m_mcu_shared_ram[0x000 / 2]--; + state->m_input_pressed = (state->m_input_pressed & 0xf7) | 8; + } + else + state->m_input_pressed = (state->m_input_pressed & 0xf7); + + if (state->m_coin_input & 0x10)//start 2 + { + if((state->m_input_pressed & 0x10) == 0 && (~(state->m_work_ram[0x100 / 2] & 2))) + state->m_mcu_shared_ram[0x000 / 2]--; + state->m_input_pressed = (state->m_input_pressed & 0xef) | 0x10; + } + else + state->m_input_pressed = (state->m_input_pressed & 0xef); + } + + /*random number generators,controls order of cards*/ + state->m_mcu_shared_ram[0x10 / 2] = timer.machine().rand() & 0xffff; + state->m_mcu_shared_ram[0x12 / 2] = timer.machine().rand() & 0xffff; + state->m_mcu_shared_ram[0x14 / 2] = timer.machine().rand() & 0xffff; + state->m_mcu_shared_ram[0x16 / 2] = timer.machine().rand() & 0xffff; +} + + + +static WRITE16_HANDLER( back_vram_w ) +{ + ddealer_state *state = space->machine().driver_data<ddealer_state>(); + COMBINE_DATA(&state->m_back_vram[offset]); + tilemap_mark_tile_dirty(state->m_back_tilemap, offset); +} + + +static WRITE16_HANDLER( ddealer_vregs_w ) +{ + ddealer_state *state = space->machine().driver_data<ddealer_state>(); + COMBINE_DATA(&state->m_vregs[offset]); +} + +/****************************************************************************************************** + +Protection handling,identical to Hacha Mecha Fighter / Thunder Dragon with different vectors. + +******************************************************************************************************/ + +#define PROT_JSR(_offs_,_protvalue_,_pc_) \ + if(state->m_mcu_shared_ram[(_offs_)/2] == _protvalue_) \ + { \ + state->m_mcu_shared_ram[(_offs_)/2] = 0xffff; /*(MCU job done)*/ \ + state->m_mcu_shared_ram[(_offs_+2-0x10)/2] = 0x4ef9;/*JMP*/\ + state->m_mcu_shared_ram[(_offs_+4-0x10)/2] = 0x0000;/*HI-DWORD*/\ + state->m_mcu_shared_ram[(_offs_+6-0x10)/2] = _pc_; /*LO-DWORD*/\ + } \ + +#define PROT_INPUT(_offs_,_protvalue_,_protinput_,_input_) \ + if(state->m_mcu_shared_ram[_offs_] == _protvalue_) \ + {\ + state->m_mcu_shared_ram[_protinput_] = ((_input_ & 0xffff0000)>>16);\ + state->m_mcu_shared_ram[_protinput_+1] = (_input_ & 0x0000ffff);\ + } + +static WRITE16_HANDLER( ddealer_mcu_shared_w ) +{ + ddealer_state *state = space->machine().driver_data<ddealer_state>(); + COMBINE_DATA(&state->m_mcu_shared_ram[offset]); + + switch(offset) + { + case 0x086/2: PROT_INPUT(0x086/2,0x1234,0x100/2,0x80000); break; + case 0x164/2: PROT_INPUT(0x164/2,0x5678,0x104/2,0x80002); break; + case 0x62e/2: PROT_INPUT(0x62e/2,0x9ca3,0x108/2,0x80008); break; + case 0x734/2: PROT_INPUT(0x734/2,0xaba2,0x10c/2,0x8000a); break; +/*These enables something for sure,maybe the random number generator?*/ + //00054C: 33FC B891 000F E828 move.w #$b891, $fe828.l + //000554: 33FC C760 000F E950 move.w #$c760, $fe950.l + //00055C: 33FC D45F 000F EA7C move.w #$d45f, $fea7c.l + //000564: 33FC E32E 000F ED4A move.w #$e32e, $fed4a.l + + case 0x40e/2: PROT_JSR(0x40e,0x8011,0x6992); break;//score + case 0x41e/2: break;//unused + case 0x42e/2: PROT_JSR(0x42e,0x8007,0x6004); break;//cards on playfield/hand (ram side) + case 0x43e/2: PROT_JSR(0x43e,0x801d,0x6176); break;//second player sub-routine + case 0x44e/2: PROT_JSR(0x44e,0x8028,0x6932); break;//"gun card" logic + case 0x45e/2: PROT_JSR(0x45e,0x803e,0x6f90); break;//card delete + case 0x46e/2: PROT_JSR(0x46e,0x8033,0x93c2); break;//card movements + case 0x47e/2: PROT_JSR(0x47e,0x8026,0x67a0); break;//cards on playfield (vram side) + case 0x48e/2: PROT_JSR(0x48e,0x8012,0x6824); break;//cards on hand (vram side) + case 0x49e/2: PROT_JSR(0x49e,0x8004,0x9696); break;//write to text layer + case 0x4ae/2: PROT_JSR(0x4ae,0x8035,0x95fe); break;//write to scroll layer + case 0x4be/2: PROT_JSR(0x4be,0x8009,0x9634); break;//show girls sub-routine + case 0x4ce/2: PROT_JSR(0x4ce,0x802a,0x9656); break; + case 0x4de/2: PROT_JSR(0x4de,0x803b,0x96c2); break; + case 0x4ee/2: PROT_JSR(0x4ee,0x800c,0x5ca4); break;//palette ram buffer + case 0x4fe/2: PROT_JSR(0x4fe,0x8018,0x9818); break; + /*Start-up vector,I think that only the first ram address can be written by the main CPU,or it is a whole sequence.*/ + case 0x000/2: + if (state->m_mcu_shared_ram[0x000 / 2] == 0x60fe) + { + state->m_mcu_shared_ram[0x000 / 2] = 0x0000;//coin counter + state->m_mcu_shared_ram[0x002 / 2] = 0x0000;//coin counter "decimal point" + state->m_mcu_shared_ram[0x004 / 2] = 0x4ef9; + } + break; + case 0x002/2: + case 0x004/2: + if (state->m_mcu_shared_ram[0x002 / 2] == 0x0000 && state->m_mcu_shared_ram[0x004 / 2] == 0x0214) + state->m_mcu_shared_ram[0x004 / 2] = 0x4ef9; + break; + case 0x008/2: + if (state->m_mcu_shared_ram[0x008 / 2] == 0x000f) + state->m_mcu_shared_ram[0x008 / 2] = 0x0604; + break; + case 0x00c/2: + if (state->m_mcu_shared_ram[0x00c / 2] == 0x000f) + state->m_mcu_shared_ram[0x00c / 2] = 0x0000; + break; + } +} + +static ADDRESS_MAP_START( ddealer, AS_PROGRAM, 16 ) + AM_RANGE(0x000000, 0x03ffff) AM_ROM + AM_RANGE(0x080000, 0x080001) AM_READ_PORT("IN0") + AM_RANGE(0x080002, 0x080003) AM_READ_PORT("IN1") + AM_RANGE(0x080008, 0x080009) AM_READ_PORT("DSW1") + AM_RANGE(0x08000a, 0x08000b) AM_READ_PORT("UNK") + AM_RANGE(0x084000, 0x084003) AM_DEVWRITE8("ymsnd", ym2203_w, 0x00ff) // ym ? + AM_RANGE(0x088000, 0x0887ff) AM_RAM_WRITE(paletteram16_RRRRGGGGBBBBRGBx_word_w) AM_BASE_GENERIC(paletteram) // palette ram + AM_RANGE(0x08c000, 0x08cfff) AM_RAM_WRITE(ddealer_vregs_w) AM_BASE_MEMBER(ddealer_state, m_vregs) // palette ram + + /* this might actually be 1 tilemap with some funky rowscroll / columnscroll enabled, I'm not sure */ + AM_RANGE(0x090000, 0x090fff) AM_RAM AM_BASE_MEMBER(ddealer_state, m_left_fg_vram_top) + AM_RANGE(0x091000, 0x091fff) AM_RAM AM_BASE_MEMBER(ddealer_state, m_right_fg_vram_top) + AM_RANGE(0x092000, 0x092fff) AM_RAM AM_BASE_MEMBER(ddealer_state, m_left_fg_vram_bottom) + AM_RANGE(0x093000, 0x093fff) AM_RAM AM_BASE_MEMBER(ddealer_state, m_right_fg_vram_bottom) + //AM_RANGE(0x094000, 0x094001) AM_NOP // always 0? + AM_RANGE(0x098000, 0x098001) AM_WRITE(ddealer_flipscreen_w) + AM_RANGE(0x09c000, 0x09cfff) AM_RAM_WRITE(back_vram_w) AM_BASE_MEMBER(ddealer_state, m_back_vram) // bg tilemap + AM_RANGE(0x0f0000, 0x0fdfff) AM_RAM AM_BASE_MEMBER(ddealer_state, m_work_ram) + AM_RANGE(0x0fe000, 0x0fefff) AM_RAM_WRITE(ddealer_mcu_shared_w) AM_BASE_MEMBER(ddealer_state, m_mcu_shared_ram) + AM_RANGE(0x0ff000, 0x0fffff) AM_RAM +ADDRESS_MAP_END + +static INPUT_PORTS_START( ddealer ) + PORT_START("IN0") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1 ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) //used,"test" in service mode,unknown purpose + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) + + PORT_START("IN1") + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) + PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) + PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) + PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) + PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + /*bits 0-7 are almost surely to be coinage.*/ + PORT_START("DSW1") + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Flip_Screen ) ) + PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0200, 0x0000, DEF_STR( Demo_Sounds ) ) + PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0400, 0x0000, DEF_STR( Language ) ) + PORT_DIPSETTING( 0x0400, DEF_STR( Japanese ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( English ) ) + PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + + PORT_START("UNK") +INPUT_PORTS_END + +static const gfx_layout charlayout = +{ + 8,8, + RGN_FRAC(1,1), + 4, + { 0, 1, 2, 3 }, + { 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4 }, + { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 }, + 32*8 +}; + +static const gfx_layout tilelayout = +{ + 16,16, + RGN_FRAC(1,1), + 4, + { 0, 1, 2, 3 }, + { 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, + 16*32+0*4, 16*32+1*4, 16*32+2*4, 16*32+3*4, 16*32+4*4, 16*32+5*4, 16*32+6*4, 16*32+7*4 }, + { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, + 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32 }, + 32*32 +}; + +static GFXDECODE_START( ddealer ) + GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 16 ) + GFXDECODE_ENTRY( "gfx2", 0, tilelayout, 0x100, 16 ) +GFXDECODE_END + +static MACHINE_START( ddealer ) +{ + ddealer_state *state = machine.driver_data<ddealer_state>(); + + state->save_item(NAME(state->m_respcount)); + state->save_item(NAME(state->m_flipscreen)); + state->save_item(NAME(state->m_input_pressed)); + state->save_item(NAME(state->m_coin_input)); +} + +static MACHINE_RESET (ddealer) +{ + ddealer_state *state = machine.driver_data<ddealer_state>(); + + state->m_respcount = 0; + state->m_flipscreen = 0; + state->m_input_pressed = 0; + state->m_coin_input = 0; +} + +static INTERRUPT_GEN( ddealer_interrupt ) +{ + device_set_input_line(device, 4, HOLD_LINE); +} + +static MACHINE_CONFIG_START( ddealer, ddealer_state ) + + MCFG_CPU_ADD("maincpu" , M68000, 10000000) + MCFG_CPU_PROGRAM_MAP(ddealer) + MCFG_CPU_VBLANK_INT("screen", ddealer_interrupt) + MCFG_CPU_PERIODIC_INT(irq1_line_hold, 90)//guess,controls music tempo,112 is way too fast + + // M50747 or NMK-110 8131 MCU + + MCFG_MACHINE_START(ddealer) + MCFG_MACHINE_RESET(ddealer) + + MCFG_GFXDECODE(ddealer) + + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) + MCFG_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) + MCFG_SCREEN_SIZE(512, 256) + MCFG_SCREEN_VISIBLE_AREA(0*8, 48*8-1, 2*8, 30*8-1) + MCFG_SCREEN_UPDATE(ddealer) + + MCFG_PALETTE_LENGTH(0x400) + + MCFG_VIDEO_START(ddealer) + + MCFG_TIMER_ADD_PERIODIC("coinsim", ddealer_mcu_sim, attotime::from_hz(10000)) // not real, but for simulating the MCU + + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("ymsnd", YM2203, 6000000 / 4)//guess + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) +MACHINE_CONFIG_END + + + +static READ16_HANDLER( ddealer_mcu_r ) +{ + ddealer_state *state = space->machine().driver_data<ddealer_state>(); + static const int resp[] = + { + 0x93, 0xc7, 0x00, 0x8000, + 0x2d, 0x6d, 0x00, 0x8000, + 0x99, 0xc7, 0x00, 0x8000, + 0x2a, 0x6a, 0x00, 0x8000, + 0x8e, 0xc7, 0x00, 0x8000, + -1}; + + int res; + + res = resp[state->m_respcount++]; + if (resp[state->m_respcount] < 0) + state->m_respcount = 0; + + return res; +} + +static DRIVER_INIT( ddealer ) +{ + machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xfe01c, 0xfe01d, FUNC(ddealer_mcu_r) ); +} + +ROM_START( ddealer ) + ROM_REGION( 0x40000, "maincpu", 0 ) /* 68000 Code */ + ROM_LOAD16_BYTE( "1.ic6", 0x00001, 0x20000, CRC(ce0dff50) SHA1(2d7a03f6b9609aea7511a4dc49560a901b0b9f19) ) + ROM_LOAD16_BYTE( "2.ic28", 0x00000, 0x20000, CRC(f00c346f) SHA1(bd73efb19d5f9efc88210d92a82a3f4595b41097) ) + + ROM_REGION( 0x40000, "mcu", 0 ) /* M50747? MCU Code */ + ROM_LOAD( "mcu", 0x0000, 0x1000, NO_DUMP ) // might be NMK-110 8131 chip + + ROM_REGION( 0x20000, "gfx1", 0 ) /* BG0 */ + ROM_LOAD( "4.ic65", 0x00000, 0x20000, CRC(4939ff1b) SHA1(af2f2feeef5520d775731a58cbfc8fcc913b7348) ) + + ROM_REGION( 0x80000, "gfx2", 0 ) /* BG1 */ + ROM_LOAD( "3.ic64", 0x00000, 0x80000, CRC(660e367c) SHA1(54827a8998c58c578c594126d5efc18a92363eaa)) + + ROM_REGION( 0x200, "user1", 0 ) /* Proms */ + ROM_LOAD( "5.ic67", 0x000, 0x100, NO_DUMP ) + ROM_LOAD( "6.ic86", 0x100, 0x100, NO_DUMP ) +ROM_END + +GAME( 1991, ddealer, 0, ddealer, ddealer, ddealer, ROT0, "NMK", "Double Dealer", GAME_SUPPORTS_SAVE ) |