diff options
Diffstat (limited to 'src/mame/machine/daikaiju.c')
-rw-r--r-- | src/mame/machine/daikaiju.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/src/mame/machine/daikaiju.c b/src/mame/machine/daikaiju.c new file mode 100644 index 00000000000..a4f6423a2c1 --- /dev/null +++ b/src/mame/machine/daikaiju.c @@ -0,0 +1,351 @@ +/*************************************************************************** + +Daikaijuu no Gyakushuu protection sim + +Tomasz Slanina 20060529 + + +Communciation from CPU to MCU is encrypted - every byte +is xored with data taken from cyclic , 22 bytes long buffer. + +MCU commands: +============= + + 0x19 - unknown +---------------- + - no args + - no results +Few writes at the end of level (level summary screen). + + + 0x1d - watchdog? +------------------ + - no args + - no results + + + 0x31 - VRAM address 1 +----------------------- + - args = row + column + - result = 0xd000 + column*2 + row*64 + Address in text layer. + + + 0x32 - VRAM address 2 +----------------------- + - args = row + column + - result = 0xc000 + column*2 + row*64 + Address in BG layer. + + + 0x36 - Controls 1 +------------------ + - args = data from input port + previous result + - result - bits 0-2 = direction , + encoded as: + 0 + 7 1 + 6 2 + 5 3 + 4 + - result - bit 3 = 0 -> no movement (bits 0-2 = bits 0-2 of previous result + 1 -> movement + - result - bit 4 = 0/1 -> button A pressed/released + - result - bit 5 = previous status of button A + - result - bit 6 = 0/1 -> button B pressed/released + - result - bit 7 = previous status of button B + + 0x40 - Player message(s) status (not working ?) +------------------------------------------------- + - args = unk (0/9/d/f (stored at $a020)) + unk (0/1/2 (stored at $a023)) + unk (0/1/2 (stored at $a024)) (2nd and 3rd args are ident.) + - result = 0/1/2/ (same as 2nd/3rd arg) +Result is discarded due to bug (or patch?) in the code - missing "cp 0"/"or a"/"and a"/etc instruction +to set CPU flags before conditional jump at addr. 0x256 (previous flags are tested, Z is _always_ set +(it's result of testing MCU "data ready to send" flag). +Thic mcu command is used to determine if player message(READY/PLAYER1/PLAYER2) should be +displayed (game) or not (attract mode). Due to above bug message is always displayed +(confirmed on real hw). + + 0x44 - Controls 2 +-------------------- +- args = result of command 0x36 + previous result of command 44 + step (1 or 2) +- result - bits 0-3 = direction encoded like in result of command 0x36, but + 16 steps instead 8. This command calculates all steps between + new direction (1st arg) and old one with given step. + Example: + w (2,0,1) r (1) + w (2,1,1) r (2) + w (2,2,1) r (3) + w (2,3,1) r (4) + w (2,4,1) r (4) + ... + w (2,4,1) r (4) + - bit 4 = 1 -> result bits 0-3 == prev result bits 0-3, otherwise 0 + - bits 5-7 = unknown , always 0 ? + + 0x60 - MCU ID +--------------- + - no args + - result = 0x5a + + +***************************************************************************/ +#include "driver.h" +#include "cpu/z80/z80.h" + +#define ID_DAIKAIJU 0x5a + +#define MCU_UNKNOWN 0x19 +#define MCU_WATCHDOG 0x1d +#define MCU_ADDRESS1 0x31 +#define MCU_ADDRESS2 0x32 +#define MCU_CONTROLS1 0x36 +#define MCU_MESSAGE 0x40 +#define MCU_CONTROLS2 0x44 +#define MCU_ID 0x60 + +#define MCU_ADDRESS1_LENGTH 2 +#define MCU_ADDRESS2_LENGTH 2 +#define MCU_CONTROLS1_LENGTH 2 +#define MCU_MESSAGE_LENGTH 3 +#define MCU_CONTROLS2_LENGTH 3 +#define MCU_ID_LENGTH 0 + +#define SET_COMMAND(n) daikaiju_command=data; \ + daikaiju_length=n;\ + daikaiju_cnt=0;\ + daikaiju_cntr=0; + + +extern int lsasquad_sound_pending; +static int daikaiju_xor, daikaiju_command, daikaiju_length, daikaiju_prev, daikaiju_cnt, daikaiju_cntr; + +static int daikaiju_buffer[256]; + +static int xortable[]= +{ + 0xF5, 0xD5, 0x6A, 0x26, 0x00, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x16, 0x00, 0xCB, 0x23, 0x19, + 0x11, 0x00, 0xC0, 0x19, 0xD1, 0xF1, 0xC9, -1 +}; + +MACHINE_RESET(daikaiju) +{ + daikaiju_xor=-1; + daikaiju_command=0; + daikaiju_length=0; +} + +WRITE8_HANDLER( daikaiju_mcu_w ) +{ + if(daikaiju_xor <0) + { + //reset + daikaiju_xor=0; + data^=0xc3; + } + else + { + data^=xortable[daikaiju_xor]; + //check for end of table + if(xortable[++daikaiju_xor]<0) + { + daikaiju_xor=0; + } + } + daikaiju_prev=data; + + if(daikaiju_length == 0) //new command + { + switch(data) + { + case MCU_UNKNOWN: + case MCU_WATCHDOG: break; + case MCU_ADDRESS1: SET_COMMAND(MCU_ADDRESS1_LENGTH); break; + case MCU_ADDRESS2: SET_COMMAND(MCU_ADDRESS2_LENGTH); break; + case MCU_CONTROLS1: SET_COMMAND(MCU_CONTROLS1_LENGTH); break; + case MCU_MESSAGE: SET_COMMAND(MCU_MESSAGE_LENGTH); break; + case MCU_CONTROLS2: SET_COMMAND(MCU_CONTROLS2_LENGTH); break; + case MCU_ID: SET_COMMAND(MCU_ID_LENGTH); break; + default: + daikaiju_command=data; + logerror("Unknown MCU command W %x %x \n",data,activecpu_get_pc()); + } + } + else + { + --daikaiju_length; + daikaiju_buffer[daikaiju_cnt++]=data; + } +} + +READ8_HANDLER( daikaiju_mcu_r ) +{ + switch(daikaiju_command) + { + case MCU_ID: + return ID_DAIKAIJU; + + case MCU_CONTROLS1: + { + int n; + switch( (daikaiju_buffer[0]&0xf)^0xf) + { + case 0x00: n = (daikaiju_buffer[1]&(~8))&0xf; break; + case 0x08: n = 0 | 8; break; + case 0x0a: n = 1 | 8; break; + case 0x02: n = 2 | 8; break; + case 0x06: n = 3 | 8; break; + case 0x04: n = 4 | 8; break; + case 0x05: n = 5 | 8; break; + case 0x01: n = 6 | 8; break; + case 0x09: n = 7 | 8; break; + + default: n = 0; break; + } + + if( !(daikaiju_buffer[0]&0x10) ) //button 1 pressed + { + if(daikaiju_buffer[1]&0x10) //previous status + { + n|=0x40; // button 0->1 + } + else + { + n|=0; //button 1->1 + } + } + else + { + if(daikaiju_buffer[1]&0x10) //previous status + { + n|=0x40+0x10; // button 0->0 + } + else + { + n|=0x10; //button 1->0 + } + } + + if( !(daikaiju_buffer[0]&0x20) ) //button 2 pressed + { + if(daikaiju_buffer[1]&0x20) //previous status + { + n|=0x80; // button 0->1 + } + else + { + n|=0; //button 1->1 + } + } + else + { + if(daikaiju_buffer[1]&0x20) //previous status + { + n|=0x80+0x20; // button 0->0 + } + else + { + n|=0x20; //button 1->0 + } + } + return n; + } + return 0; + + case MCU_ADDRESS1: + { + int address=daikaiju_buffer[1]*2+64*daikaiju_buffer[0]; + + address&=0x0fff; // ? + address+=0xd000; + + if(daikaiju_cntr==0) + { + daikaiju_cntr++; + return address&0xff; + } + else + { + return address>>8; + } + } + return 0; + + case MCU_ADDRESS2: + { + int address=daikaiju_buffer[1]*2+64*daikaiju_buffer[0]; + + address&=0x1fff; // ? + address+=0xc000; + + if(daikaiju_cntr==0) + { + daikaiju_cntr++; + return address&0xff; + } + else + { + return address>>8; + } + } + return 0; + + case MCU_MESSAGE: + return daikaiju_buffer[1]; + + case MCU_CONTROLS2: + { + int n; + int dest=(daikaiju_buffer[0]&0x7)<<1; + int prev=(daikaiju_buffer[1]&0xf); + + if(daikaiju_buffer[2]==2) + { + prev&=0xfe; + } + if(prev!=dest) + { + int diff=(dest-prev); + + if((diff>8 )|| (diff<0 && diff >-8)) + { + n=(prev-daikaiju_buffer[2])&0xf; + } + else + { + n=(prev+daikaiju_buffer[2])&0xf; + } + } + else + { + n=prev; + } + prev&=0xf; + if(prev!=n) + { + n|=0x10; + } + return n; + } + } + logerror("Unknown MCU R %x %x %x %x\n",activecpu_get_pc(), daikaiju_command, daikaiju_length, daikaiju_prev); + return 0xff; +} + +READ8_HANDLER( daikaiju_mcu_status_r ) +{ + int res = input_port_3_r(0); + + res^=mame_rand(Machine)&3; + res |=((lsasquad_sound_pending & 0x02)^2)<<3; //inverted flag + lsasquad_sound_pending &= ~0x02; + return res; +} + |