amalgamation
[picodrive.git] / Pico / Sek.c
1 // This is part of Pico Library\r
2 \r
3 // (c) Copyright 2004 Dave, All rights reserved.\r
4 // (c) Copyright 2006 notaz, All rights reserved.\r
5 // Free for non-commercial use.\r
6 \r
7 // For commercial use, separate licencing terms must be obtained.\r
8 \r
9 \r
10 #include "PicoInt.h"\r
11 \r
12 \r
13 int SekCycleCnt=0; // cycles done in this frame\r
14 int SekCycleAim=0; // cycle aim\r
15 unsigned int SekCycleCntT=0;\r
16 \r
17 #ifdef EMU_C68K\r
18 // ---------------------- Cyclone 68000 ----------------------\r
19 struct Cyclone PicoCpu;\r
20 #endif\r
21 \r
22 #ifdef EMU_M68K\r
23 // ---------------------- MUSASHI 68000 ----------------------\r
24 m68ki_cpu_core PicoM68kCPU; // MD's CPU\r
25 #endif\r
26 \r
27 #ifdef EMU_A68K\r
28 // ---------------------- A68K ----------------------\r
29 \r
30 void __cdecl M68000_RESET();\r
31 int m68k_ICount=0;\r
32 unsigned int mem_amask=0xffffff; // 24-bit bus\r
33 unsigned int mame_debug=0,cur_mrhard=0,m68k_illegal_opcode=0,illegal_op=0,illegal_pc=0,opcode_entry=0; // filler\r
34 \r
35 static int IrqCallback(int i) { i; return -1; }\r
36 static int DoReset() { return 0; }\r
37 static int (*ResetCallback)()=DoReset;\r
38 \r
39 #pragma warning (disable:4152)\r
40 #endif\r
41 \r
42 \r
43 \r
44 #ifdef EMU_C68K\r
45 // interrupt acknowledgment\r
46 static int SekIntAck(int level)\r
47 {\r
48   // try to emulate VDP's reaction to 68000 int ack\r
49   if     (level == 4) Pico.video.pending_ints  =  0;\r
50   else if(level == 6) Pico.video.pending_ints &= ~0x20;\r
51   PicoCpu.irq = 0;\r
52   return CYCLONE_INT_ACK_AUTOVECTOR;\r
53 }\r
54 \r
55 static void SekResetAck()\r
56 {\r
57 #if defined(__DEBUG_PRINT) || defined(WIN32)\r
58   dprintf("Reset encountered @ %06x", SekPc);\r
59 #endif\r
60 }\r
61 \r
62 static int SekUnrecognizedOpcode()\r
63 {\r
64   unsigned int pc, op;\r
65   pc = SekPc;\r
66   op = PicoCpu.read16(pc);\r
67 #if defined(__DEBUG_PRINT) || defined(WIN32)\r
68   dprintf("Unrecognized Opcode %04x @ %06x", op, pc);\r
69 #endif\r
70   // see if we are not executing trash\r
71   if (pc < 0x200 || (pc > Pico.romsize+4 && (pc&0xe00000)!=0xe00000)) {\r
72     PicoCpu.cycles = 0;\r
73     PicoCpu.state_flags |= 1;\r
74     return 1;\r
75   }\r
76 #ifdef EMU_M68K // debugging cyclone\r
77   {\r
78     extern int have_illegal;\r
79     have_illegal = 1;\r
80   }\r
81 #endif\r
82   //exit(1);\r
83   return 0;\r
84 }\r
85 #endif\r
86 \r
87 \r
88 #ifdef EMU_M68K\r
89 static int SekIntAckM68K(int level)\r
90 {\r
91   if     (level == 4) { Pico.video.pending_ints  =  0;    dprintf("hack: [%i|%i]", Pico.m.scanline, SekCyclesDone()); }\r
92   else if(level == 6) { Pico.video.pending_ints &= ~0x20; dprintf("vack: [%i|%i]", Pico.m.scanline, SekCyclesDone()); }\r
93   CPU_INT_LEVEL = 0;\r
94   return M68K_INT_ACK_AUTOVECTOR;\r
95 }\r
96 \r
97 static int SekTasCallback(void)\r
98 {\r
99   return 0; // no writeback\r
100 }\r
101 #endif\r
102 \r
103 \r
104 \r
105 PICO_INTERNAL int SekInit()\r
106 {\r
107 #ifdef EMU_C68K\r
108   CycloneInit();\r
109   memset(&PicoCpu,0,sizeof(PicoCpu));\r
110   PicoCpu.IrqCallback=SekIntAck;\r
111   PicoCpu.ResetCallback=SekResetAck;\r
112   PicoCpu.UnrecognizedCallback=SekUnrecognizedOpcode;\r
113 #endif\r
114 #ifdef EMU_A68K\r
115   memset(&M68000_regs,0,sizeof(M68000_regs));\r
116   M68000_regs.IrqCallback=IrqCallback;\r
117   M68000_regs.pResetCallback=ResetCallback;\r
118   M68000_RESET(); // Init cpu emulator\r
119 #endif\r
120 #ifdef EMU_M68K\r
121   {\r
122     void *oldcontext = m68ki_cpu_p;\r
123     m68k_set_context(&PicoM68kCPU);\r
124     m68k_set_cpu_type(M68K_CPU_TYPE_68000);\r
125     m68k_init();\r
126     m68k_set_int_ack_callback(SekIntAckM68K);\r
127     m68k_set_tas_instr_callback(SekTasCallback);\r
128     m68k_pulse_reset(); // Init cpu emulator\r
129     m68k_set_context(oldcontext);\r
130   }\r
131 #endif\r
132 \r
133   return 0;\r
134 }\r
135 \r
136 // Reset the 68000:\r
137 PICO_INTERNAL int SekReset()\r
138 {\r
139   if (Pico.rom==NULL) return 1;\r
140 \r
141 #ifdef EMU_C68K\r
142   PicoCpu.state_flags=0;\r
143   PicoCpu.osp=0;\r
144   PicoCpu.srh =0x27; // Supervisor mode\r
145   PicoCpu.flags=4;   // Z set\r
146   PicoCpu.irq=0;\r
147   PicoCpu.a[7]=PicoCpu.read32(0); // Stack Pointer\r
148   PicoCpu.membase=0;\r
149   PicoCpu.pc=PicoCpu.checkpc(PicoCpu.read32(4)); // Program Counter\r
150 #endif\r
151 #ifdef EMU_A68K\r
152   // Reset CPU: fetch SP and PC\r
153   M68000_regs.srh=0x27; // Supervisor mode\r
154   M68000_regs.a[7]=PicoRead32(0);\r
155   M68000_regs.pc  =PicoRead32(4);\r
156   PicoInitPc(M68000_regs.pc);\r
157 #endif\r
158 #ifdef EMU_M68K\r
159   m68k_set_context(&PicoM68kCPU); // if we ever reset m68k, we always need it's context to be set\r
160   m68ki_cpu.sp[0]=0;\r
161   m68k_set_irq(0);\r
162   m68k_pulse_reset();\r
163 #endif\r
164 \r
165   return 0;\r
166 }\r
167 \r
168 \r
169 PICO_INTERNAL int SekInterrupt(int irq)\r
170 {\r
171 #if defined(EMU_C68K) && defined(EMU_M68K)\r
172   {\r
173     extern unsigned int dbg_irq_level;\r
174     dbg_irq_level=irq;\r
175     return 0;\r
176   }\r
177 #endif\r
178 #ifdef EMU_C68K\r
179   PicoCpu.irq=irq;\r
180 #endif\r
181 #ifdef EMU_A68K\r
182   M68000_regs.irq=irq; // raise irq (gets lowered after taken)\r
183 #endif\r
184 #ifdef EMU_M68K\r
185   {\r
186     void *oldcontext = m68ki_cpu_p;\r
187     m68k_set_context(&PicoM68kCPU);\r
188     m68k_set_irq(irq); // raise irq (gets lowered after taken or must be done in ack)\r
189     m68k_set_context(oldcontext);\r
190   }\r
191 #endif\r
192   return 0;\r
193 }\r
194 \r
195 //int SekPc() { return PicoCpu.pc-PicoCpu.membase; }\r
196 //int SekPc() { return M68000_regs.pc; }\r
197 //int SekPc() { return m68k_get_reg(NULL, M68K_REG_PC); }\r
198 \r
199 PICO_INTERNAL void SekState(unsigned char *data)\r
200 {\r
201 #ifdef EMU_C68K\r
202   memcpy(data,PicoCpu.d,0x44);\r
203 #elif defined(EMU_A68K)\r
204   memcpy(data,      M68000_regs.d, 0x40);\r
205   memcpy(data+0x40,&M68000_regs.pc,0x04);\r
206 #elif defined(EMU_M68K)\r
207   memcpy(data,      PicoM68kCPU.dar,0x40);\r
208   memcpy(data+0x40,&PicoM68kCPU.pc, 0x04);\r
209 #endif\r
210 }\r
211 \r
212 PICO_INTERNAL void SekSetRealTAS(int use_real)\r
213 {\r
214 #ifdef EMU_C68K\r
215   CycloneSetRealTAS(use_real);\r
216 #endif\r
217 }\r
218 \r