1 /*--------------------------------------------------
2    TGB Dual - Gameboy Emulator -
3    Copyright (C) 2001  Hii
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License
7    as published by the Free Software Foundation; either version 2
8    of the License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 */
19 
20 //---------------------------------------
21 // MBC エミュレーション部 (MBC1/2/3/5/7,HuC-1,MMM01,Rumble,RTC,Motion-Sensor,etc...)
22 // MBC emulation unit (MBC1/2/3/5/7,HuC-1,MMM01,Rumble,RTC,Motion-Sensor,etc...)
23 
24 #include "gb.h"
25 
mbc(gb * ref)26 mbc::mbc(gb *ref)
27 {
28 	ref_gb=ref;
29 
30 	reset();
31 }
32 
~mbc()33 mbc::~mbc()
34 {
35 
36 }
37 
reset()38 void mbc::reset()
39 {
40 	ref_gb->get_rom()->set_first(0);
41 	rom_page=ref_gb->get_rom()->get_rom();
42 	sram_page=ref_gb->get_rom()->get_sram();
43 
44 	mbc1_16_8=true;
45 	mbc1_dat=0;
46 	ext_is_ram=true;
47 
48 	mbc7_adr=0;
49 	mbc7_dat=0;
50 	mbc7_write_enable=false;
51 	mbc7_idle=false;
52 	mbc7_cs=0;
53 	mbc7_sk=0;
54 	mbc7_state=0;
55 	mbc7_buf=0;
56 	mbc7_count=0;
57 	mbc7_ret=0;
58 
59 	huc1_16_8=true;
60 	huc1_dat=0;
61 
62 	if (ref_gb->get_rom()->get_info()->cart_type==0xFD){
63 		ext_is_ram=false;
64 	}
65 }
66 
read(word adr)67 byte mbc::read(word adr)
68 {
69 	return 0;
70 }
71 
write(word adr,byte dat)72 void mbc::write(word adr,byte dat)
73 {
74 	switch(ref_gb->get_rom()->get_info()->cart_type){
75 	case 1:
76 	case 2:
77 	case 3:
78 		mbc1_write(adr,dat);
79 		break;
80 	case 5:
81 	case 6:
82 		mbc2_write(adr,dat);
83 		break;
84 	case 0x0F:
85 	case 0x10:
86 	case 0x11:
87 	case 0x12:
88 	case 0x13:
89 		mbc3_write(adr,dat);
90 		break;
91 	case 0x19:
92 	case 0x1A:
93 	case 0x1B:
94 	case 0x1C:
95 	case 0x1D:
96 	case 0x1E:
97 		mbc5_write(adr,dat);
98 		break;
99 	case 0x22:
100 		mbc7_write(adr,dat);
101 		break;
102 	case 0xFD:
103 		tama5_write(adr,dat);
104 		break;
105 	case 0xFE:
106 		huc3_write(adr,dat);
107 		break;
108 	case 0xFF:
109 		huc1_write(adr,dat);
110 		break;
111 	case 0x100:
112 		mmm01_write(adr,dat);
113 		break;
114 	}
115 }
116 
ext_read(word adr)117 byte mbc::ext_read(word adr)
118 {
119 	switch(ref_gb->get_rom()->get_info()->cart_type){
120 	case 1:
121 	case 2:
122 	case 3:
123 	case 5:
124 	case 6:
125 		return 0;
126 	case 0x0F:
127 	case 0x10:
128 	case 0x11:
129 	case 0x12:
130 	case 0x13:
131 //		extern FILE *file;
132 //		fprintf(file,"external read [%04X]\n",adr);
133 		if (mbc3_latch){
134 			switch(mbc3_timer){
135 			case 8: return mbc3_sec;
136 			case 9: return mbc3_min;
137 			case 10: return mbc3_hour;
138 			case 11: return mbc3_dayl;
139 			case 12: return mbc3_dayh;
140 			}
141 		}
142 		return ref_gb->get_renderer()->get_time(mbc3_timer);
143 	case 0x19:
144 	case 0x1A:
145 	case 0x1B:
146 	case 0x1C:
147 	case 0x1D:
148 	case 0x1E:
149 		return 0;
150 	case 0x22: // コロコロカービィ // Korokoro Kirby
151 		switch(adr&0xa0f0)
152 		{
153 		case 0xA000:
154 			return 0;
155 		case 0xA010:
156 			return 0;
157 		case 0xA020:
158 			return ref_gb->get_renderer()->get_sensor(true)&0xff;
159 		case 0xA030:
160 			return (ref_gb->get_renderer()->get_sensor(true)>>8)&0xf;
161 		case 0xA040:
162 			return ref_gb->get_renderer()->get_sensor(false)&0xff;
163 		case 0xA050:
164 			return (ref_gb->get_renderer()->get_sensor(false)>>8)&0xf;
165 		case 0xA060:
166 			return 0;
167 		case 0xA070:
168 			return 0;
169 		case 0xA080:
170 			return mbc7_ret;
171 		}
172 		return 0xff;
173 	case 0xFD:
174 //		extern FILE *file;
175 //		fprintf(file,"%04X : TAMA5 ext_read %04X \n",ref_gb->get_cpu()->get_regs()->PC,adr);
176 		return 1;
177 	case 0xFE:
178 //		extern FILE *file;
179 //		fprintf(file,"%04X : HuC-3 ext_read %04X \n",ref_gb->get_cpu()->get_regs()->PC,adr);
180 		return 1;
181 	case 0xFF:
182 		return 0;
183 	}
184 	return 0;
185 }
186 
ext_write(word adr,byte dat)187 void mbc::ext_write(word adr,byte dat)
188 {
189 	int i;
190 
191 	switch(ref_gb->get_rom()->get_info()->cart_type){
192 	case 1:
193 	case 2:
194 	case 3:
195 	case 5:
196 	case 6:
197 	case 0x19:
198 	case 0x1A:
199 	case 0x1B:
200 	case 0x1C:
201 	case 0x1D:
202 	case 0x1E:
203 	case 0xFF:
204 		break;
205 	case 0x0F:
206 	case 0x10:
207 	case 0x11:
208 	case 0x12:
209 	case 0x13:
210 		ref_gb->get_renderer()->set_time(mbc3_timer,dat);
211 		break;
212 	case 0xFE: //HuC-3
213 //		extern FILE *file;
214 //		fprintf(file,"%04X : HuC-3 ext_write %04X <= %02X\n",ref_gb->get_cpu()->get_regs()->PC,adr,dat);
215 		break;
216 	case 0xFD: //TAMA5
217 //		extern FILE *file;
218 //		fprintf(file,"%04X : TAMA5 ext_write %04X <= %02X\n",ref_gb->get_cpu()->get_regs()->PC,adr,dat);
219 		break;
220 	case 0x22: // コロコロカービィ // Korokoro Kirby
221 		if (adr==0xA080){
222 			int bef_cs=mbc7_cs,bef_sk=mbc7_sk;
223 
224 			mbc7_cs=dat>>7;
225 			mbc7_sk=(dat>>6)&1;
226 
227 			if (!bef_cs&&mbc7_cs){
228 				if (mbc7_state==5){
229 					if (mbc7_write_enable){
230 						*(ref_gb->get_rom()->get_sram()+mbc7_adr*2)=mbc7_buf>>8;
231 						*(ref_gb->get_rom()->get_sram()+mbc7_adr*2+1)=mbc7_buf&0xff;
232 ////						fprintf(file,"書き込み完了\n");
233 //						fprintf(file,"Write complete\n");
234 					}
235 					mbc7_state=0;
236 					mbc7_ret=1;
237 ////					fprintf(file,"書き込み受理 ステート:なし\n");
238 //					fprintf(file,"State writing acceptance: no\n");
239 				}
240 				else{
241 					mbc7_idle=true; // アイドル状態突入
242 					mbc7_state=0;
243 ////					fprintf(file,"アイドル状態突入 ステート:アイドル状態\n");
244 //					fprintf(file,"Idle: idle state rush\n");
245 				}
246 			}
247 
248 			if (!bef_sk&&mbc7_sk){ // クロック立ち上がり // Rising edge of the clock
249 				if (mbc7_idle){ // アイドル状態であれば // If idle
250 					if (dat&0x02){
251 						mbc7_idle=false; // アイドル状態解除 // Idle state release
252 						mbc7_count=0;
253 						mbc7_state=1;
254 ////						fprintf(file,"アイドル状態解除 ステート:コマンド認識\n");
255 //						fprintf(file,"Command recognition: release idle state\n");
256 					}
257 				}
258 				else{
259 					switch(mbc7_state){
260 					case 1: // コマンド受付 // Command reception
261 						mbc7_buf<<=1;
262 						mbc7_buf|=(dat&0x02)?1:0;
263 						mbc7_count++;
264 						if (mbc7_count==2){ // 受付終了 // Exit Reception
265 							mbc7_state=2;
266 							mbc7_count=0;
267 							mbc7_op_code=mbc7_buf&3;
268 						}
269 						break;
270 					case 2: // アドレス受信 // Address received
271 						mbc7_buf<<=1;
272 						mbc7_buf|=(dat&0x02)?1:0;
273 						mbc7_count++;
274 						if (mbc7_count==8){ // 受付終了 // Exit Reception
275 							mbc7_state=3;
276 							mbc7_count=0;
277 							mbc7_adr=mbc7_buf&0xff;
278 							if (mbc7_op_code==0){
279 								if ((mbc7_adr>>6)==0){
280 ////									fprintf(file,"書き込み消去禁止 ステート:なし\n");
281 //									fprintf(file,"erasing state prohibited : No\n");
282 									mbc7_write_enable=false;
283 									mbc7_state=0;
284 								}
285 								else if ((mbc7_adr>>6)==3){
286 ////									fprintf(file,"書き込み消去許可 ステート:なし\n");
287 //									fprintf(file,"erasing the authorized state : No\n");
288 									mbc7_write_enable=true;
289 									mbc7_state=0;
290 								}
291 							}
292 							else{
293 ////								fprintf(file,"アドレス:%02X ステート:データ受信\n",mbc7_adr);
294 //								fprintf(file,"Address: %02X State: Data reception\n",mbc7_adr);
295 							}
296 						}
297 						break;
298 					case 3: // データ // Data
299 						mbc7_buf<<=1;
300 						mbc7_buf|=(dat&0x02)?1:0;
301 						mbc7_count++;
302 
303 						switch(mbc7_op_code){
304 						case 0:
305 							if (mbc7_count==16){
306 								if ((mbc7_adr>>6)==0){
307 ////									fprintf(file,"書き込み消去禁止 ステート:なし\n");
308 //									fprintf(file,"erasing state prohibited : No\n");
309 									mbc7_write_enable=false;
310 									mbc7_state=0;
311 								}
312 								else if ((mbc7_adr>>6)==1){
313 									if (mbc7_write_enable){
314 										for (i=0;i<256;i++){
315 											*(ref_gb->get_rom()->get_sram()+i*2)=mbc7_buf>>8;
316 											*(ref_gb->get_rom()->get_sram()+i*2)=mbc7_buf&0xff;
317 										}
318 									}
319 ////									fprintf(file,"全アドレス書き込み %04X ステート:なし\n",mbc7_buf);
320 //									fprintf(file,"Write all addresses %04X State: No\n",mbc7_buf);
321 									mbc7_state=5;
322 								}
323 								else if ((mbc7_adr>>6)==2){
324 									if (mbc7_write_enable){
325 										for (i=0;i<256;i++)
326 											*(word*)(ref_gb->get_rom()->get_sram()+i*2)=0xffff;
327 									}
328 ////									fprintf(file,"全アドレス消去 ステート:なし\n");
329 //									fprintf(file,"erased state all addresses : None\n");
330 									mbc7_state=5;
331 								}
332 								else if ((mbc7_adr>>6)==3){
333 ////									fprintf(file,"書き込み消去許可 ステート:なし\n");
334 //									fprintf(file,"erasing the authorized state : No\n");
335 									mbc7_write_enable=true;
336 									mbc7_state=0;
337 								}
338 								mbc7_count=0;
339 							}
340 							break;
341 						case 1:
342 							if (mbc7_count==16){
343 ////								fprintf(file,"書き込み [%02X]<-%04X ステート:書き込み待ちフレーム\n",mbc7_adr,mbc7_buf);
344 //								fprintf(file,"Writing [%02X]<-%04X State: Frame waiting to be written\n",mbc7_adr,mbc7_buf);
345 								mbc7_count=0;
346 								mbc7_state=5;
347 								mbc7_ret=0;
348 							}
349 							break;
350 						case 2:
351 							if (mbc7_count==1){
352 ////								fprintf(file,"ダミー受信完了 ステート:読み出し可\n");
353 //								fprintf(file,"Readable: State reception complete dummy\n");
354 								mbc7_state=4;
355 								mbc7_count=0;
356 								mbc7_buf=(ref_gb->get_rom()->get_sram()[mbc7_adr*2]<<8)|(ref_gb->get_rom()->get_sram()[mbc7_adr*2+1]);
357 ////								fprintf(file,"受信データ %04X\n",mbc7_buf);
358 //								fprintf(file,"Received data %04X\n",mbc7_buf);
359 							}
360 							break;
361 						case 3:
362 							if (mbc7_count==16){
363 ////								fprintf(file,"消去 [%02X] ステート:書き込み待ちフレーム\n",mbc7_adr,mbc7_buf);
364 //								fprintf(file,"Elimination [%02X] State: Frame waiting to be written\n",mbc7_adr,mbc7_buf);
365 								mbc7_count=0;
366 								mbc7_state=5;
367 								mbc7_ret=0;
368 								mbc7_buf=0xffff;
369 							}
370 							break;
371 						}
372 						break;
373 					}
374 				}
375 			}
376 
377 			if (bef_sk&&!mbc7_sk){ // クロック立ち下り // Falling clock
378 				if (mbc7_state==4){ // 読み出し中 // While reading
379 					mbc7_ret=(mbc7_buf&0x8000)?1:0;
380 					mbc7_buf<<=1;
381 					mbc7_count++;
382 ////					fprintf(file,"読み出し中 %d ビット目\n",mbc7_count);
383 //					fprintf(file,"While reading %dth bit\n",mbc7_count);
384 					if (mbc7_count==16){
385 						mbc7_count=0;
386 						mbc7_state=0;
387 ////						fprintf(file,"読み出し完了 ステート:なし\n");
388 //						fprintf(file,"Read state complete: No\n");
389 					}
390 				}
391 			}
392 		}
393 
394 		break;
395 	}
396 }
397 
get_state()398 int mbc::get_state()
399 {
400 	switch(ref_gb->get_rom()->get_info()->cart_type){
401 	case 1:
402 	case 2:
403 	case 3:
404 		return mbc1_dat|(mbc1_16_8?0x100:0);
405 	case 5:
406 	case 6:
407 		return 0;
408 	case 0x0F:
409 	case 0x10:
410 	case 0x11:
411 	case 0x12:
412 	case 0x13:
413 		return (mbc3_timer&0xf)|((mbc3_latch&1)<<4)|((mbc3_sec&0x3f)<<5)|((mbc3_min&0x3f)<<11)|
414 			((mbc3_hour&0x1f)<<17)|(mbc3_dayl<<22)|((mbc3_dayh&1)<<30);
415 	case 0x19:
416 	case 0x1A:
417 	case 0x1B:
418 	case 0x1C:
419 	case 0x1D:
420 	case 0x1E:
421 		return mbc5_dat;
422 	case 0xFF:
423 		return huc1_dat|(huc1_16_8?0x100:0);
424 	default:
425 		return 0;
426 	}
427 }
428 
set_state(int dat)429 void mbc::set_state(int dat)
430 {
431 	switch(ref_gb->get_rom()->get_info()->cart_type){
432 	case 1:
433 	case 2:
434 	case 3:
435 		mbc1_dat=dat&0xFF;
436 		mbc1_16_8=((dat>>8)&1?true:false);
437 		break;
438 	case 5:
439 	case 6:
440 		break;
441 	case 0x0F:
442 	case 0x10:
443 	case 0x11:
444 	case 0x12:
445 	case 0x13:
446 		mbc3_timer=dat&0x0F;
447 		dat>>=4;
448 		mbc3_latch=dat&1;
449 		dat>>=1;
450 		mbc3_sec=dat&0x3f;
451 		dat>>=6;
452 		mbc3_min=dat&0x3f;
453 		dat>>=6;
454 		mbc3_hour=dat&0x1f;
455 		dat>>=5;
456 		mbc3_dayl=dat&0xff;
457 		dat>>=8;
458 		mbc3_dayh=dat&1;
459 		break;
460 	case 0x19:
461 	case 0x1A:
462 	case 0x1B:
463 	case 0x1C:
464 	case 0x1D:
465 	case 0x1E:
466 		mbc5_dat=dat&0xFFFF;
467 		break;
468 	case 0xFF:
469 		huc1_dat=dat&0xFF;
470 		huc1_16_8=((dat>>8)&1?true:false);
471 		break;
472 	}
473 }
474 
set_page(int rom,int sram)475 void mbc::set_page(int rom,int sram)
476 {
477 	rom_page=ref_gb->get_rom()->get_rom()+rom*0x4000;
478 	sram_page=ref_gb->get_rom()->get_sram()+sram*0x2000;
479 }
480 
481 static int rom_size_tbl[]={2,4,8,16,32,64,128,256,512};
482 static int ram_size_tbl[]={0,1,1,4,16,8};
483 
mbc1_write(word adr,byte dat)484 void mbc::mbc1_write(word adr,byte dat)
485 {
486 	if (mbc1_16_8){//16/8モード
487 		switch(adr>>13){
488 		case 0:
489 			break;
490 		case 1:
491 			mbc1_dat=(mbc1_dat&0x60)+(dat&0x1F);
492 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((mbc1_dat==0?1:mbc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
493 			break;
494 		case 2:
495 			mbc1_dat=((dat<<5)&0x60)+(mbc1_dat&0x1F);
496 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((mbc1_dat==0?1:mbc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
497 			break;
498 		case 3:
499 			if (dat&1)
500 				mbc1_16_8=false;
501 			else
502 				mbc1_16_8=true;
503 //			mbc1_dat=0;
504 			break;
505 		}
506 	}
507 	else{//4/32モード
508 		switch(adr>>13){
509 		case 0:
510 			break;
511 		case 1:
512 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat==0?1:dat)&0x1F&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
513 			break;
514 		case 2:
515 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&3);
516 			break;
517 		case 3:
518 			if (dat&1)
519 				mbc1_16_8=false;
520 			else
521 				mbc1_16_8=true;
522 //			mbc1_dat=0;
523 			break;
524 		}
525 	}
526 }
527 
mbc2_write(word adr,byte dat)528 void mbc::mbc2_write(word adr,byte dat)
529 {
530 	if ((adr>=0x2000)&&(adr<=0x3FFF))
531 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*(((dat&0x0F)==0?1:dat&0x0F)-1);
532 }
533 
mbc3_write(word adr,byte dat)534 void mbc::mbc3_write(word adr,byte dat)
535 {
536 	switch(adr>>13){
537 	case 0:
538 		if (dat==0x0a)
539 			ext_is_ram=true;
540 		else{
541 			ext_is_ram=false;
542 			mbc3_timer=0;
543 		}
544 		break;
545 	case 1:
546 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat==0?1:dat)&0x7F&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
547 		break;
548 	case 2:
549 		if (dat<8){
550 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&7&(ram_size_tbl[ref_gb->get_rom()->get_info()->ram_size]-1));
551 			ext_is_ram=true;
552 		}
553 		else{
554 			ext_is_ram=false;
555 			mbc3_timer=dat&0x0F;
556 		}
557 		break;
558 	case 3://RTCラッチ // RTC latch
559 		if (dat==0){ // Latchはずす // Disconnect latch
560 			mbc3_latch=0;
561 		}
562 		else if (dat==1){ // データをLatchする // Latch the data to
563 			if (!mbc3_latch){
564 				mbc3_sec=ref_gb->get_renderer()->get_time(8);
565 				mbc3_min=ref_gb->get_renderer()->get_time(9);
566 				mbc3_hour=ref_gb->get_renderer()->get_time(10);
567 				mbc3_dayl=ref_gb->get_renderer()->get_time(11);
568 				mbc3_dayh=ref_gb->get_renderer()->get_time(12);
569 			}
570 			mbc3_latch=1;
571 		}
572 
573 		break;
574 	}
575 }
576 
mbc5_write(word adr,byte dat)577 void mbc::mbc5_write(word adr,byte dat)
578 {
579 	switch(adr>>12){
580 	case 0:
581 	case 1:
582 		break;
583 	case 2:
584 		mbc5_dat&=0x0100;
585 		mbc5_dat|=dat;
586 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*(mbc5_dat&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
587 		break;
588 	case 3:
589 		mbc5_dat&=0x00FF;
590 		mbc5_dat|=(dat&1)<<8;
591 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*(mbc5_dat&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
592 		break;
593 	case 4:
594 	case 5:
595 		if (ref_gb->get_rom()->get_info()->cart_type==0x1C||ref_gb->get_rom()->get_info()->cart_type==0x1D||ref_gb->get_rom()->get_info()->cart_type==0x1E){//Rumble カートリッジ
596 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&0x07&(ram_size_tbl[ref_gb->get_rom()->get_info()->ram_size]-1));
597 			if (dat&0x8)
598 				ref_gb->get_renderer()->set_bibrate(true);
599 			else
600 				ref_gb->get_renderer()->set_bibrate(false);
601 		}
602 		else
603 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&0x0f&(ram_size_tbl[ref_gb->get_rom()->get_info()->ram_size]-1));
604 		break;
605 	}
606 }
607 
mbc7_write(word adr,byte dat)608 void mbc::mbc7_write(word adr,byte dat)
609 {
610 	switch(adr>>13){
611 	case 0:
612 		break;
613 	case 1:
614 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat==0?1:dat)&0x7F&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
615 //		rom_page=ref_gb->get_rom()->get_rom()+0x4000*(dat&0x3f)-0x4000;
616 		break;
617 	case 2:
618 		if (dat<8){
619 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&3);
620 			ext_is_ram=false;
621 		}
622 		else
623 			ext_is_ram=false;
624 		break;
625 	case 3: // 0x40 が モーションセンサーにマップだが、他のものがマップされることは無い。
626 		// But mapped to a motion sensor, but not the other things that will be mapped.
627 		break;
628 	}
629 }
630 
huc1_write(word adr,byte dat)631 void mbc::huc1_write(word adr,byte dat)
632 {
633 	if (huc1_16_8){//16/8モード
634 		switch(adr>>13){
635 		case 0:
636 			break;
637 		case 1:
638 			huc1_dat=(huc1_dat&0x60)+(dat&0x3F);
639 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((huc1_dat==0?1:huc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
640 			break;
641 		case 2:
642 			huc1_dat=((dat<<5)&0x60)+(huc1_dat&0x3F);
643 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((huc1_dat==0?1:huc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
644 			break;
645 		case 3:
646 			if (dat&1)
647 				huc1_16_8=false;
648 			else
649 				huc1_16_8=true;
650 			huc1_dat=0;
651 			break;
652 		}
653 	}
654 	else{//4/32モード
655 		switch(adr>>13){
656 		case 0:
657 			break;
658 		case 1:
659 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat==0?1:dat)&0x3F&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
660 			break;
661 		case 2:
662 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&3);
663 			break;
664 		case 3:
665 			if (dat&1)
666 				huc1_16_8=false;
667 			else
668 				huc1_16_8=true;
669 			huc1_dat=0;
670 			break;
671 		}
672 	}
673 }
674 
huc3_write(word adr,byte dat)675 void mbc::huc3_write(word adr,byte dat)
676 {
677 //	extern FILE *file;
678 //	fprintf(file,"%04X : HuC-3 write %04X <= %02X\n",ref_gb->get_cpu()->get_regs()->PC,adr,dat);
679 	switch(adr>>13){
680 	case 0:
681 		if (dat==0xA)
682 			ext_is_ram=true;
683 		else if (dat==0x0B){
684 			ext_is_ram=false;
685 		}
686 		else if (dat==0x0C){
687 			ext_is_ram=false;
688 		}
689 		else if (dat==0x0D){
690 			ext_is_ram=false;
691 		}
692 		else {
693 			ext_is_ram=false;
694 		}
695 		break;
696 	case 1:
697 		rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat==0?1:dat)&0x7F&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
698 		break;
699 	case 2:
700 		if (dat<8){
701 			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&3);
702 			ext_is_ram=true;
703 		}
704 		else{
705 //			ext_is_ram=false;
706 //			mbc3_timer=dat&0x0F;
707 		}
708 		break;
709 	case 3://RTCラッチ
710 /*		if (dat==0){ // Latchはずす // Disconnect Latch
711 			mbc3_latch=0;
712 		}
713 		else if (dat==1){ // データをLatchする // Latch the data to
714 			if (!mbc3_latch){
715 				mbc3_sec=ref_gb->get_renderer()->get_time(8);
716 				mbc3_min=ref_gb->get_renderer()->get_time(9);
717 				mbc3_hour=ref_gb->get_renderer()->get_time(10);
718 				mbc3_dayl=ref_gb->get_renderer()->get_time(11);
719 				mbc3_dayh=ref_gb->get_renderer()->get_time(12);
720 			}
721 			mbc3_latch=1;
722 		}
723 */
724 		break;
725 	}
726 }
727 
tama5_write(word adr,byte dat)728 void mbc::tama5_write(word adr,byte dat)
729 {
730 //	extern FILE *file;
731 //	fprintf(file,"TAMA5 write %04X <= %02X\n",adr,dat);
732 }
733 
mmm01_write(word adr,byte dat)734 void mbc::mmm01_write(word adr,byte dat)
735 {
736 	if (mbc1_16_8){//16/8モード // 16/8 mode
737 		switch(adr>>13){
738 		case 0:
739 			break;
740 		case 1:
741 			mbc1_dat=(mbc1_dat&0x60)+(dat&0x1F);
742 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((mbc1_dat==0?1:mbc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
743 			break;
744 		case 2:
745 			mbc1_dat=((dat<<5)&0x60)+(mbc1_dat&0x1F);
746 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((mbc1_dat==0?1:mbc1_dat)&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
747 			break;
748 		case 3:
749 			if (dat&1)
750 				mbc1_16_8=false;
751 			else
752 				mbc1_16_8=true;
753 			mbc1_dat=0;
754 			break;
755 		}
756 	}
757 	else{//4/32モード // 4/32 mode
758 		switch(adr>>13){
759 		case 0:
760 			break;
761 		case 1:
762 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*(((dat&3)*0x10+(dat==0?1:dat))&0x0f&(rom_size_tbl[ref_gb->get_rom()->get_info()->rom_size]-1))-0x4000;
763 			break;
764 		case 2:
765 			ref_gb->get_rom()->set_first((dat&3)*0x10);
766 			rom_page=ref_gb->get_rom()->get_rom()+0x4000*((dat&3)*0x10);
767 			mbc1_dat=dat&3;
768 //			sram_page=ref_gb->get_rom()->get_sram()+0x2000*(dat&3);
769 			break;
770 		case 3:
771 			if (dat&1)
772 				mbc1_16_8=false;
773 			else
774 				mbc1_16_8=true;
775 //			mbc1_dat=0;
776 			break;
777 		}
778 	}
779 }
780 
781 
serialize(serializer & s)782 void mbc::serialize(serializer &s)
783 {
784 	byte*  rom = ref_gb->get_rom()->get_rom();
785 	byte* sram = ref_gb->get_rom()->get_sram();
786 
787 	int tmp;
788 
789 	tmp = ( rom_page- rom)/0x4000; s_VAR(tmp);  rom_page =  rom + tmp*0x4000;
790 	tmp = (sram_page-sram)/0x2000; s_VAR(tmp); sram_page = sram + tmp*0x2000;
791 
792 	tmp = get_state(); s_VAR(tmp); set_state(tmp);
793 
794 	s_VAR(ext_is_ram);
795 
796 	// all of the below were originally not in the save state format.
797 	s_VAR(mbc1_16_8);  s_VAR(mbc1_dat);
798 
799 	s_VAR(mbc3_latch); s_VAR(mbc3_sec);  s_VAR(mbc3_min); s_VAR(mbc3_hour);
800 	s_VAR(mbc3_dayl);  s_VAR(mbc3_dayh); s_VAR(mbc3_timer);
801 
802 	s_VAR(mbc5_dat);
803 
804 	s_VAR(mbc7_write_enable);
805 	s_VAR(mbc7_idle);  s_VAR(mbc7_cs);   s_VAR(mbc7_sk);  s_VAR(mbc7_op_code);
806 	s_VAR(mbc7_adr);   s_VAR(mbc7_dat);  s_VAR(mbc7_ret); s_VAR(mbc7_state);
807 	s_VAR(mbc7_buf);   s_VAR(mbc7_count);
808 
809 	s_VAR(huc1_16_8);  s_VAR(huc1_dat);
810 }
811 
812