OSDN Git Service

client 0.6.0 release
[unagi/old-svn-converted.git] / client / tag / 0.6.0 / reader_hongkongfc.c
1 /*
2 famicom ROM cartridge utility - unagi
3 hongkong FC driver
4
5 Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 »ÅÍÍÉÔÌÀÍ×ÁÇ:
22   * 74138 ¤Î channel select ¤À¤¬¡¢¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Î¥Ç¡¼¥¿¤ÎÊý¸þ¤òÊѹ¹¤¹¤ë¤È¡¢ÆÃÄê¤Î¥Á¥ã¥ó¥Í¥ë¤Î¥Ç¡¼¥¿¤¬Ç˲õ¤µ¤ì¤ë
23     * Ç˲õ¤µ¤ì¤ë¤¬¡¢Ç˲õÀ褬ÀßÄê¤Ç¤­¤ë¤é¤·¤¯¤½¤ì¤Ë¤·¤¿
24 */
25 #include "type.h"
26 #include "paralellport.h"
27 #include "reader_master.h"
28 #include "reader_hongkongfc.h"
29 #include "hard_hongkongfc.h"
30
31 enum{
32         PORT_CONTROL_MASK_XOR = 0x03, //bit01 invert
33         PORT_CONTROL_READ = 0,
34         PORT_CONTROL_WRITE
35 };
36
37 static inline int busy_get(void)
38 {
39         int d = _inp(PORT_BUSY);
40         d >>= 7;
41         return d ^ 1;
42 }
43
44 static inline void port_control_write(int s, int rw)
45 {
46         if(rw == PORT_CONTROL_READ){ 
47                 //H:BUS->PC
48                 s = bit_set(s, BITNUM_CONTROL_DIRECTION);
49         }else{
50                 //L:PC->BUS
51                 s = bit_clear(s, BITNUM_CONTROL_DIRECTION);
52         }
53         s = bit_clear(s, BITNUM_CONTROL_INTERRUPT);
54         s ^= PORT_CONTROL_MASK_XOR;
55         _outp(PORT_CONTROL, s);
56 }
57
58 static inline void data_port_latch(int select, long data)
59 {
60         select <<= BITNUM_CONTROL_DATA_SELECT;
61         select = bit_set(select, BITNUM_CONTROL_DATA_LATCH);
62         port_control_write(select, PORT_CONTROL_WRITE);
63         _outp(PORT_DATA, data);
64         select = bit_clear(select, BITNUM_CONTROL_DATA_LATCH);
65         port_control_write(select, PORT_CONTROL_WRITE);
66 }
67
68 enum{ADDRESS_CPU_OPEN, ADDRESS_CPU_CLOSE};
69 static inline void address_set(long address)
70 {
71         long address_h = address >> 8;
72         long address_l = address & 0xff;
73         data_port_latch(DATA_SELECT_A15toA8, address_h);
74         data_port_latch(DATA_SELECT_A7toA0, address_l);
75 }
76
77 static inline u8 data_port_get(long address, int bus)
78 {
79         address_set(address);
80         if(bus != 0){
81                 data_port_latch(DATA_SELECT_CONTROL, bus);
82         }
83         port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
84         int s = DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT;
85         s = bit_set(s, BITNUM_CONTROL_DATA_LATCH);
86         port_control_write(s, PORT_CONTROL_READ);
87         return (u8) _inp(PORT_DATA);
88 }
89
90 /*
91 ËÜÂΠA23-A16 port ¤Ë latch ¤µ¤»¤¿¤¢¤È¤Ë¡¢
92 fc adapater ÆâÉô¤Ë¤µ¤é¤Ë latch ¤µ¤»¤ë¡£
93 */
94 static void data_port_set(int c, long data)
95 {
96         data_port_latch(DATA_SELECT_WRITEDATA, data);
97         data_port_latch(DATA_SELECT_CONTROL, c);
98         c = bit_set(c, BITNUM_WRITEDATA_LATCH);
99         data_port_latch(DATA_SELECT_CONTROL, c);
100 }
101
102 // /A15 ¤À¤±¤ò»ÈÍѤ¹¤ë
103 static const int BUS_CONTROL_CPU_READ = (
104         (1 << BITNUM_PPU_OUTPUT) |
105         (1 << BITNUM_PPU_RW) |
106         (1 << BITNUM_PPU_SELECT) |
107         (1 << BITNUM_WRITEDATA_OUTPUT) |
108         (0 << BITNUM_WRITEDATA_LATCH) |
109         (1 << BITNUM_CPU_M2) |
110         (1 << BITNUM_CPU_RW)
111 );
112 static const int BUS_CONTROL_PPU_READ = (
113         (0 << BITNUM_PPU_OUTPUT) |
114         (1 << BITNUM_PPU_RW) |
115         (0 << BITNUM_PPU_SELECT) |
116         (1 << BITNUM_WRITEDATA_OUTPUT) |
117         (0 << BITNUM_WRITEDATA_LATCH) |
118         (1 << BITNUM_CPU_M2) |
119         (1 << BITNUM_CPU_RW)
120 );
121 //static const int BUS_CONTROL_BUS_STANDBY = BUS_CONTROL_CPU_READ; //¥¨¥é¡¼¤Ë¤Ê¤ë
122 #define BUS_CONTROL_BUS_STANDBY BUS_CONTROL_CPU_READ
123 /*
124 namcot ¤Î SRAM ÉÕ¥«¡¼¥È¥ê¥Ã¥¸¤Ï¦Õ2¤ò0x80²ó¾å¤²¤ë¤È½ÐÎϤ¬°ÂÄꤹ¤ë
125 RAM ¥¢¥À¥×¥¿¤âƱÍÍ??
126 ÉÔ°ÂÄê»þ¤Ï CPU ¤È PPU ¤Î data ¤¬º®¹ç¤µ¤ì¤Æ¤¤¤ëʪ¤¬¤Ç¤Æ¤¤¤ëµ¤¤¬¤¹¤ë
127 */
128 static void hk_init(void)
129 {
130         int c = BUS_CONTROL_CPU_READ;
131         int i = 0x80;
132         while(i != 0){
133                 c = bit_set(c, BITNUM_CPU_M2);
134                 data_port_latch(DATA_SELECT_CONTROL, c);
135                 c = bit_clear(c, BITNUM_CPU_M2);
136                 data_port_latch(DATA_SELECT_CONTROL, c);
137                 i--;
138         }
139 }
140
141 static void hk_cpu_read(long address, long length, u8 *data)
142 {
143         //fc bus ½é´ü²½
144         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
145         //A15 ¤òȿž¤·¡¢ /ROMCS ¤Ë¤·¤¿¤â¤Î¤òÅϤ¹
146         address ^= ADDRESS_MASK_A15;
147         while(length != 0){
148                 *data = data_port_get(address, 0);
149                 address++;
150                 data++;
151                 length--;
152         }
153 }
154
155 //patch. charcter ¤Î½ñ¤­¹þ¤ß¤Î°ÂÄ꤬²þÁ±¤µ¤ì¤¿¤éºï½ü¤¹¤ë
156 int hongkong_flash_patch = 0;
157 static void hk_ppu_read(long address, long length, u8 *data)
158 {
159         if(hongkong_flash_patch == 0){
160                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
161         }else{
162                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
163         }
164         
165         address &= ADDRESS_MASK_A0toA12; //PPU charcter data area mask
166         address |= ADDRESS_MASK_A15; //CPU area disk
167         while(length != 0){
168                 if(hongkong_flash_patch == 0){
169                         *data = data_port_get(address, BUS_CONTROL_PPU_READ);
170                 }else{
171                         *data = data_port_get(address, 0); 
172                 }
173                 address++;
174                 data++;
175                 length--;
176                 if(hongkong_flash_patch == 0){
177                         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
178                 }
179         }
180 }
181
182 static inline void cpu_romcs_set(long address)
183 {
184         data_port_latch(DATA_SELECT_A15toA8, address >> 8);
185 }
186
187 static void hk_cpu_write_6502(long address, long length, const uint8_t *data)
188 {
189         while(length != 0){
190                 int c = BUS_CONTROL_BUS_STANDBY;
191                 //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
192                 data_port_latch(DATA_SELECT_CONTROL, c);
193                 // /rom ¤ò H ¤Ë¤·¤Æ¥Ð¥¹¤ò»ß¤á¤ë
194                 address_set(address | ADDRESS_MASK_A15);
195                 
196                 //¦Õ2 = L, R/W=L, address set, data set
197                 c = bit_clear(c, BITNUM_CPU_M2);
198                 data_port_set(c, *data); //latch¤Ï¤³¤Î´Ø¿ôÆâÉô¤Ç¹Ô¤¦
199                 if(address & ADDRESS_MASK_A15){
200                         cpu_romcs_set(address & ADDRESS_MASK_A0toA14);
201                 }
202                 c = bit_clear(c, BITNUM_CPU_RW);
203                 data_port_latch(DATA_SELECT_CONTROL, c);
204                 //wait(wait_msec);
205                 //¦Õ2 = H, data out
206                 c = bit_set(c, BITNUM_CPU_M2);
207                 c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
208                 data_port_latch(DATA_SELECT_CONTROL, c);
209                 //wait(wait_msec);
210                 //¦Õ2 = L, H ¤Ë¤¹¤ë¤Þ¤Ç R/W, address, Data ¤òÍ­¸ú¾õÂ֤ˤ¹¤ë
211                 c = bit_clear(c, BITNUM_CPU_M2);
212                 data_port_latch(DATA_SELECT_CONTROL, c);
213                 //wait(wait_msec);
214                 //¦Õ2 = H, R/W = H, address disable, data out disable
215                 if(address & ADDRESS_MASK_A15){
216                         //address & ADDRESS_MASK_A15 ¤ÇÆ°¤¤¤Æ¤¿..?
217                         cpu_romcs_set(address | ADDRESS_MASK_A15);
218                 }
219                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
220                 address += 1;
221                 data += 1;
222                 length -= 1;
223         }
224 }
225
226 //onajimi ¤À¤È /CS ¤È /OE ¤¬Æ±¤¸¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¢hongkong¤À¤È»ß¤á¤é¤ì¤ë¡£½ñ¤­¹þ¤ß»þ¤Ë output enable ¤Ï H ¤Ç¤¢¤ë¤Ù¤­¡£
227 static void hk_ppu_write(long address, long length, const uint8_t *data)
228 {
229         while(address != 0){
230                 int c = BUS_CONTROL_BUS_STANDBY;
231                 c = bit_clear(c, BITNUM_CPU_M2); //¤¿¤Ö¤ó¤¤¤ë
232                 //c = bit_clear(c, BITNUM_CPU_RW);
233                 data_port_latch(DATA_SELECT_CONTROL, c);
234                 //cpu rom ¤ò»ß¤á¤¿¥¢¥É¥ì¥¹¤òÅϤ¹
235                 address_set((address & ADDRESS_MASK_A0toA12) | ADDRESS_MASK_A15);
236                 data_port_set(c, *data); 
237         //      data_port_latch(DATA_SELECT_CONTROL, c);
238                 //CS down
239                 c = bit_clear(c, BITNUM_PPU_SELECT);
240                 data_port_latch(DATA_SELECT_CONTROL, c);
241                 //WE down
242                 c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
243                 c = bit_clear(c, BITNUM_PPU_RW);
244                 data_port_latch(DATA_SELECT_CONTROL, c);
245                 //WE up
246                 c = bit_set(c, BITNUM_PPU_RW);
247                 data_port_latch(DATA_SELECT_CONTROL, c);
248                 //CS up
249         //      c = bit_set(c, BITNUM_WRITEDATA_OUTPUT);
250                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
251                 
252                 address += 1;
253                 data += 1;
254                 length -= 1;
255         }
256 }
257
258 #if 0
259 static const int FLASH_CPU_WRITE = (
260         (1 << BITNUM_PPU_OUTPUT) |
261         (1 << BITNUM_PPU_RW) |
262         (1 << BITNUM_PPU_SELECT) |
263         (1 << BITNUM_WRITEDATA_OUTPUT) |
264         (0 << BITNUM_WRITEDATA_LATCH) |
265         (0 << BITNUM_CPU_M2) |
266         (1 << BITNUM_CPU_RW)
267 );
268
269 static void hk_cpu_flash_write(long address, long data)
270 {
271         int c = FLASH_CPU_WRITE;
272         //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
273         data_port_latch(DATA_SELECT_CONTROL, c);
274         address_set(address | ADDRESS_MASK_A15);
275         data_port_set(c, data);
276 /*
277 W29C020
278 During the byte-load cycle, the addresses are latched by the falling 
279 edge of either CE or WE,whichever occurs last. The data are latched 
280 by the rising edge of either CE or WE, whicheveroccurs first.
281 W49F002
282 #CS or #WE ¤¬¹ß¤ê¤¿¤È¤­¤Ë address latch
283 #CS or #WE ¤¬¾å¤¬¤Ã¤¿¤È¤­¤Ë data latch
284
285 hongkong ·Ï¤Ï address ¤È /ROMCS ¤¬Æ±¤¸¥Ð¥¤¥È¤Ç¡¢ /CS À©¸æ¤Ë¤¹¤ë¤È
286 hongkong ¥Ç¡¼¥¿Ç˲õ+¥¢¥É¥ì¥¹ÉÔ°ÂÄê¤Ë¤Ê¤ë¤Î¤Ç¡¢/WE À©¸æ¤Ë¤·¤Ê¤¤¤ÈÆ°¤«¤Ê¤¤¡£
287 */
288         //CS down
289         cpu_romcs_set(address & ADDRESS_MASK_A0toA14);
290         //WE down
291         c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
292         c = bit_clear(c, BITNUM_CPU_RW);
293 //      c = bit_clear(c, BITNUM_CPU_M2);
294         data_port_latch(DATA_SELECT_CONTROL, c);
295         //WE up
296         data_port_latch(DATA_SELECT_CONTROL, FLASH_CPU_WRITE);
297         //CS up
298         cpu_romcs_set(address | ADDRESS_MASK_A15);
299 }
300 #endif
301
302 const struct reader_driver DRIVER_HONGKONGFC = {
303         .name = "hongkongfc",
304         .open_or_close = paralellport_open_or_close,
305         .init = hk_init,
306         .cpu_read = hk_cpu_read,
307         .ppu_read = hk_ppu_read,
308         .cpu_write_6502 = hk_cpu_write_6502,
309         .ppu_write = hk_ppu_write,
310         .flash_support = NG,
311         .cpu_flash_config = NULL, .cpu_flash_erase = NULL, .cpu_flash_program = NULL,
312         .ppu_flash_config = NULL, .ppu_flash_erase = NULL, .ppu_flash_program = NULL
313 };
314
315 #ifdef TEST
316 #include "giveio.h"
317 #include <stdio.h>
318 #include <stdlib.h>
319 static void data_show(u8 *d, int length)
320 {
321         int sum = 0;
322         int offset = 0;
323         while(length != 0){
324                 char safix;
325                 switch(offset & 0xf){
326                 default:
327                         safix = ' ';
328                         break;
329                 case 7:
330                         safix = '-';
331                         break;
332                 case 0xf:
333                         safix = '\n';
334                         break;
335                 }
336                 printf("%02x%c", *d, safix);
337                 sum += *d;
338                 d++;
339                 offset++;
340                 length--;
341         }
342         printf("sum 0x%06x", sum);
343 }
344
345 int main(int c, char **v)
346 {
347         const int gg = giveio_start();
348         switch(gg){
349         case GIVEIO_OPEN:
350         case GIVEIO_START:
351         case GIVEIO_WIN95:
352                 break;
353         default:
354         case GIVEIO_ERROR:
355                 printf("Can't Access Direct IO %d\n", gg);
356                 return 0;
357         }
358
359         long d = strtol(v[2], NULL, 0x10);
360
361         switch(v[1][0]){
362         case 'w':
363                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_STANDBY);
364                 port_control_write(DATA_SELECT_WRITE << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
365                 _outp(PORT_DATA, d);
366                 break;
367         case 'c':
368                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
369                 address_set(d ^ ADDRESS_MASK_A15);
370                 port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
371                 port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
372                 printf("%02x\n", _inp(PORT_DATA));
373                 break;
374         case 'C':{
375                 const long length = 0x1000;
376                 u8 data[length];
377                 hk_cpu_read(d, length, data);
378                 data_show(data, length);
379                 }
380                 break;
381         case 'p':
382                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
383                 address_set(d | ADDRESS_MASK_A15, ADDRESS_RESET);
384                 port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
385                 printf("%02x\n", _inp(PORT_DATA));
386                 break;
387         case 'P':{
388                 const long length = 0x200;
389                 u8 data[length];
390                 hk_ppu_read(d, length, data);
391                 data_show(data, length);
392                 }
393                 break;
394         }
395         
396         if(gg != GIVEIO_WIN95){
397                 giveio_stop(GIVEIO_STOP);
398         }
399         return 0;
400 }
401 #endif