summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/daikaiju.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/daikaiju.c')
-rw-r--r--src/mame/machine/daikaiju.c351
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;
+}
+