1 /*  gngeo a neogeo emulator
2  *  Copyright (C) 2001 Peponas Mathieu
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include "940shared.h"
20 #include "mvs.h"
21 #include "DrZ80.h"
22 #include "2610intf.h"
23 
24 Uint16 z80_bank[4];
25 static Uint8 *z80map1, *z80map2, *z80map3, *z80map4;
26 Uint8 drz80mem[0x10000];
27 Uint32 mydrz80_Z80PC,mydrz80_Z80SP;
28 
29 struct DrZ80 mydrz80;
30 //extern Z80_Regs Z80;
31 
drz80_rebasePC(unsigned short address)32 unsigned int drz80_rebasePC(unsigned short address)
33 {
34 	//if (address==0x66)
35 	//printf("Rebase PC %x\n",address);
36         mydrz80.Z80PC_BASE = (unsigned int)drz80mem;
37 	mydrz80.Z80PC = mydrz80.Z80PC_BASE + address;
38         return mydrz80.Z80PC_BASE + address;
39 }
40 
drz80_rebaseSP(unsigned short address)41 unsigned int drz80_rebaseSP(unsigned short address)
42 {
43 	//printf("Rebase SP %x\n",address);
44         mydrz80.Z80SP_BASE = (unsigned int)drz80mem;
45 	mydrz80.Z80SP = mydrz80.Z80SP_BASE + address;
46 	return mydrz80.Z80SP_BASE + address;
47 }
48 
drz80_read8(unsigned short address)49 unsigned char drz80_read8(unsigned short address) {
50         return (drz80mem[address&0xFFFF]);
51 }
52 
drz80_read16(unsigned short address)53 unsigned short drz80_read16(unsigned short address) {
54         return drz80_read8(address) | (drz80_read8(address + 1) << 8);
55 }
56 
drz80_write8(unsigned char data,unsigned short address)57 void drz80_write8(unsigned char data,unsigned short address) {
58         if (address>=0xf800) drz80mem[address&0xFFFF]=data;
59 }
60 
drz80_write16(unsigned short data,unsigned short address)61 void drz80_write16(unsigned short data,unsigned short address) {
62         drz80_write8(data & 0xFF,address);
63         drz80_write8(data >> 8,address + 1);
64 }
65 /* cpu interface implementation */
cpu_z80_switchbank(Uint8 bank,Uint16 PortNo)66 void cpu_z80_switchbank(Uint8 bank, Uint16 PortNo)
67 {
68 	//printf("Switch bank %x %x\n",bank,PortNo);
69     if (bank<=3)
70 	z80_bank[bank]=PortNo;
71 
72     switch (bank) {
73     case 0:
74 	z80map1 = shared_data->sm1 + (0x4000 * ((PortNo >> 8) & 0x0f));
75 	memcpy(drz80mem + 0x8000, z80map1, 0x4000);
76 	break;
77     case 1:
78 	z80map2 = shared_data->sm1 + (0x2000 * ((PortNo >> 8) & 0x1f));
79 	memcpy(drz80mem + 0xc000, z80map2, 0x2000);
80 	break;
81     case 2:
82 	z80map3 = shared_data->sm1 + (0x1000 * ((PortNo >> 8) & 0x3f));
83 	memcpy(drz80mem + 0xe000, z80map3, 0x1000);
84 	break;
85     case 3:
86 	z80map4 = shared_data->sm1 + (0x0800 * ((PortNo >> 8) & 0x7f));
87 	memcpy(drz80mem + 0xf000, z80map4, 0x0800);
88 	break;
89     }
90 }
91 
92 
93 /* Z80 IO port handler */
z80_port_read(Uint16 PortNo)94 Uint8 z80_port_read(Uint16 PortNo)
95 {
96         //printf("z80_port_read PC=%04x p=%04x ",cpu_z80_get_pc(),PortNo);
97 	//printf("z80_port_read p=%04x \n",PortNo);
98 	switch (PortNo & 0xff) {
99 	case 0x0:
100 		shared_ctl->pending_command = 0;
101 		//printf("Reseting command. Return sndcode %x\n",sound_code);
102 		return shared_ctl->sound_code;
103 		break;
104 
105 	case 0x4:
106 		//printf("v=%02x\n",YM2610_status_port_0_A_r(0));
107 		return YM2610_status_port_A_r(0);
108 		break;
109 
110 	case 0x5:
111 		//printf("v=%02x\n",YM2610_read_port_0_r(0));
112 		return YM2610_read_port_r(0);
113 		break;
114 
115 	case 0x6:
116 		//printf("v=%02x\n",YM2610_status_port_0_B_r(0));
117 		return YM2610_status_port_B_r(0);
118 		break;
119 
120 	case 0x08:
121 		//printf("v=00 (sb3)\n");
122 		cpu_z80_switchbank(3, PortNo);
123 		return 0;
124 		break;
125 
126 	case 0x09:
127 		//printf("v=00 (sb2)\n");
128 		cpu_z80_switchbank(2, PortNo);
129 		return 0;
130 		break;
131 
132 	case 0x0a:
133 		//printf("v=00 (sb1)\n");
134 		cpu_z80_switchbank(1, PortNo);
135 		return 0;
136 		break;
137 
138 	case 0x0b:
139 		//printf("v=00 (sb0)\n");
140 		cpu_z80_switchbank(0, PortNo);
141 		return 0;
142 		break;
143 	};
144 
145 	return 0;
146 }
147 
z80_port_write(Uint16 PortNb,Uint8 Value)148 void z80_port_write(Uint16 PortNb, Uint8 Value)
149 {
150 	Uint8 data = Value;
151 	//printf("z80_port_write PC=%04x OP=%02x p=%04x v=%02x\n",cpu_z80_get_pc(),memory.sm1[cpu_z80_get_pc()],PortNb,Value);
152 	//printf("Write port %04x %02x\n",PortNb,Value);
153 	switch (PortNb & 0xff) {
154 	case 0x4:
155 		YM2610_control_port_A_w(0, data);
156 		break;
157 
158 	case 0x5:
159 		YM2610_data_port_A_w(0, data);
160 		break;
161 
162 	case 0x6:
163 		YM2610_control_port_B_w(0, data);
164 		break;
165 
166 	case 0x7:
167 		YM2610_data_port_B_w(0, data);
168 		break;
169 
170 	case 0xC:
171 		//printf("Setting result code to %0x\n",Value);
172 		shared_ctl->result_code = Value;
173 		break;
174 	}
175 }
176 
drz80_writeport16(Uint16 port,Uint8 value)177 void drz80_writeport16(Uint16 port, Uint8 value)
178 {
179 	//printf("Write port %d=%d\n",port,value);
180     z80_port_write(port, value);
181 }
182 
drz80_readport16(Uint16 port)183 Uint8 drz80_readport16(Uint16 port)
184 {
185 	//printf("Read port %d\n",port);
186     return z80_port_read(port);
187 }
188 
189 
drz80_irq_callback(void)190 void drz80_irq_callback(void)
191 {
192         //if (mydrz80.Z80_IRQ ==0x2)
193 	//mydrz80.Z80_IRQ = 0x00;
194 	//printf("Irq have been accepted %x %x\n",mydrz80.Z80_IRQ,mydrz80.Z80IF);
195 }
196 
197 #if 0
198 static void pre_save_state(void) {
199 
200     memcpy(shared_data->z80_ram,drz80mem+0xf800,0x800);
201     mydrz80_Z80PC=mydrz80.Z80PC-mydrz80.Z80PC_BASE;
202     mydrz80_Z80SP=mydrz80.Z80SP-mydrz80.Z80SP_BASE;
203 }
204 
205 static void post_load_state(void) {
206     int i;
207 
208     mydrz80.z80_rebasePC=drz80_rebasePC;
209     mydrz80.z80_rebaseSP=drz80_rebaseSP;
210     mydrz80.z80_read8   =drz80_read8;
211     mydrz80.z80_read16  =drz80_read16;
212     mydrz80.z80_write8  =drz80_write8;
213     mydrz80.z80_write16 =drz80_write16;
214     mydrz80.z80_in      =drz80_readport16; /*z80_in*/
215     mydrz80.z80_out     =drz80_writeport16; /*z80_out*/
216 
217     drz80_rebasePC(mydrz80_Z80PC);
218     drz80_rebaseSP(mydrz80_Z80SP);
219 
220     for (i=0;i<4;i++) {
221 	cpu_z80_switchbank(i,z80_bank[i]);
222     }
223     memcpy(drz80mem+0xf800,shared_data->z80_ram,0x800);
224 
225 }
226 
227 static void z80_init_save_state(void) {
228 
229 	create_state_register(ST_Z80,"drz80",1,(void *)&mydrz80,sizeof(mydrz80),REG_UINT8);
230 	create_state_register(ST_Z80,"pc",1,(void *)&mydrz80_Z80PC,sizeof(Uint16),REG_UINT32);
231 	create_state_register(ST_Z80,"sp",1,(void *)&mydrz80_Z80SP,sizeof(Uint16),REG_UINT32);
232 	create_state_register(ST_Z80,"bank",1,(void *)z80_bank,sizeof(Uint16)*4,REG_UINT16);
233 	create_state_register(ST_Z80,"z80_ram",1,(void *)shared_data->z80_ram,sizeof(Uint8)*0x800,REG_UINT8);
234 
235     set_post_load_function(ST_Z80,post_load_state);
236     set_pre_save_function(ST_Z80,pre_save_state);
237 }
238 #endif
239 
cpu_z80_init(void)240 void cpu_z80_init(void)
241 {
242 
243 
244         memset (&mydrz80, 0, sizeof(mydrz80));
245 
246         mydrz80.z80_rebasePC=drz80_rebasePC;
247         mydrz80.z80_rebaseSP=drz80_rebaseSP;
248         mydrz80.z80_read8   =drz80_read8;
249         mydrz80.z80_read16  =drz80_read16;
250         mydrz80.z80_write8  =drz80_write8;
251         mydrz80.z80_write16 =drz80_write16;
252         mydrz80.z80_in      =drz80_readport16; /*z80_in*/
253         mydrz80.z80_out     =drz80_writeport16; /*z80_out*/
254         //mydrz80.z80_irq_callback=drz80_irq_callback;
255         mydrz80.Z80A = 0x00 <<24;
256         mydrz80.Z80F = (1<<2); /* set ZFlag */
257         mydrz80.Z80BC = 0x0000 <<16;
258         mydrz80.Z80DE = 0x0000 <<16;
259         mydrz80.Z80HL = 0x0000 <<16;
260         mydrz80.Z80A2 = 0x00 <<24;
261         mydrz80.Z80F2 = 1<<2;  /* set ZFlag */
262         mydrz80.Z80BC2 = 0x0000 <<16;
263         mydrz80.Z80DE2 = 0x0000 <<16;
264         mydrz80.Z80HL2 = 0x0000 <<16;
265         mydrz80.Z80IX = 0xFFFF;// <<16;
266         mydrz80.Z80IY = 0xFFFF;// <<16;
267         mydrz80.Z80I = 0x00;
268         mydrz80.Z80IM = 0x01;
269         mydrz80.Z80_IRQ = 0x00;
270         mydrz80.Z80IF = 0x00;
271         mydrz80.Z80PC=mydrz80.z80_rebasePC(0);
272         mydrz80.Z80SP=mydrz80.z80_rebaseSP(0xffff);/*0xf000;*/
273 
274 
275 
276 /* bank initalisation */
277 	z80map1 = shared_data->sm1 + 0x8000;
278 	z80map2 = shared_data->sm1 + 0xc000;
279 	z80map3 = shared_data->sm1 + 0xe000;
280 	z80map4 = shared_data->sm1 + 0xf000;
281 
282 
283 
284 	z80_bank[0]=0x8000;
285 	z80_bank[1]=0xc000;
286 	z80_bank[2]=0xe000;
287 	z80_bank[3]=0xf000;
288 
289 	memcpy(drz80mem, shared_data->sm1, 0xf800);
290 
291 	//z80_init_save_state();
292 }
cpu_z80_run(int nbcycle)293 void cpu_z80_run(int nbcycle)
294 {
295 	DrZ80Run(&mydrz80, nbcycle);
296 }
297 
cpu_z80_nmi(void)298 void cpu_z80_nmi(void)
299 {
300 	mydrz80.Z80_IRQ |= 0x02;
301 }
cpu_z80_raise_irq(int l)302 void cpu_z80_raise_irq(int l)
303 {
304 	mydrz80.Z80_IRQ |= 0x1;
305 }
cpu_z80_lower_irq(void)306 void cpu_z80_lower_irq(void)
307 {
308 	mydrz80.Z80_IRQ &= ~0x1;
309 }
310