12-in-1 + realtec mapper
[picodrive.git] / Pico / carthw / carthw.c
1 /*
2  * should better do some pointer stuff here. But as none of these bankswitch
3  * while the game runs, memcpy will suffice.
4  */
5
6 #include "../PicoInt.h"
7
8
9 /* 12-in-1 and 4-in-1. Assuming 2MB ROMs here. */
10 static unsigned int carthw_12in1_read16(unsigned int a, int realsize)
11 {
12         // ??
13         elprintf(EL_UIO, "12-in-1: read [%06x] @ %06x", a, SekPc);
14         return 0;
15 }
16
17 static void carthw_12in1_write8(unsigned int a, unsigned int d, int realsize)
18 {
19         int len;
20
21         if (a < 0xA13000 || a >= 0xA13040) {
22                 /* 4-in-1 has Real Deal Boxing, which uses serial eeprom,
23                  * but I really doubt that pirate cart had it */
24                 if (a != 0x200001)
25                         elprintf(EL_ANOMALY, "12-in-1: unexpected write [%06x] %02x @ %06x", a, d, SekPc);
26                 return;
27         }
28
29         a &= 0x3f; a <<= 16;
30         len = Pico.romsize - a;
31         if (len <= 0) {
32                 elprintf(EL_ANOMALY, "12-in-1: missing bank @ %06x", a);
33                 return;
34         }
35
36         memcpy(Pico.rom, Pico.rom + Pico.romsize + a, len);
37 }
38
39 static void carthw_12in1_reset(void)
40 {
41         carthw_12in1_write8(0xA13000, 0, 0);
42 }
43
44 void carthw_12in1_startup(void)
45 {
46         void *tmp;
47
48         elprintf(EL_STATUS, "12-in-1 mapper detected");
49
50         tmp = realloc(Pico.rom, Pico.romsize * 2);
51         if (tmp == NULL)
52         {
53                 elprintf(EL_STATUS, "OOM");
54                 return;
55         }
56         Pico.rom = tmp;
57         memcpy(Pico.rom + Pico.romsize, Pico.rom, Pico.romsize);
58
59         PicoRead16Hook = carthw_12in1_read16;
60         PicoWrite8Hook = carthw_12in1_write8;
61         PicoResetHook  = carthw_12in1_reset;
62 }
63
64
65 /* Realtec, based on TascoDLX doc
66  * http://www.sharemation.com/TascoDLX/REALTEC%20Cart%20Mapper%20-%20description%20v1.txt
67  */
68 static int realtec_bank = 0x80000000, realtec_size = 0x80000000;
69 static int realtec_romsize = 0;
70
71 static void carthw_realtec_write8(unsigned int a, unsigned int d, int realsize)
72 {
73         int i, bank_old = realtec_bank, size_old = realtec_size;
74
75         if (a == 0x400000)
76         {
77                 realtec_bank &= 0x0e0000;
78                 realtec_bank |= 0x300000 & (d << 19);
79                 if (realtec_bank != bank_old)
80                         elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
81         }
82         else if (a == 0x402000)
83         {
84                 realtec_size = (d << 17) & 0x3e0000;
85                 if (realtec_size != size_old)
86                         elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
87         }
88         else if (a == 0x404000)
89         {
90                 realtec_bank &= 0x300000;
91                 realtec_bank |= 0x0e0000 & (d << 17);
92                 if (realtec_bank != bank_old)
93                         elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
94         }
95         else
96                 elprintf(EL_ANOMALY, "realtec: unexpected write [%06x] %02x @ %06x", a, d, SekPc);
97         
98         if (realtec_bank >= 0 && realtec_size >= 0 &&
99                 (realtec_bank != bank_old || realtec_size != size_old))
100         {
101                 elprintf(EL_ANOMALY, "realtec: new bank %06x, size %06x", realtec_bank, realtec_size, SekPc);
102                 if (realtec_size > realtec_romsize - realtec_bank || realtec_bank >= realtec_romsize)
103                 {
104                         elprintf(EL_ANOMALY, "realtec: bank too large / out of range?");
105                         return;
106                 }
107
108                 for (i = 0; i < 0x400000; i += realtec_size)
109                         memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_bank, realtec_size);
110         }
111 }
112
113 void carthw_realtec_reset(void)
114 {
115         int i;
116         /* map boot code */
117         for (i = 0; i < 0x400000; i += 0x2000)
118                 memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_romsize - 0x2000, 0x2000);
119         realtec_bank = realtec_size = 0x80000000;
120 }
121
122 void carthw_realtec_startup(void)
123 {
124         void *tmp;
125
126         elprintf(EL_STATUS, "Realtec mapper detected");
127
128         realtec_romsize = Pico.romsize;
129         Pico.romsize = 0x400000;
130         tmp = realloc(Pico.rom, 0x400000 + realtec_romsize);
131         if (tmp == NULL)
132         {
133                 elprintf(EL_STATUS, "OOM");
134                 return;
135         }
136         Pico.rom = tmp;
137         memcpy(Pico.rom + 0x400000, Pico.rom, realtec_romsize);
138
139         PicoWrite8Hook = carthw_realtec_write8;
140         PicoResetHook = carthw_realtec_reset;
141 }
142