OSDN Git Service

1da3d24f6a676b993f813ee245281431734751e7
[unagi/old-svn-converted.git] / client / trunk / driver_onajimi.c
1 /*
2 famicom ROM cartridge dump program - unagi
3 emuste.net ¤Ç¤ª¤Ê¤¸¤ß¤Î¤â¤Î¤Î¥Ï¡¼¥É¥É¥é¥¤¥Ð
4
5 todo: 
6 * Ê̤Υϡ¼¥É¥¦¥§¥¢¤ËÂбþ¤·¤¿¾ì¹ç¤Ï PORT_DATA ¤«¤é wait ¤Þ¤Ç¤ò¥Ø¥Ã¥À¤Ë¤Þ¤È¤á¤ë
7
8 memo:
9 * -O0 ¤Ê¤é inline asm ¤Ç¤âÈ¿±þ¤Ç¤­¤ë¤¬¡¢-O2 ¤À¤ÈÆ°¤«¤Ê¤¤
10  * Í½ÁÛ¤ËÈ¿¤·¤Æ out ¤ÏÆ°¤¯¤¬¡¢ in ¤Ë wait ¤¬É¬Íפߤ¿¤¤
11 * gcc ¤Î¥¢¥»¥ó¥Ö¥é¤Ï x86 ¤Ç¤¢¤í¤¦¤È src,dst ¤Î½ç¤Çȿž¤·¤Æ¤¤¤ë
12 * http://download.intel.com/jp/developer/jpdoc/IA32_Arh_Dev_Man_Vol2A_i.pdf
13  * out,in ¤Î¥¢¥É¥ì¥¹¤Ë dx ¤ò»È¤ï¤Ê¤¤¤È 8bit ¥¢¥É¥ì¥¹¤Ë¤Ê¤ë
14  * out,in ¤Î¥Ç¡¼¥¿¤Ï¥ì¥¸¥¹¥¿¤Ç¥Ç¡¼¥¿Éý¤¬ÊѤï¤ë al:8bit, ax:16bit, eax:32bit
15 */
16 //#include <dos.h> ?
17 //#include <windows.h>
18 #include "type.h"
19 #include "hard_onajimi.h"
20 #include "driver_onajimi.h"
21
22 #define ASM_ENABLE (0)
23 enum{
24         PORT_DATA = 0x0378,
25         PORT_STATUS,
26         PORT_CONTROL
27 };
28 enum{
29         ADDRESS_MASK_A0toA14 = 0x7fff,
30         ADDRESS_MASK_A15 = 0x8000
31 };
32 #if ASM_ENABLE==0
33 void _outp(int, int);
34 int _inp(int);
35 #endif
36
37 static inline int bit_set(int data, const int bit)
38 {
39         data |= 1 << bit;
40         return data;
41 }
42
43 static inline int bit_clear(int data, const int bit)
44 {
45         data &= ~(1 << bit);
46         return data;
47 }
48
49 static inline void wait(void)
50 {
51         //const long waittime = 100000;
52         //SleepEx(20,TRUE);
53 }
54
55 static inline void bus_control(int data)
56 {
57 #if ASM_ENABLE==0
58         _outp(PORT_DATA, data);
59 #else
60         asm(
61                 " movl %0,%%edx\n"
62                 " movl %1,%%eax\n"
63                 " out %%al,%%dx\n"
64                 :: "i"(PORT_DATA), "q"(data): "%edx", "%eax"
65         );
66 #endif
67         wait();
68 }
69
70 /*
71 CONTROL bit0 STROBE
72 ¥Ç¡¼¥¿¤¬È¿Å¾¤¹¤ë
73 */
74 static inline void address_control(int data)
75 {
76         data &= 0x01;
77         data ^= 0x01;
78 #if ASM_ENABLE==0
79         _outp(PORT_CONTROL, data);
80 #else
81         asm(
82                 " movl %0,%%edx\n"
83                 " movl %1,%%eax\n"
84                 " out %%al,%%dx\n"
85                 :: "i"(PORT_CONTROL), "q"(data): "%edx", "%eax"
86         );
87 #endif
88         wait();
89 }
90
91 /* address control data & function */
92 static long past_address = 0;
93
94 static void address_reset(void)
95 {
96         address_control(ADDRESS_RESET);
97         address_control(ADDRESS_ENABLE);
98         past_address = 0;
99 }
100
101 /*
102 H->L ¤Çaddressincrement
103 */
104 static inline void address_increment(int data)
105 {
106         data = bit_set(data, BITNUM_ADDRESS_INCREMENT);
107         bus_control(data);
108
109         data = bit_clear(data, BITNUM_ADDRESS_INCREMENT);
110         bus_control(data);
111         past_address += 1;
112         past_address &= ADDRESS_MASK_A0toA14;
113 }
114
115 static void address_set(long address, int control)
116 {
117         address &= ADDRESS_MASK_A0toA14;
118         long increment_count = address - past_address;
119         if(increment_count < 0){
120                 address_reset();
121                 increment_count = address;
122         }
123                 
124         while(increment_count != 0){
125                 address_increment(control);
126                 increment_count -= 1;
127         }
128 }
129
130 /*
131 STATUS bit7 BUSY
132 ¥Ç¡¼¥¿¤¬È¿Å¾¤¹¤ë
133 */
134 static inline int data_bit_get(void)
135 {
136 #if ASM_ENABLE==1
137         int data;
138         asm(
139                 " xorl %%eax,%%eax\n"
140                 " movl %1,%%edx\n"
141                 " in %%dx,%%al\n"
142                 " movl %%eax,%0"
143                 :"=q"(data) : "i"(PORT_STATUS) :"%edx", "%eax"
144         );
145 #else
146         int data = _inp(PORT_STATUS);
147 #endif
148         data >>= 7;
149         data &= 0x01;
150         return data ^ 0x01;
151 }
152
153 /* 
154 L->H ¤Çshift 
155 */
156 static void data_shift(int control)
157 {
158         control = bit_clear(control, BITNUM_DATA_SHIFT_RIGHT);
159         bus_control(control);
160         control = bit_set(control, BITNUM_DATA_SHIFT_RIGHT);
161         bus_control(control);
162 }
163
164 /*ºÇ¾å°Ìbit¤«¤é½çÈ֤ˤȤë*/
165 static u8 data_get(int control)
166 {
167         int data = 0;
168         int i;
169         //fcbus 8bit data load, shift count reset
170         control = bit_set(control, BITNUM_DATA_DIRECTION);
171         data_shift(control);
172         //shift mode
173         control = bit_clear(control, BITNUM_DATA_DIRECTION);
174         bus_control(control);
175         for(i = 0; i < 8; i++){
176                 data |= (data_bit_get() << i);
177                 data_shift(control);
178         }
179         return (u8) data;
180 }
181
182 //¤³¤³¤Î data ¤Ï 0 or 1
183 static inline int writedata_set(long data)
184 {
185         data &= 1;
186         return data << BITNUM_DATA_WRITE_DATA;
187 }
188
189 static void data_set(int control, long data)
190 {
191         int i;
192         for(i = 0; i < 8; i++){
193                 control = bit_clear(control, BITNUM_DATA_WRITE_DATA);
194                 control |= writedata_set(data >> i);
195                 bus_control(control);
196                 data_shift(control);
197         }
198 }
199
200 static const int BUS_CONTROL_INIT = (
201         ADDRESS_NOP | DATA_SHIFT_NOP |
202         (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
203         (PPU_DISABLE << BITNUM_PPU_SELECT) |
204         (PPU_WRITE__CPU_DISABLE << BITNUM_CPU_M2) |
205         (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
206         (CPU_READ << BITNUM_CPU_RW)
207 );
208 void reader_init(void)
209 {
210         bus_control(BUS_CONTROL_INIT);
211         address_reset();
212 }
213
214 static const int BUS_CONTROL_CPU_READ = (
215         ADDRESS_NOP | DATA_SHIFT_NOP |
216         (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
217         (PPU_DISABLE << BITNUM_PPU_SELECT) |
218         (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) | //H
219         (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
220         (CPU_READ << BITNUM_CPU_RW)
221 );
222
223 static const int BUS_CONTROL_PPU_READ = (
224         ADDRESS_NOP | DATA_SHIFT_NOP |
225         (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
226         (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) |
227         (PPU_ENABLE << BITNUM_PPU_SELECT) |
228         (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
229         (CPU_READ << BITNUM_CPU_RW)
230 );
231
232 static const int BUS_CONTROL_BUS_WRITE = (
233         ADDRESS_NOP | DATA_SHIFT_NOP |
234         (DATA_DIRECTION_WRITE << BITNUM_DATA_DIRECTION) |
235         (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) |
236         (PPU_DISABLE << BITNUM_PPU_SELECT) |
237         (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
238         (CPU_READ << BITNUM_CPU_RW)
239 );
240
241 enum{ 
242         M2_CONTROL_TRUE, M2_CONTROL_FALSE
243 };
244
245 static void fc_bus_read(long address, long length, u8 *data, int control, int m2_control)
246 {
247         address_set(address, control);
248         if(m2_control == M2_CONTROL_TRUE){
249                 control = bit_clear(control, BITNUM_CPU_M2);
250                 bus_control(control); //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
251         }
252         while(length != 0){
253                 if(m2_control == M2_CONTROL_TRUE){
254                         //L->H: mapper ¤¬ data ¤ò½Ð¤¹
255                         control = bit_set(control, BITNUM_CPU_M2);
256                 }
257                 *data = data_get(control);
258                 if(m2_control == M2_CONTROL_TRUE){
259                         //H->L: ¤ª¤ä¤¹¤ß
260                         control = bit_clear(control, BITNUM_CPU_M2);
261                         bus_control(control);
262                         //L->H: increment
263                         control = bit_set(control, BITNUM_CPU_M2);
264                 }
265                 address_increment(control);
266
267                 if(m2_control == M2_CONTROL_TRUE){
268                         //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
269                         control = bit_clear(control, BITNUM_CPU_M2);
270                         bus_control(control);
271                 }
272
273                 data++;
274                 length--;
275         }
276         control = bit_set(control, BITNUM_CPU_M2);
277 }
278
279 void cpu_read(long address, long length, u8 *data)
280 {
281         int control = BUS_CONTROL_CPU_READ;
282         if(address & ADDRESS_MASK_A15){
283                 control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
284         }
285         fc_bus_read(address, length, data, control, M2_CONTROL_TRUE);
286 }
287
288 void ppu_read(long address, long length, u8 *data)
289 {
290         fc_bus_read(address, length, data, BUS_CONTROL_PPU_READ, M2_CONTROL_FALSE);
291 }
292 /*
293 6502 write cycle
294 t   |01234
295 ----+-----
296 ¦Õ2 |HLHLH
297 /ROM|HHxxH
298 R/W |HHLLH
299
300 0 H bus:addressset
301 1 H->L bus:data set, mapper:address get
302 2 L->H bus:data write
303 3 H->L mapper: data write enable
304 4 L->H mapper: data get, bus:close
305
306 H:1, L:0, x:ROMareaaccess»þ0, ¤½¤ì°Ê³°1
307 */
308 void cpu_write(long address, long data)
309 {
310         int control = BUS_CONTROL_BUS_WRITE;
311         //addressÀßÄê + Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
312         address_set(address, control);
313
314         control = bit_clear(control, BITNUM_CPU_M2);
315         //printf("%02x ", (int) data);
316         data_set(control, data);
317
318         control = bit_clear(control, BITNUM_CPU_RW);
319         //bus_control(control); //
320         control = bit_set(control, BITNUM_CPU_M2);
321         //bus_control(control); //
322         if(address & ADDRESS_MASK_A15){
323                 control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
324         }
325         bus_control(control);
326         control = bit_clear(control, BITNUM_CPU_M2);
327         bus_control(control);
328         bus_control(BUS_CONTROL_BUS_WRITE);
329 }
330
331 void ppu_write(long address, long data)
332 {
333         int control = BUS_CONTROL_BUS_WRITE;
334
335         address_set(address, control);
336         bus_control(control);
337         data_set(control, data);
338         control = bit_clear(control, BITNUM_PPU_RW);
339         control = bit_clear(control, BITNUM_PPU_SELECT); //mmc1 ¤Ï¤Ê¤¯¤Æ¤â¤¤¤±¤ë¤¬ mmc3 ¤Ë¤ÏɬÍ×
340         bus_control(control);
341         bus_control(BUS_CONTROL_BUS_WRITE);
342 }