OSDN Git Service

ファイル名変更: driver_*.[ch] -> reader_*.[ch]
[unagi/old-svn-converted.git] / client / trunk / reader_hongkongfc.c
1 /*
2 famicom ROM cartridge utility - unagi
3 hongkong FC driver
4
5 Copyright (C) 2008  sato_tiff
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_RESET, ADDRESS_SET};
69 /*¤³¤ì¤â¥Ý¡¼¥ÈÇ˲õ¤¬µ¯¤³¤ë¤Î¤«¤Á¤ã¤ó¤ÈÆ°¤«¤Ê¤¤
70 static inline void address_set(long address, int reset)
71 {
72         static long last_address_h, last_address_l;
73         long address_h = address >> 8;
74         long address_l = address & 0xff;
75         if(reset == ADDRESS_RESET){
76                 data_port_latch(DATA_SELECT_A15toA8, address_h);
77                 data_port_latch(DATA_SELECT_A7toA0, address_l);
78         }else{
79                 if(last_address_h != address_h){
80                         data_port_latch(DATA_SELECT_A15toA8, address_h);
81                 }
82                 if(last_address_l != address_l){
83                         data_port_latch(DATA_SELECT_A7toA0, address_l);
84                 }
85         }
86         last_address_h = address_h;
87         last_address_l = address_l;
88 }
89 */
90 static inline void address_set(long address, int reset)
91 {
92         long address_h = address >> 8;
93         long address_l = address & 0xff;
94         data_port_latch(DATA_SELECT_A15toA8, address_h);
95         data_port_latch(DATA_SELECT_A7toA0, address_l);
96 }
97 static inline u8 data_port_get(long address, int bus, int m2)
98 {
99         if(0){ 
100                 // at VRC4d
101                 //¦Õ2 control ¤òÆþ¤ì¤ë¤È²¿¸Î¤«CPU¥¢¥É¥ì¥¹ $8090 ¤Ç¥Ð¥ó¥¯¤¬ÀÚ¤êÂؤï¤ë???
102                 //PPU area ¤ÏÂç¾æÉ×
103                 if(address == (0x8090 ^ ADDRESS_MASK_A15)){
104                         //debug break point
105                 }
106                 address_set(address, ADDRESS_SET);
107                 if(m2 == M2_CONTROL_TRUE){
108                         bus = bit_clear(bus, BITNUM_CPU_M2);
109                 }
110                 data_port_latch(DATA_SELECT_CONTROL, bus);
111                 if(m2 == M2_CONTROL_TRUE){
112                         bus = bit_set(bus, BITNUM_CPU_M2);
113                         data_port_latch(DATA_SELECT_CONTROL, bus);
114                 }
115         }else{
116                 address_set(address, ADDRESS_SET);
117         }
118         port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
119         int s = DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT;
120         s = bit_set(s, BITNUM_CONTROL_DATA_LATCH);
121         port_control_write(s, PORT_CONTROL_READ);
122         return (u8) _inp(PORT_DATA);
123 }
124
125 /*
126 ËÜÂΠA23-A16 port ¤Ë latch ¤µ¤»¤¿¤¢¤È¤Ë¡¢
127 fc adapater ÆâÉô¤Ë¤µ¤é¤Ë latch ¤µ¤»¤ë¡£
128 */
129 static void data_port_set(int c, long data)
130 {
131         data_port_latch(DATA_SELECT_WRITEDATA, data);
132         data_port_latch(DATA_SELECT_CONTROL, c);
133         c = bit_set(c, BITNUM_WRITEDATA_LATCH);
134         data_port_latch(DATA_SELECT_CONTROL, c);
135 }
136
137 // /A15 ¤À¤±¤ò»ÈÍѤ¹¤ë
138 static const int BUS_CONTROL_CPU_READ = (
139         (1 << BITNUM_PPU_OUTPUT) |
140         (1 << BITNUM_PPU_RW) |
141         (1 << BITNUM_PPU_SELECT) |
142         (1 << BITNUM_WRITEDATA_OUTPUT) |
143         (0 << BITNUM_WRITEDATA_LATCH) |
144         (1 << BITNUM_CPU_M2) |
145         (1 << BITNUM_CPU_RW)
146 );
147 static const int BUS_CONTROL_PPU_READ = (
148         (0 << BITNUM_PPU_OUTPUT) |
149         (1 << BITNUM_PPU_RW) |
150         (0 << BITNUM_PPU_SELECT) |
151         (1 << BITNUM_WRITEDATA_OUTPUT) |
152         (0 << BITNUM_WRITEDATA_LATCH) |
153         (0 << BITNUM_CPU_M2) |
154         (1 << BITNUM_CPU_RW)
155 );
156 //static const int BUS_CONTROL_BUS_WRITE = BUS_CONTROL_CPU_READ; //¥¨¥é¡¼¤Ë¤Ê¤ë
157 #define BUS_CONTROL_BUS_WRITE BUS_CONTROL_CPU_READ
158 /*
159 namcot ¤Î SRAM ÉÕ¥«¡¼¥È¥ê¥Ã¥¸¤Ï¦Õ2¤ò0x80²ó¾å¤²¤ë¤È½ÐÎϤ¬°ÂÄꤹ¤ë
160 RAM ¥¢¥À¥×¥¿¤âƱÍÍ??
161 ÉÔ°ÂÄê»þ¤Ï CPU ¤È PPU ¤Î data ¤¬º®¹ç¤µ¤ì¤Æ¤¤¤ëʪ¤¬¤Ç¤Æ¤¤¤ëµ¤¤¬¤¹¤ë
162 */
163 static void hk_init(void)
164 {
165         int c = BUS_CONTROL_CPU_READ;
166         int i = 0x80;
167         while(i != 0){
168                 c = bit_set(c, BITNUM_CPU_M2);
169                 data_port_latch(DATA_SELECT_CONTROL, c);
170                 c = bit_clear(c, BITNUM_CPU_M2);
171                 data_port_latch(DATA_SELECT_CONTROL, c);
172                 i--;
173         }
174         if(0){
175                 address_set(0, ADDRESS_RESET);
176         }
177 }
178
179 static void hk_cpu_read(long address, long length, u8 *data)
180 {
181         //fc bus ½é´ü²½
182         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
183         //A15 ¤òȿž¤·¡¢ /ROMCS ¤Ë¤·¤¿¤â¤Î¤òÅϤ¹
184         address ^= ADDRESS_MASK_A15;
185         while(length != 0){
186                 *data = data_port_get(address, BUS_CONTROL_CPU_READ, M2_CONTROL_FALSE);
187                 address++;
188                 data++;
189                 length--;
190         }
191 }
192
193 static void hk_ppu_read(long address, long length, u8 *data)
194 {
195         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
196         address &= ADDRESS_MASK_A0toA12; //PPU charcter data area mask
197         address |= ADDRESS_MASK_A15; //CPU area disk
198         while(length != 0){
199                 *data = data_port_get(address, BUS_CONTROL_PPU_READ, M2_CONTROL_FALSE);
200                 address++;
201                 data++;
202                 length--;
203         }
204 }
205
206 static void hk_cpu_6502_write(long address, long data)
207 {
208         int c = BUS_CONTROL_BUS_WRITE;
209         //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
210         data_port_latch(DATA_SELECT_CONTROL, c);
211         // /rom ¤ò H ¤Ë¤·¤Æ¥Ð¥¹¤ò»ß¤á¤ë
212         address_set(address | ADDRESS_MASK_A15, ADDRESS_SET);
213         
214         //1 H->L bus:data set, mapper:address get
215         c = bit_clear(c, BITNUM_CPU_M2);
216         data_port_set(c, data); //latch¤Ï¤³¤Î´Ø¿ôÆâÉô¤Ç¹Ô¤¦
217         c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
218         data_port_latch(DATA_SELECT_CONTROL, c);
219         //2 L->H bus:data write
220         //ROM Îΰè¤Î¾ì¹ç¤Ï¤³¤Î¥¿¥¤¥ß¥ó¥°¤Ç /rom ¤òÍî¤È¤¹
221         if(address & ADDRESS_MASK_A15){
222                 address_set(address & ADDRESS_MASK_A0toA14, ADDRESS_SET);
223         }
224         c = bit_clear(c, BITNUM_CPU_RW);
225         c = bit_set(c, BITNUM_CPU_M2);
226         data_port_latch(DATA_SELECT_CONTROL, c);
227         //3 H->L mapper: data write enable
228         c = bit_clear(c, BITNUM_CPU_M2);
229         data_port_latch(DATA_SELECT_CONTROL, c);
230         //4 L->H mapper: data get, bus:close
231         if(address & ADDRESS_MASK_A15){
232                 address_set(address | ADDRESS_MASK_A15, ADDRESS_SET);
233         }
234         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_WRITE);
235 }
236
237 //onajimi ¤À¤È /CS ¤È /OE ¤¬Æ±¤¸¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¬¡¢hongkong¤À¤È»ß¤á¤é¤ì¤ë¡£½ñ¤­¹þ¤ß»þ¤Ë output enable ¤Ï H ¤Ç¤¢¤ë¤Ù¤­¡£
238 static void hk_ppu_write(long address, long data)
239 {
240         int c = BUS_CONTROL_BUS_WRITE;
241         c = bit_clear(c, BITNUM_CPU_M2); //¤¿¤Ö¤ó¤¤¤ë
242         data_port_latch(DATA_SELECT_CONTROL, c);
243         //cpu rom ¤ò»ß¤á¤¿¥¢¥É¥ì¥¹¤òÅϤ¹
244         address_set((address & ADDRESS_MASK_A0toA12) | ADDRESS_MASK_A15, ADDRESS_SET);
245         data_port_set(c, data); 
246         c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
247         //WE down
248         c = bit_clear(c, BITNUM_PPU_RW);
249         data_port_latch(DATA_SELECT_CONTROL, c);
250         //CS down
251         c = bit_clear(c, BITNUM_PPU_SELECT);
252         data_port_latch(DATA_SELECT_CONTROL, c);
253         //CS up
254         c = bit_set(c, BITNUM_PPU_SELECT);
255         data_port_latch(DATA_SELECT_CONTROL, c);
256         //WE up
257         data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_WRITE);
258 }
259
260 static const int FLASH_CPU_WRITE = (
261         (1 << BITNUM_PPU_OUTPUT) |
262         (1 << BITNUM_PPU_RW) |
263         (1 << BITNUM_PPU_SELECT) |
264         (1 << BITNUM_WRITEDATA_OUTPUT) |
265         (0 << BITNUM_WRITEDATA_LATCH) |
266         (0 << BITNUM_CPU_M2) |
267         (1 << BITNUM_CPU_RW)
268 );
269
270 static void hk_cpu_flash_write(long address, long data)
271 {
272         int c = FLASH_CPU_WRITE;
273         //Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
274         data_port_latch(DATA_SELECT_CONTROL, c);
275         address_set(address | ADDRESS_MASK_A15, ADDRESS_SET);
276         data_port_set(c, data);
277 /*
278 W29C020
279 During the byte-load cycle, the addresses are latched by the falling 
280 edge of either CE or WE,whichever occurs last. The data are latched 
281 by the rising edge of either CE or WE, whicheveroccurs first.
282 */
283 /*
284 W49F002
285 #CS or #WE ¤¬¹ß¤ê¤¿¤È¤­¤Ë address latch
286 #CS or #WE ¤¬¾å¤¬¤Ã¤¿¤È¤­¤Ë data latch
287 */
288         c = bit_clear(c, BITNUM_WRITEDATA_OUTPUT);
289         //WE down
290         c = bit_clear(c, BITNUM_CPU_RW);
291 //      c = bit_clear(c, BITNUM_CPU_M2);
292         data_port_latch(DATA_SELECT_CONTROL, c);
293         //CS down
294         address_set(address & ADDRESS_MASK_A0toA14, ADDRESS_SET);
295         //CS up
296         address_set(address | ADDRESS_MASK_A15, ADDRESS_SET);
297         //WE up
298         data_port_latch(DATA_SELECT_CONTROL, FLASH_CPU_WRITE);
299 }
300
301 const struct reader_driver DRIVER_HONGKONGFC = {
302         name: "hongkongfc",
303         init: hk_init,
304         cpu_read: hk_cpu_read,
305         ppu_read: hk_ppu_read,
306         cpu_6502_write: hk_cpu_6502_write,
307         ppu_write: hk_ppu_write,
308         cpu_flash_write: hk_cpu_flash_write
309 };
310
311 #ifdef TEST
312 #include "giveio.h"
313 #include <stdio.h>
314 #include <stdlib.h>
315 static void data_show(u8 *d, int length)
316 {
317         int sum = 0;
318         int offset = 0;
319         while(length != 0){
320                 char safix;
321                 switch(offset & 0xf){
322                 default:
323                         safix = ' ';
324                         break;
325                 case 7:
326                         safix = '-';
327                         break;
328                 case 0xf:
329                         safix = '\n';
330                         break;
331                 }
332                 printf("%02x%c", *d, safix);
333                 sum += *d;
334                 d++;
335                 offset++;
336                 length--;
337         }
338         printf("sum 0x%06x", sum);
339 }
340
341 int main(int c, char **v)
342 {
343         const int gg = giveio_start();
344         switch(gg){
345         case GIVEIO_OPEN:
346         case GIVEIO_START:
347         case GIVEIO_WIN95:
348                 break;
349         default:
350         case GIVEIO_ERROR:
351                 printf("Can't Access Direct IO %d\n", gg);
352                 return 0;
353         }
354
355         long d = strtol(v[2], NULL, 0x10);
356
357         switch(v[1][0]){
358         case 'w':
359                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_BUS_WRITE);
360                 port_control_write(DATA_SELECT_WRITE << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
361                 _outp(PORT_DATA, d);
362                 break;
363         case 'c':
364                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_CPU_READ);
365                 address_set(d ^ ADDRESS_MASK_A15, ADDRESS_RESET);
366                 port_control_write(DATA_SELECT_BREAK_DATA << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_WRITE);
367                 port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
368                 printf("%02x\n", _inp(PORT_DATA));
369                 break;
370         case 'C':{
371                 const long length = 0x1000;
372                 u8 data[length];
373                 hk_cpu_read(d, length, data);
374                 data_show(data, length);
375                 }
376                 break;
377         case 'p':
378                 data_port_latch(DATA_SELECT_CONTROL, BUS_CONTROL_PPU_READ);
379                 address_set(d | ADDRESS_MASK_A15, ADDRESS_RESET);
380                 port_control_write(DATA_SELECT_READ << BITNUM_CONTROL_DATA_SELECT, PORT_CONTROL_READ);
381                 printf("%02x\n", _inp(PORT_DATA));
382                 break;
383         case 'P':{
384                 const long length = 0x200;
385                 u8 data[length];
386                 hk_ppu_read(d, length, data);
387                 data_show(data, length);
388                 }
389                 break;
390         }
391         
392         if(gg != GIVEIO_WIN95){
393                 giveio_stop(GIVEIO_STOP);
394         }
395         return 0;
396 }
397 #endif