OSDN Git Service

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