random warning fixes
[fceu.git] / boards / 164.c
CommitLineData
d97315ac 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
386f5371 4 * Copyright (C) 2002 Xodnizel 2006 CaH4e3
d97315ac 5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
43725da7 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * It seems that 162/163/164 mappers are the same mapper with just different
21 * mapper modes enabled or disabled in software or hardware, need more nanjing
22 * carts
d97315ac 23 */
24
25#include "mapinc.h"
26
43725da7 27static uint8 laststrobe, trigger;
28static uint8 reg[8];
29static uint8 *WRAM=NULL;
30static uint32 WRAMSIZE;
31
32static void(*WSync)(void);
33
d97315ac 34static SFORMAT StateRegs[]=
35{
386f5371 36 {&laststrobe, 1, "STB"},
37 {&trigger, 1, "TRG"},
43725da7 38 {reg, 8, "REGS"},
d97315ac 39 {0}
40};
41
43725da7 42/*
43const EEPROM_interface eeprom_interface. =
44{
45 9, // address bits 9
46 8, // data bits 8
47 "*110", // read 1 10 aaaaaaaaa
48 "*101", // write 1 01 aaaaaaaaa dddddddd
49. "*10000xxxxxxx", // lock 1 00 00xxxxxxx
50 "*10011xxxxxxx", // unlock 1 00 11xxxxxxx
51 1,
52 5
53};
54
55static const EEPROM_interface *intf;
56
57static int serial_count = 0;
58static u8 serial_buffer[SERIAL_BUFFER_LENGTH];
59
60static int eeprom_data_bits;
61static int eeprom_clock_count;
62static int eeprom_read_address;
63static u8 *eeprom_data;
64
65static int latch = 0;
66static int locked = 1;
67static int sending = 0;
68static int reset_line = ASSERT_LINE;
69static int clock_line = ASSERT_LINE;
70static int reset_delay;
71
72void EEPROM_Init(u8 *data, u8 bit)
73{
74 eeprom_data = data;
75 if(bit == 8)
76 intf = &eeprom_interface_93C46_8;
77 else
78 intf = &eeprom_interface_93C46_16;
79}
80
81u8 *EEPROM_GetData()
82{
83 return eeprom_data;
84}
85
86static int EEPROM_command_match(const char *buf, const char *cmd, int len)
87{
88 if ( cmd == 0 ) return 0;
89 if ( len == 0 ) return 0;
90
91 for (;len>0;)
92 {
93 char b = *buf;
94 char c = *cmd;
95
96 if ((b==0) || (c==0))
97 return (b==c);
98
99 switch ( c )
100 {
101 case '0':
102 case '1':
103 if (b != c) return 0;
104 case 'X':
105 case 'x':
106 buf++;
107 len--;
108 cmd++;
109 break;
110
111 case '*':
112 c = cmd[1];
113 switch( c )
114 {
115 case '0':
116 case '1':
117 if (b == c) { cmd++; }
118 else { buf++; len--; }
119 break;
120 default: return 0;
121 }
122 }
123 }
124 return (*cmd==0);
125}
126
127static void EEPROM_write(int bit)
128{
129 if (serial_count >= SERIAL_BUFFER_LENGTH-1)
130 {
131 return;
132 }
133
134 serial_buffer[serial_count++] = (bit ? '1' : '0');
135 serial_buffer[serial_count] = 0;
136
137 if ( (serial_count > intf->address_bits) &&
138 EEPROM_command_match((char*)serial_buffer,intf->cmd_read,(int)strlen((char*)serial_buffer)-intf->address_bits) )
139 {
140 int i,address;
141
142 address = 0;
143 for (i = serial_count-intf->address_bits;i < serial_count;i++)
144 {
145 address <<= 1;
146 if (serial_buffer[i] == '1') address |= 1;
147 }
148 if (intf->data_bits == 16)
149 eeprom_data_bits = (eeprom_data[2*address+0] << 8) + eeprom_data[2*address+1];
150 else
151 eeprom_data_bits = eeprom_data[address];
152 eeprom_read_address = address;
153 eeprom_clock_count = 0;
154 sending = 1;
155 serial_count = 0;
156 }
157 else if ( (serial_count > intf->address_bits) &&
158 EEPROM_command_match((char*)serial_buffer,intf->cmd_erase,(int)strlen((char*)serial_buffer)-intf->address_bits) )
159 {
160 int i,address;
161
162 address = 0;
163 for (i = serial_count-intf->address_bits;i < serial_count;i++)
164 {
165 address <<= 1;
166 if (serial_buffer[i] == '1') address |= 1;
167 }
168
169 if (locked == 0)
170 {
171 if (intf->data_bits == 16)
172 {
173 eeprom_data[2*address+0] = 0x00;
174 eeprom_data[2*address+1] = 0x00;
175 }
176 else
177 eeprom_data[address] = 0x00;
178 }
179 else
180 serial_count = 0;
181 }
182 else if ( (serial_count > (intf->address_bits + intf->data_bits)) &&
183 EEPROM_command_match((char*)serial_buffer,intf->cmd_write,(int)strlen((char*)serial_buffer)-(intf->address_bits + intf->data_bits)) )
184 {
185 int i,address,data;
186
187 address = 0;
188 for (i = serial_count-intf->data_bits-intf->address_bits;i < (serial_count-intf->data_bits);i++)
189 {
190 address <<= 1;
191 if (serial_buffer[i] == '1') address |= 1;
192 }
193 data = 0;
194 for (i = serial_count-intf->data_bits;i < serial_count;i++)
195 {
196 data <<= 1;
197 if (serial_buffer[i] == '1') data |= 1;
198 }
199 if (locked == 0)
200 {
201 if (intf->data_bits == 16)
202 {
203 eeprom_data[2*address+0] = data >> 8;
204 eeprom_data[2*address+1] = data & 0xff;
205 }
206 else
207 eeprom_data[address] = data;
208 }
209 else
210 serial_count = 0;
211 }
212 else if ( EEPROM_command_match((char*)serial_buffer,intf->cmd_lock,(int)strlen((char*)serial_buffer)) )
213 {
214 locked = 1;
215 serial_count = 0;
216 }
217 else if ( EEPROM_command_match((char*)serial_buffer,intf->cmd_unlock,(int)strlen((char*)serial_buffer)) )
218 {
219 locked = 0;
220 serial_count = 0;
221 }
222}
223
224static void EEPROM_reset()
225{
226 serial_count = 0;
227 sending = 0;
228 reset_delay = intf->reset_delay;
229}
230
231void EEPROM_set_cs_line(int state)
232{
233 reset_line = state;
234
235 if (reset_line != CLEAR_LINE)
236 EEPROM_reset();
237}
238
239void EEPROM_set_clock_line(int state)
240{
241 if (state == PULSE_LINE || (clock_line == CLEAR_LINE && state != CLEAR_LINE))
242 {
243 if (reset_line == CLEAR_LINE)
244 {
245 if (sending)
246 {
247 if (eeprom_clock_count == intf->data_bits)
248 {
249 if(intf->enable_multi_read)
250 {
251 eeprom_read_address = (eeprom_read_address + 1) & ((1 << intf->address_bits) - 1);
252 if (intf->data_bits == 16)
253 eeprom_data_bits = (eeprom_data[2*eeprom_read_address+0] << 8) + eeprom_data[2*eeprom_read_address+1];
254 else
255 eeprom_data_bits = eeprom_data[eeprom_read_address];
256 eeprom_clock_count = 0;
257 }
258 else
259 {
260 sending = 0;
261 }
262 }
263 eeprom_data_bits = (eeprom_data_bits << 1) | 1;
264 eeprom_clock_count++;
265 }
266 else
267 EEPROM_write(latch);
268 }
269 }
270
271 clock_line = state;
272}
273
274
275void EEPROM_write_bit(int bit)
276{
277 latch = bit;
278}
279
280int EEPROM_read_bit(void)
281{
282 int res;
283
284 if (sending)
285 res = (eeprom_data_bits >> intf->data_bits) & 1;
286 else
287 {
288 if (reset_delay > 0)
289 {
290 reset_delay--;
291 res = 0;
292 }
293 else
294 res = 1;
295 }
296
297 return res;
298}
299*/
300
d97315ac 301static void Sync(void)
302{
43725da7 303 setprg8r(0x10,0x6000,0);
304 setprg32(0x8000,(reg[0]<<4)|(reg[1]&0xF));
305 setchr8(0);
d97315ac 306}
307
308static void StateRestore(int version)
309{
43725da7 310 WSync();
d97315ac 311}
312
386f5371 313static DECLFR(ReadLow)
314{
315 switch (A&0x7700)
316 {
43725da7 317 case 0x5100: return reg[2]|reg[0]|reg[1]|reg[3]^0xff; break;
386f5371 318 case 0x5500: if(trigger)
43725da7 319 return reg[2]|reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games
386f5371 320 else
321 return 0;
322 }
323 return 4;
324}
325
43725da7 326static void M163HB(void)
327{
328 if(reg[1]&0x80)
329 {
330 if(scanline==239)
331 {
332 setchr4(0x0000,0);
333 setchr4(0x1000,0);
334 }
335 else if(scanline==127)
336 {
337 setchr4(0x0000,1);
338 setchr4(0x1000,1);
339 }
340/*
341 if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it
342 {
343 setchr4(0x0000,1);
344 setchr4(0x1000,1);
345 }
346 else
347 {
348 setchr4(0x0000,0);
349 setchr4(0x1000,0);
350 }
351*/
352 }
353}
354
d97315ac 355static DECLFW(Write)
356{
357 switch (A&0x7300)
358 {
43725da7 359 case 0x5100: reg[0]=V; WSync(); break;
360 case 0x5000: reg[1]=V; WSync(); break;
361 case 0x5300: reg[2]=V; break;
362 case 0x5200: reg[3]=V; WSync(); break;
d97315ac 363 }
364}
365
43725da7 366static void Power(void)
367{
368 memset(reg,0,8);
369 reg[1]=0xFF;
370 SetWriteHandler(0x5000,0x5FFF,Write);
371 SetReadHandler(0x6000,0xFFFF,CartBR);
372 SetWriteHandler(0x6000,0x7FFF,CartBW);
373 WSync();
374}
375
376static void Close(void)
377{
378 if(WRAM)
379 FCEU_gfree(WRAM);
380 WRAM=NULL;
381}
382
383void Mapper164_Init(CartInfo *info)
384{
385 info->Power=Power;
386 info->Close=Close;
387 WSync = Sync;
388
389 WRAMSIZE = 8192;
390 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
391 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
392 AddExState(WRAM, WRAMSIZE, 0, "WRAM");
393
394 if(info->battery)
395 {
396 info->SaveGame[0]=WRAM;
397 info->SaveGameLen[0]=WRAMSIZE;
398 }
399
400 GameStateRestore=StateRestore;
401 AddExState(&StateRegs, ~0, 0, 0);
402}
403
d97315ac 404static DECLFW(Write2)
405{
386f5371 406 if(A==0x5101)
407 {
408 if(laststrobe&&!V)
409 {
410 trigger^=1;
411 }
412 laststrobe=V;
413 }else if(A==0x5100&&V==6) //damn thoose protected games
414 setprg32(0x8000,3);
415 else
d97315ac 416 switch (A&0x7300)
417 {
43725da7 418 case 0x5200: reg[0]=V; WSync(); break;
419 case 0x5000: reg[1]=V; WSync(); if(!(reg[1]&0x80)&&(scanline<128)) setchr8(0); /* setchr8(0); */ break;
420 case 0x5300: reg[2]=V; break;
421 case 0x5100: reg[3]=V; WSync(); break;
d97315ac 422 }
423}
424
43725da7 425static void Power2(void)
d97315ac 426{
43725da7 427 memset(reg,0,8);
428 laststrobe=1;
429 SetReadHandler(0x5000,0x5FFF,ReadLow);
430 SetWriteHandler(0x5000,0x5FFF,Write2);
431 SetReadHandler(0x6000,0xFFFF,CartBR);
432 SetWriteHandler(0x6000,0x7FFF,CartBW);
433 WSync();
d97315ac 434}
435
43725da7 436void Mapper163_Init(CartInfo *info)
d97315ac 437{
43725da7 438 info->Power=Power2;
439 info->Close=Close;
440 WSync = Sync;
441 GameHBIRQHook=M163HB;
442
443 WRAMSIZE = 8192;
444 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
445 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
446 AddExState(WRAM, WRAMSIZE, 0, "WRAM");
447
448 if(info->battery)
449 {
450 info->SaveGame[0]=WRAM;
451 info->SaveGameLen[0]=WRAMSIZE;
452 }
453 GameStateRestore=StateRestore;
454 AddExState(&StateRegs, ~0, 0, 0);
d97315ac 455}
456
43725da7 457static void Sync3(void)
d97315ac 458{
386f5371 459 setchr8(0);
43725da7 460 setprg8r(0x10,0x6000,0);
461 switch(reg[3]&7){
462 case 0:
463 case 2: setprg32(0x8000,(reg[0]&0xc)|(reg[1]&2)|((reg[2]&0xf)<<4)); break;
464 case 1:
465 case 3: setprg32(0x8000,(reg[0]&0xc)|(reg[2]&0xf)<<4); break;
466 case 4:
467 case 6: setprg32(0x8000,(reg[0]&0xe)|((reg[1]>>1)&1)|((reg[2]&0xf)<<4)); break;
468 case 5:
469 case 7: setprg32(0x8000,(reg[0]&0xf)|((reg[2]&0xf)<<4)); break;
470 }
d97315ac 471}
472
43725da7 473static DECLFW(Write3)
e2d0dd92 474{
43725da7 475// FCEU_printf("bs %04x %02x\n",A,V);
476 reg[(A>>8)&3]=V;
477 WSync();
e2d0dd92 478}
479
43725da7 480static void Power3(void)
d97315ac 481{
43725da7 482 reg[0]=3;
483 reg[1]=0;
484 reg[2]=0;
485 reg[3]=7;
486 SetWriteHandler(0x5000,0x5FFF,Write3);
487 SetReadHandler(0x6000,0xFFFF,CartBR);
488 SetWriteHandler(0x6000,0x7FFF,CartBW);
489 WSync();
d97315ac 490}
491
43725da7 492void UNLFS304_Init(CartInfo *info)
d97315ac 493{
43725da7 494 info->Power=Power3;
495 info->Close=Close;
496 WSync = Sync3;
497
498 WRAMSIZE = 8192;
499 WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
500 SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
501 AddExState(WRAM, WRAMSIZE, 0, "WRAM");
d97315ac 502
43725da7 503 if(info->battery)
504 {
505 info->SaveGame[0]=WRAM;
506 info->SaveGameLen[0]=WRAMSIZE;
507 }
508
d97315ac 509 GameStateRestore=StateRestore;
510 AddExState(&StateRegs, ~0, 0, 0);
511}