2 famicom ROM cartridge utility - unagi
3 emuste.net ¤Ç¤ª¤Ê¤¸¤ß¤Î¤â¤Î¤Î¥Ï¡¼¥É¥É¥é¥¤¥Ð
5 Copyright (C) 2008 ±·³«È¯¶¨Æ±Áȹç
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.
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.
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
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
30 #include "paralellport.h"
31 #include "hard_onajimi.h"
32 #include "reader_master.h"
33 #include "reader_onajimi.h"
35 static inline void bus_control(int data)
38 _outp(PORT_DATA, data);
44 :: "i"(PORT_DATA), "q"(data): "%edx", "%eax"
53 static inline void address_control(int data)
58 _outp(PORT_CONTROL, data);
64 :: "i"(PORT_CONTROL), "q"(data): "%edx", "%eax"
69 /* address control data & function */
70 static long past_address = 0;
72 static void address_reset(void)
74 address_control(ADDRESS_RESET);
75 address_control(ADDRESS_ENABLE);
80 H->L ¤Çaddressincrement
82 static inline void address_increment(int data)
84 data = bit_set(data, BITNUM_ADDRESS_INCREMENT);
87 data = bit_clear(data, BITNUM_ADDRESS_INCREMENT);
90 past_address &= ADDRESS_MASK_A0toA14;
93 static void address_set(long address, int control)
95 address &= ADDRESS_MASK_A0toA14;
96 long increment_count = address - past_address;
97 if(increment_count < 0){
99 increment_count = address;
102 while(increment_count != 0){
103 address_increment(control);
104 increment_count -= 1;
112 static inline int data_bit_get(void)
117 " xorl %%eax,%%eax\n"
121 :"=q"(data) : "i"(PORT_BUSY) :"%edx", "%eax"
124 int data = _inp(PORT_BUSY);
134 static inline void data_shift(int control)
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);
142 /*ºÇ¾å°Ìbit¤«¤é½çÈ֤ˤȤë*/
143 static u8 data_get(int control)
147 //fcbus 8bit data load, shift count reset
148 control = bit_set(control, BITNUM_DATA_DIRECTION);
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);
160 //¤³¤³¤Î data ¤Ï 0 or 1
161 static inline int writedata_set(long data)
164 return data << BITNUM_DATA_WRITE_DATA;
167 static void data_set(int control, long data)
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);
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)
186 static void reader_init(void)
188 int c = BUS_CONTROL_INIT;
197 c = bit_set(c, BITNUM_CPU_M2);
199 c = bit_clear(c, BITNUM_CPU_M2);
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)
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)
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)
232 static void fc_bus_read(long address, long length, u8 *data, int control, int m2_control)
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 ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
240 if(m2_control == M2_CONTROL_TRUE){
241 //L->H: mapper ¤¬ data ¤ò½Ð¤¹
242 control = bit_set(control, BITNUM_CPU_M2);
244 *data = data_get(control);
245 if(m2_control == M2_CONTROL_TRUE){
247 control = bit_clear(control, BITNUM_CPU_M2);
248 bus_control(control);
250 control = bit_set(control, BITNUM_CPU_M2);
252 address_increment(control);
254 if(m2_control == M2_CONTROL_TRUE){
255 //H->L: mapper ¤¬¥¢¥É¥ì¥¹¤ò¼è¤Ã¤Æ¤¯¤ë
256 control = bit_clear(control, BITNUM_CPU_M2);
257 bus_control(control);
263 control = bit_set(control, BITNUM_CPU_M2);
266 static void cpu_read(long address, long length, u8 *data)
268 int control = BUS_CONTROL_CPU_READ;
269 if(address & ADDRESS_MASK_A15){
270 control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
272 fc_bus_read(address, length, data, control, M2_CONTROL_TRUE);
275 static void ppu_read(long address, long length, u8 *data)
277 fc_bus_read(address, length, data, BUS_CONTROL_PPU_READ, M2_CONTROL_FALSE);
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
293 H:1, L:0, x:ROMareaaccess»þ0, ¤½¤ì°Ê³°1
295 static void cpu_6502_write(long address, long data, long wait_msec)
297 int control = BUS_CONTROL_BUS_WRITE;
298 //addressÀßÄê + Á´¤Æ¤Î¥Ð¥¹¤ò»ß¤á¤ë
299 address_set(address, control);
301 //¦Õ2 = L, R/W=L, data set, dataout
302 control = bit_clear(control, BITNUM_CPU_M2);
303 data_set(control, data);
304 control = bit_clear(control, BITNUM_CPU_RW);
305 bus_control(control);
306 if(address & ADDRESS_MASK_A15){
307 control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
312 control = bit_set(control, BITNUM_CPU_M2);
313 bus_control(control);
315 //¦Õ2 = L, H ¤Ë¤¹¤ë¤Þ¤Ç R/W, address, Data ¤ò͸ú¾õÂ֤ˤ¹¤ë
316 control = bit_clear(control, BITNUM_CPU_M2);
317 bus_control(control);
319 //¦Õ2 = H, R/W = H, address disable, data out disable
320 bus_control(BUS_CONTROL_BUS_WRITE);
323 static void ppu_write(long address, long data)
325 int control = BUS_CONTROL_BUS_WRITE;
327 address_set(address, control);
328 bus_control(control);
329 data_set(control, data);
330 control = bit_clear(control, BITNUM_PPU_RW);
331 control = bit_clear(control, BITNUM_PPU_SELECT);
332 bus_control(control);
333 bus_control(BUS_CONTROL_BUS_WRITE);
336 static const int BUS_CONTROL_CPU_FLASH_WRITE = (
337 ADDRESS_NOP | DATA_SHIFT_NOP |
338 (DATA_DIRECTION_READ << BITNUM_DATA_DIRECTION) |
339 (PPU_DISABLE << BITNUM_PPU_SELECT) |
340 (PPU_READ__CPU_ENABLE << BITNUM_CPU_M2) | //H
341 (CPU_RAM_SELECT << BITNUM_CPU_RAMROM_SELECT) |
342 (CPU_READ << BITNUM_CPU_RW)
345 static void cpu_flash_write(long address, long data)
347 int control = BUS_CONTROL_BUS_WRITE;
348 control = bit_clear(control, BITNUM_CPU_M2);
349 address_set(address, control);
352 control = bit_clear(control, BITNUM_CPU_RW);
353 data_set(control, data);
355 control = bit_clear(control, BITNUM_CPU_RAMROM_SELECT);
356 bus_control(control);
358 control = bit_set(control, BITNUM_CPU_RAMROM_SELECT);
359 bus_control(control);
361 control = bit_set(control, BITNUM_CPU_RW);
362 bus_control(control);
365 const struct reader_driver DRIVER_ONAJIMI = {
367 .open_or_close = paralellport_open_or_close,
369 .cpu_read = cpu_read,
370 .ppu_read = ppu_read,
371 .cpu_6502_write = cpu_6502_write,
372 .cpu_flash_write = cpu_flash_write,
373 .ppu_write = ppu_write