1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996 |
- /*
- gbx.c - Game Boy Xchanger/GBDoctor support for uCON64
- Copyright (c) 1999 - 2001 NoisyB
- Copyright (c) 2001 - 2004 dbjh
- Based on gbt15.c - Copyright (c) Bung Enterprises
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- /********************************************************************
- * use parallel EPP/SPP port to r/w game boy cartridge *
- * *
- * ai[]=0 w a[7..0] *
- * ai[]=1 w a[15..8] *
- * ai[]=2 w control d7=rs,d6=spp,d1=xwe_en,d0=cs_en *
- * ai[]=3 r/w data *
- * *
- * MBC1 *
- * R/W A000~BFFF RAM SWITCHING BANK(256Kbit) 4 BANKS OF 8Kbyte *
- * R 4000~7FFF ROM SWITCHING BANK(4Mbit) 32 BANKS OF 128Kbit *
- * W 2000~3FFF SET ROM BANK (5 BIT) *
- * R 0000~3FFF FIX ROM BANK 0 *
- * W 4000~5FFF SET RAM BANK (2 BIT) *
- * W 0000~1FFF SET 0A ENABLE RAM BANK *
- * *
- * MBC2 *
- * R/W A000~BFFF 512 X 4 BIT RAM *
- * R 4000~7FFF ROM SWITCHING BANK(2Mbit) 16 BANKS OF 128Kbit *
- * W 2100 SET ROM BANK (4 BIT) *
- * R 0000~3FFF FIX ROM BANK 0 *
- * W 0000 SET 0A ENABLE RAM BANK *
- * *
- * MBC5 *
- * R/W A000~BFFF RAM SWITCHING BANK(1Mbit) 16 BANKS OF 64 Kbit *
- * R 4000~7FFF ROM SWITCHING BANK(64Mbit) 512 BANKS OF 128Kbit *
- * W 3000~3FFF SET ROM BANK1(BANK Q8) TOTAL 9 BIT *
- * W 2000~2FFF SET ROM BANK0(BANK Q7~Q0) *
- * R 0000~3FFF FIX ROM BANK 0 *
- * W 4000~7FFF SET RAM BANK (4 BIT) *
- * W 0000~1FFF SET 0A ENABLE RAM BANK *
- * *
- ********************************************************************/
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <ctype.h>
- #include <stdlib.h>
- #include "misc/archive.h"
- #include "misc/file.h"
- #include "misc/misc.h"
- #include "misc/parallel.h"
- #include "misc/term.h"
- #include "ucon64_misc.h"
- #include "console/gb.h" // GB_NAME_LEN, gb_logodata,
- #include "backup/gbx.h" // rocket_logodata
- #ifdef USE_PARALLEL
- static st_ucon64_obj_t gbx_obj[] =
- {
- {UCON64_GB, WF_DEFAULT | WF_STOP | WF_NO_ROM},
- {UCON64_GB, WF_STOP | WF_NO_ROM},
- {UCON64_GB, WF_SWITCH}
- };
- #endif
- const st_getopt2_t gbx_usage[] =
- {
- {
- NULL, 0, 0, 0,
- NULL, "Game Boy Xchanger/GBDoctor"/*"19XX Bung Enterprises Ltd http://www.bung.com.hk"*/,
- NULL
- },
- #ifdef USE_PARALLEL
- {
- "xgbx", 0, 0, UCON64_XGBX,
- NULL, "send/receive ROM to/from GB Xchanger; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when ROM does not exist",
- &gbx_obj[0]
- },
- {
- "xgbxs", 0, 0, UCON64_XGBXS,
- NULL, "send/receive SRAM to/from GB Xchanger; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when SRAM does not exist",
- &gbx_obj[1]
- },
- {
- "xgbxb", 1, 0, UCON64_XGBXB,
- "BANK", "send/receive 64 kbits SRAM to/from GB Xchanger BANK\n"
- "BANK can be a number from 0 to 15; " OPTION_LONG_S "port=PORT\n"
- "receives automatically when ROM does not exist",
- &gbx_obj[1]
- },
- {
- "xgbxm", 0, 0, UCON64_XGBXM,
- NULL, "try to enable EPP mode, default is SPP mode",
- &gbx_obj[2]
- },
- #endif
- {NULL, 0, 0, 0, NULL, NULL, NULL}
- };
- #ifdef USE_PARALLEL
- //#define set_ai_write outportb (port_a, 5); // ninit=1, nwrite=0
- #define set_data_read outportb (port_a, 0); // ninit=0, nastb=1, nib_sel=0, ndstb=1, nwrite=1
- #define set_data_write outportb (port_a, 1); // ninit=0, nastb=1, nib_sel=0, ndstb=1, nwrite=0
- //#define set_normal outportb (port_a, 4); // ninit=1, nwrite=1
- typedef enum { UNKNOWN_MBC, BUNG, ROM, MBC1, MBC2, MBC3, MBC5, CAMERA, ROCKET } mbc_t;
- typedef enum { UNKNOWN_EEPROM, WINBOND, MX, INTEL } eeprom_t;
- static unsigned short port_8, port_9, port_a, port_b, port_c, rocket_game_no;
- static unsigned char buffer[32768];
- static mbc_t mbc_type;
- static eeprom_t eeprom_type;
- static parport_mode_t port_mode;
- static void
- delay_us (int n_us)
- // Hmmm, usleep() can be used on UNIX, but default on DOS is delay() which waits
- // for a number of milliseconds... Better use the same code on all platforms.
- {
- volatile int n;
- int n_max;
- // it's probably best to use the original strange loop values
- if (n_us == 10)
- n_max = 0x2000;
- else if (n_us == 100)
- n_max = 0x10000;
- else if (n_us == 20000)
- n_max = 0xfffff;
- else
- n_max = n_us * 1000;
- for (n = 0; n < n_max; n++)
- ;
- }
- static void
- spp_set_ai (unsigned char ai)
- {
- set_data_write
- // outportb (port_a, 1); // nastb=1,nib_sel=0,ndstb=1,nwrite=0
- outportb (port_8, ai); // put ai at data bus
- outportb (port_a, 9); // nastb=0,nib_sel=0,ndstb=1,nwrite=0
- outportb (port_a, 1); // nastb=1,nib_sel=0,ndstb=1,nwrite=0
- // nastb ~~~~|___|~~~~
- }
- static void
- spp_write_data (unsigned char data)
- {
- // outportb (port_a, 1); // nastb=1,nib_sel=0,ndstb=1,nwrite=0
- outportb (port_8, data); // put data at data bus
- outportb (port_a, 3); // nastb=1,nib_sel=0,ndstb=0,nwrite=0
- outportb (port_a, 1); // nastb=1,nib_sel=0,ndstb=1,nwrite=0
- // ndstb ~~~~|___|~~~~
- }
- static void
- spp_set_ai_data (unsigned char ai, unsigned char data)
- {
- spp_set_ai (ai);
- spp_write_data (data);
- }
- static unsigned char
- spp_read_data (void)
- {
- unsigned char byte;
- set_data_read
- outportb (port_a, 2); // nastb=1,nib_sel=0,ndstb=0,nwrite=1
- byte = (inportb (port_9) >> 3) & 0x0f;
- outportb (port_a, 6); // nastb=1,nib_sel=1,ndstb=0,nwrite=1
- byte |= (inportb (port_9) << 1) & 0xf0;
- outportb (port_a, 0); // nastb=1,nib_sel=0,ndstb=1,nwrite=1
- // nibble_sel ___|~~~ and ndstb ~~~~|___|~~~~
- return byte;
- }
- static void
- epp_set_ai (unsigned char ai)
- {
- set_data_write
- outportb (port_b, ai);
- }
- static void
- epp_set_ai_data (unsigned char ai, unsigned char data)
- {
- epp_set_ai (ai);
- set_data_write
- outportb (port_c, data);
- }
- static void
- set_ai (unsigned char ai)
- {
- set_data_write
- if (port_mode == UCON64_SPP)
- spp_set_ai (ai);
- else
- epp_set_ai (ai);
- }
- static void
- set_ai_data (unsigned char ai, unsigned char data)
- {
- if (port_mode == UCON64_SPP)
- spp_set_ai_data (ai, data); // SPP mode
- else
- epp_set_ai_data (ai, data); // EPP mode
- }
- static void
- write_data (unsigned char data)
- {
- if (port_mode == UCON64_SPP)
- spp_write_data (data); // SPP write data
- else
- outportb (port_c, data); // EPP write data
- }
- static unsigned char
- read_data (void)
- {
- if (port_mode == UCON64_SPP)
- return spp_read_data (); // SPP read data
- else
- return inportb (port_c); // EPP read data
- }
- static void
- init_port (void)
- {
- #ifndef USE_PPDEV
- outportb (port_9, 1); // clear EPP time flag
- #endif
- set_ai_data ((unsigned char) 2, 0); // rst=0, wei=0(dis.), rdi=0(dis.)
- set_ai_data ((unsigned char) 2, 0x80); // rst=1, wei=0(dis.), rdi=0(dis.)
- }
- static void
- end_port (void)
- {
- set_ai_data ((unsigned char) 2, 0); // rst=0, wei=0(dis.), rdi=0(dis.)
- outportb (port_a, 4); // ninit=1, nwrite=1
- }
- static void
- set_adr (unsigned int adr)
- {
- set_ai_data ((unsigned char) 0, (unsigned char) adr); // a[7..0]
- set_ai_data ((unsigned char) 1, (unsigned char) (adr >> 8)); // a[15..8]
- set_ai (3);
- set_data_read // ninit=0, nwrite=1
- }
- static void
- set_adr_long (unsigned int adr, int ignore_xh) // real address
- {
- unsigned char xh, h, m, l;
- set_ai_data ((unsigned char) 2, 0x80); // disable wr/rd inc.
- l = (unsigned char) adr; // a7-a0
- m = (unsigned char) (adr >> 8) & 0x3f; // a13-a8
- h = (unsigned char) (adr >> 14) & 0xff; // a21-a13
- if (h)
- m |= 0x40; // > bank 0
- if (!ignore_xh)
- {
- xh = (unsigned char) (adr >> 22) & 0x7; // max. 256Mbit
- if (xh)
- m |= 0x40; // > bank 0
- set_adr (0x3000); // write 3000:xh
- set_data_write
- write_data (xh); // set ROM bank extend value
- }
- set_adr (0x2000); // write 2000:h
- set_data_write
- write_data (h); // set ROM bank value
- set_ai_data ((unsigned char) 1, m); // a[15..8]
- set_ai_data ((unsigned char) 0, l); // a[7..0]
- }
- static void
- set_bank (unsigned int adr, unsigned char bank)
- {
- set_ai_data ((unsigned char) 2, 0x80); // disable inc
- set_ai_data ((unsigned char) 0, (unsigned char) adr); // a[7..0]
- set_ai_data ((unsigned char) 1, (unsigned char) ((adr >> 8) & 0x7f)); // a[15..8]
- set_ai_data ((unsigned char) 3, bank); // write bank no
- set_data_read // ninit=0, nwrite=1
- }
- static void
- out_byte_eeprom (unsigned char data)
- {
- set_ai_data ((unsigned char) 2, 0x82); // wei enable
- set_ai (3); // default write mode
- // set_data_read // ninit=0, nwrite=1
- set_data_write
- write_data (data); // out data
- set_ai_data ((unsigned char) 2, 0x80); // wei disable
- set_ai (3); // default write mode
- }
- static void
- out_byte (unsigned char data)
- {
- set_ai (3);
- // set_data_read // ninit=0, nwrite=1
- set_data_write
- write_data (data); // out data
- }
- static void
- out_data (unsigned char h, unsigned char m, unsigned char l, unsigned char data)
- {
- // ai[]=2 w control d7=rs,d1=xwe_en,d0=cs_en
- h = ((h << 2) | (m >> 6)) & 0x1f; // maximum bank is 1f
- if (h)
- m = (m & 0x3f) | 0x40; // > bank 0
- else
- m = m & 0x3f; // bank 0
- set_adr (0x2000); // write 2000:h
- set_data_write
- write_data (h); // set ROM bank value
- set_ai_data ((unsigned char) 1, m); // a[15..8]
- set_ai_data ((unsigned char) 0, l); // a[7..0]
- out_byte_eeprom (data); // write data to EEPROM
- }
- static void
- out_adr2_data (unsigned int adr, unsigned char data) // address shift 1 bit
- {
- set_adr_long (adr << 1, 1); // adr x 2
- out_byte_eeprom (data); // write data to EEPROM
- }
- static void
- out_adr_data (unsigned int adr, unsigned char data) // real address
- {
- set_adr_long (adr, 0);
- out_byte_eeprom (data); // write data to EEPROM
- }
- static void
- out_adr_data_32k (unsigned int adr, unsigned char data)
- {
- set_adr (adr);
- out_byte_eeprom (data); // write data to EEPROM
- }
- static unsigned char
- read_byte (void)
- {
- set_ai (3); // default write mode
- set_data_read // ninit=0, nwrite=1
- return read_data ();
- }
- static void
- enable_protection (void)
- {
- // set_bank (0x2000,0); // set bank 0
- out_data (0, 0x55, 0x55, 0xaa); // adr2,adr1,adr0,data 05555:aa
- out_data (0, 0x2a, 0xaa, 0x55);
- out_data (0, 0x55, 0x55, 0xa0);
- }
- /*
- static void
- disable_protection (void)
- {
- out_data (0, 0x55, 0x55, 0xaa); // adr2,adr1,adr0,data 05555:aa
- out_data (0, 0x2a, 0xaa, 0x55);
- out_data (0, 0x55, 0x55, 0x80);
- out_data (0, 0x55, 0x55, 0xaa);
- out_data (0, 0x2a, 0xaa, 0x55);
- out_data (0, 0x55, 0x55, 0x20);
- delay_us (20000);
- }
- */
- #if 0
- static int
- data_polling_data (unsigned char last_data)
- {
- unsigned int timeout = 0;
- while (timeout++ < 0x07ffffff)
- if (((read_byte () ^ last_data) & 0x80) == 0)
- return 0;
- return 1; // ready to exit the while loop
- }
- #endif
- static int
- data_polling (void)
- {
- unsigned char predata, currdata;
- unsigned int timeout = 0;
- predata = read_byte () & 0x40;
- while (timeout++ < 0x07ffffff)
- {
- currdata = read_byte () & 0x40;
- if (predata == currdata)
- return 0;
- predata = currdata;
- }
- return 1;
- }
- static void
- reset_to_read (void) // return to read mode
- {
- out_adr2_data (0x5555, 0xaa); // 5555:aa adr2,adr1,adr0,data
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55
- out_adr2_data (0x5555, 0xf0); // 5555:f0
- }
- /*
- static void
- read_status_reg_cmd (void)
- {
- out_adr2_data (0x5555, 0xaa); // 5555:aa adr2,adr1,adr0,data
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55
- out_adr2_data (0x5555, 0x70); // 5555:70
- }
- */
- static int
- wait_status (void)
- {
- unsigned temp = read_byte (); // read first status byte
- while ((temp & 0xfc) != 0x80)
- {
- if ((temp & 0x20) == 0x20 && port_mode == UCON64_SPP)
- {
- fputs ("\nERROR: Erase failed\n", stderr);
- return -1;
- }
- if ((temp & 0x10) == 0x10)
- {
- fputs ("\nERROR: Programming failed\n", stderr);
- return -2;
- }
- temp = read_data ();
- }
- // reset_to_read ();
- return 0;
- }
- static int
- mx_erase (void)
- {
- int retval;
- out_adr2_data (0x5555, 0xaa); // 5555:aa adr2,adr1,adr0,data
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55
- out_adr2_data (0x5555, 0x80); // 5555:80
- out_adr2_data (0x5555, 0xaa); // 5555:aa
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55
- out_adr2_data (0x5555, 0x10); // 5555:10
- delay_us (100);
- // read_status_reg_cmd (); // send read status reg. cmd
- retval = wait_status () ? -1 : 0;
- reset_to_read ();
- return retval;
- }
- /*
- static int
- win_erase (void)
- {
- out_data (0, 0x55, 0x55, 0xaa); // adr2,adr1,adr0,data 05555:aa
- out_data (0, 0x2a, 0xaa, 0x55);
- out_data (0, 0x55, 0x55, 0x80);
- out_data (0, 0x55, 0x55, 0xaa);
- out_data (0, 0x2a, 0xaa, 0x55);
- out_data (0, 0x55, 0x55, 0x10);
- delay_us (20000);
- if (data_polling ())
- {
- fputs ("ERROR: Erase failed\n", stderr);
- return -1;
- }
- else
- return 0;
- }
- */
- static unsigned char
- intel_read_status (void)
- {
- out_adr_data (0, 0x70); // read status command
- return read_byte ();
- }
- static int
- intel_check_status (void)
- {
- unsigned int time_out = 0x8000;
- while (!(intel_read_status () & 0x80))
- {
- time_out--;
- if (time_out == 0)
- {
- fprintf (stderr, "\nERROR: Intel read status time out\n"
- " Status = 0x%02x\n", intel_read_status ());
- out_adr_data (0, 0x50); // clear status register
- return -1;
- }
- }
- return 0;
- }
- static int
- intel_block_erase (unsigned int block)
- {
- unsigned int time_out = 0x8000;
- while ((intel_read_status ()) != 0x80)
- {
- time_out--;
- if (time_out == 0)
- {
- fprintf (stderr, "\nERROR: Intel block erase time out\n"
- " Status = 0x%02x\n", intel_read_status ());
- return -1;
- }
- }
- out_adr_data (block, 0x20); // block erase
- out_adr_data (block, 0xd0); // write confirm
- time_out = 0x8000;
- while (!(intel_read_status () & 0x80))
- {
- time_out--;
- if (time_out == 0)
- {
- fprintf (stderr, "\nERROR: Intel block erase time out at 0x%x\n"
- " Status = 0x%02x\n", block, intel_read_status ());
- out_adr_data (block, 0x50); // clear status register
- fprintf (stderr, " Status = 0x%02x\n", intel_read_status ());
- return -1;
- }
- }
- if ((intel_read_status ()) == 0x80)
- return 0;
- else
- {
- fprintf (stderr, "\nERROR: Intel block erase error at 0x%x\n"
- " Status = 0x%02x\n", block, intel_read_status ());
- out_adr_data (block, 0x50); // clear status register
- fprintf (stderr, " Status = 0x%02x\n", intel_read_status ());
- out_adr_data (0x0000, 0xff); // read array
- return -1;
- }
- }
- /*
- static int
- intel_erase (void)
- {
- unsigned int block;
- for (block = 0; block < 64; block++)
- if (intel_block_erase (block * 0x20000))
- return -1;
- return 0;
- }
- static int
- erase (void)
- {
- if (eeprom_type == WINBOND)
- return win_erase ();
- else if (eeprom_type == MX)
- return mx_erase ();
- else if (eeprom_type == INTEL)
- return intel_erase ();
- fputs ("ERROR: Unknown EEPROM type\n", stderr);
- return -1;
- }
- */
- static int
- check_eeprom (void)
- {
- int i;
- // check 4M flash
- out_adr_data_32k (0x5555, 0xaa); // software product ID entry
- out_adr_data_32k (0x2aaa, 0x55);
- out_adr_data_32k (0x5555, 0x80);
- out_adr_data_32k (0x5555, 0xaa);
- out_adr_data_32k (0x2aaa, 0x55);
- out_adr_data_32k (0x5555, 0x60);
- delay_us (10);
- set_adr (0); // adr2,adr1,adr0
- if (read_byte () == 0xda) // manufacturer code
- {
- set_adr (1); // adr2,adr1,adr0
- if (read_byte () == 0x46) // device code
- {
- out_adr_data_32k (0x5555, 0xaa); // software product ID exit
- out_adr_data_32k (0x2aaa, 0x55); // adr2,adr1,adr0,data
- out_adr_data_32k (0x5555, 0xf0); // adr2,adr1,adr0,data
- eeprom_type = WINBOND; // Winbond 4 Mbit flash
- return 0;
- }
- }
- // check 16M flash
- out_adr2_data (0x5555, 0xaa); // 5555:aa software product ID entry
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55 adr2,adr1,adr0,data
- out_adr2_data (0x5555, 0x90); // 5555:90 adr2,adr1,adr0,data
- set_adr (0); // adr2,adr1,adr0
- if (read_byte () == 0xc2) // manufacturer code
- {
- set_adr (2); // adr2,adr1,adr0
- if (read_byte () == 0xf1) // device code
- {
- reset_to_read (); // reset to read mode
- eeprom_type = MX; // MX 16 Mbit flash
- return 0;
- }
- }
- // check 64M flash
- reset_to_read ();
- init_port ();
- out_adr_data (0x0000, 0x98); // read query
- for (i = 0; i < 128; i += 2)
- {
- set_adr (i); // adr2,adr1,adr0
- buffer[i / 2] = read_byte ();
- }
- // dumper (stdout, buffer, 64, 0, DUMPER_HEX);
- if (buffer[0] == 0x89 && buffer[1] == 0x15
- && buffer[0x10] == 'Q' && buffer[0x11] == 'R' && buffer[0x12] == 'Y')
- {
- out_adr_data (0x0000, 0xff); // read array
- eeprom_type = INTEL; // Intel 64 Mbit flash
- return 0;
- }
- // eeprom_type = UNKNOWN_EEPROM;
- return 1;
- }
- static void
- check_mbc (void)
- // determine memory bank controller type
- {
- if (eeprom_type != UNKNOWN_EEPROM)
- mbc_type = BUNG;
- else
- {
- unsigned char rom_type = buffer[0x47];
- if (memcmp (buffer + 4, rocket_logodata, GB_LOGODATA_LEN) == 0)
- mbc_type = ROCKET; // rom_type == 0x97 || rom_type == 0x99
- else if (rom_type == 0)
- mbc_type = ROM;
- else if ((rom_type >= 1 && rom_type <= 3) || rom_type == 0xff)
- mbc_type = MBC1;
- else if (rom_type == 5 || rom_type == 6)
- mbc_type = MBC2;
- else if (rom_type >= 0x0f && rom_type <= 0x13)
- mbc_type = MBC3;
- else if (rom_type >= 0x19 && rom_type <= 0x1e)
- mbc_type = MBC5;
- else if (rom_type == 0x1f)
- mbc_type = CAMERA;
- else
- mbc_type = UNKNOWN_MBC;
- }
- }
- static int
- check_card (void)
- /*
- 16 kB ROM = 1 bank
- 8 kB RAM = 1 bank
- */
- {
- unsigned char sum = 0;
- char game_name[GB_NAME_LEN + 2];
- int gb_name_len, i;
- puts ("Checking ROM data...");
- if (mbc_type == ROCKET)
- puts ("NOTE: Rocket Games cartridge detected");
- else if (memcmp (buffer + 4, gb_logodata, GB_LOGODATA_LEN) != 0)
- {
- puts ("WARNING: Cartridge does not contain official Nintendo logo data");
- dumper (stdout, buffer, 0x50, 0x100, DUMPER_HEX);
- }
- gb_name_len = (buffer[0x43] == 0x80 || buffer[0x43] == 0xc0) ?
- GB_NAME_LEN : GB_NAME_LEN + 1;
- memcpy (game_name, buffer + 0x34, gb_name_len);
- game_name[gb_name_len] = 0;
- for (i = 0; i < gb_name_len; i++)
- if (!isprint ((int) game_name[i]) && game_name[i] != 0)
- game_name[i] = '.';
- printf ("Game name: \"%s\"\n", game_name);
- if (buffer[0x48] > 8) // ROM size
- printf ("NOTE: Strange ROM size byte value in header (0x%02x)\n", buffer[0x48]);
- if (buffer[0x49] > 5) // SRAM size
- printf ("NOTE: Strange RAM size byte value in header (0x%02x)\n", buffer[0x49]);
- /*
- // [47] = ROM type
- if (buffer[0x47] > 0 && buffer[0x47] < 4 && buffer[0x48] > 4)
- mbc1_exp = 1; // MBC1 8 Mbit/16 Mbit
- */
- for (i = 0x34; i < 0x4d; i++)
- sum += ~buffer[i];
- if (buffer[0x4d] != sum)
- printf ("NOTE: Incorrect header checksum (0x%02x), should be 0x%02x\n",
- buffer[0x4d], sum);
- return (1 << (buffer[0x48] > 8 ? 9 : buffer[0x48])) * 32 * 1024;
- }
- static void
- set_sram_bank (unsigned char bank)
- // original code only did "set_adr (0x4000); out_byte (bank);"
- {
- if (eeprom_type != UNKNOWN_EEPROM)
- { // flash card
- set_adr (0x4000); // set SRAM adr
- out_byte (bank); // SRAM bank 0
- // this should be equivalent to the code above: set_bank (0x4000, bank)
- }
- else
- { // game cartridge
- switch (mbc_type)
- {
- case MBC1:
- set_bank (0x6000, 1);
- set_bank (0x4000, (unsigned char) (bank & 3));
- break;
- case MBC3:
- case MBC5:
- set_bank (0x4000, bank);
- break;
- default:
- break;
- }
- }
- }
- static void
- set_bank2 (unsigned int bank)
- {
- switch (mbc_type)
- {
- case BUNG:
- case UNKNOWN_MBC:
- case MBC5:
- set_bank (0x2000, (unsigned char) bank);
- if (eeprom_type != WINBOND)
- set_bank (0x3000, (unsigned char) (bank >> 8));
- break;
- case MBC1:
- set_bank (0x6000, 0);
- set_bank (0x2000, (unsigned char) (bank & 0x1f));
- set_bank (0x4000, (unsigned char) ((bank >> 5) & 3)); // (bank & 0x60) >> 5
- break;
- case MBC2:
- set_bank (0x2100, (unsigned char) (bank & 0x0f));
- break;
- case MBC3:
- set_bank (0x2000, (unsigned char) bank);
- break;
- case CAMERA:
- set_bank (0x4000, (unsigned char) bank);
- break;
- case ROCKET:
- set_bank (0x3f00, (unsigned char) bank);
- break;
- default:
- break;
- }
- }
- static void
- read_rom_16k (unsigned int bank) // ROM or EEPROM
- {
- int idx = 0, i, j;
- char game_name[GB_NAME_LEN + 2];
- set_bank2 (bank);
- for (j = 0; j < 64; j++)
- { // 16k bytes = 64 x 256 bytes
- if (bank)
- set_ai_data ((unsigned char) 1, (unsigned char) (j | 0x40)); // set adr[15..8]
- else
- set_ai_data ((unsigned char) 1, (unsigned char) j); // a[15..0]
- set_ai_data ((unsigned char) 0, 0); // a[7..0]
- set_ai_data ((unsigned char) 2, 0x81); // enable read inc.
- set_ai (3); // read/write data
- set_data_read
- for (i = 0; i < 256; i++) // page = 256
- buffer[idx + i] = read_data ();
- idx += 256;
- /*
- One can select the game in 2-in-1 cartridges by writing the game number
- to 0x3fc0. This has been verified for 2 cartridges with ROM type byte
- value 0x99. Maybe there exist other Rocket Games n-in-1 games with a
- different ROM type byte value. That's why we don't check for that
- specific ROM type byte value.
- */
- if (mbc_type == ROCKET && j == 1)
- if (memcmp (buffer + 0x104, rocket_logodata, GB_LOGODATA_LEN) == 0)
- {
- set_adr (0x3fc0);
- out_byte ((unsigned char) rocket_game_no++);
- if (bank)
- {
- // Reread the last two pages, because the data came from the
- // previously selected game (data is "mirrored"). This does not
- // apply to the first game.
- int k, gb_name_len;
- idx = 0;
- for (k = 0; k < 2; k++)
- {
- set_ai_data ((unsigned char) 1, (unsigned char) (k | 0x40));
- set_ai_data ((unsigned char) 0, 0);
- set_ai_data ((unsigned char) 2, 0x81);
- set_ai (3);
- set_data_read
- for (i = 0; i < 256; i++)
- buffer[idx + i] = read_data ();
- idx += 256;
- }
- clear_line (); // remove last gauge
- gb_name_len = (buffer[0x143] == 0x80 || buffer[0x143] == 0xc0) ?
- GB_NAME_LEN : GB_NAME_LEN + 1;
- memcpy (game_name, buffer + 0x134, gb_name_len);
- game_name[gb_name_len] = 0;
- for (i = 0; i < gb_name_len; i++)
- if (!isprint ((int) game_name[i]) && game_name[i] != 0)
- game_name[i] = '.';
- printf ("Found another game: \"%s\"\n\n", game_name);
- }
- }
- }
- }
- static int
- verify_rom_16k (unsigned int bank) // ROM or EEPROM
- {
- int idx = 0, i, j;
- set_bank2 (bank);
- for (j = 0; j < 64; j++)
- { // 16k bytes = 64 x 256 bytes
- if (bank)
- set_ai_data ((unsigned char) 1, (unsigned char) (j | 0x40)); // set adr[15..8]
- else
- set_ai_data ((unsigned char) 1, (unsigned char) j);
- set_ai_data ((unsigned char) 0, 0); // a[7..0]
- set_ai_data ((unsigned char) 2, 0x81); // enable read inc.
- set_ai (3); // read/write data
- set_data_read
- for (i = 0; i < 256; i++)
- if (read_data () != buffer[idx + i])
- {
- printf ("\nWARNING: Verify error at 0x%x\n",
- (bank * 16384) + (j * 256) + i);
- return -1;
- }
- idx += 256;
- }
- return 0;
- }
- static int
- win_write_eeprom_16k (unsigned int bank)
- {
- int wr_done, err_cnt, idx = 0, i, j;
- // disable_protection ();
- for (j = 0; j < 64; j++)
- { // 16k bytes = 64 x 256 bytes
- err_cnt = 16; // retry write counter
- wr_done = 1;
- while (wr_done)
- {
- enable_protection ();
- // write 256 bytes
- set_bank (0x2000, (unsigned char) bank); // for MCB1 16k bank
- if (bank)
- set_ai_data ((unsigned char) 1, (unsigned char) (j | 0x40)); // set adr[15..8]
- else
- set_ai_data ((unsigned char) 1, (unsigned char) j);
- set_ai_data ((unsigned char) 0, 0); // a[7..0]
- // set_ai_data ((unsigned char) 2, 0x82); // enable flash write
- set_ai_data ((unsigned char) 2, 0x83); // enable flash write inc.
- set_ai (3); // read/write data
- // set_ai_data ((unsigned char) 2, 0x80);
- for (i = 0; i < 256; i++)
- write_data (buffer[idx + i]); // write data to EEPROM
- set_ai_data ((unsigned char) 2, 0x80); // disable wr/rd inc.
- set_ai_data ((unsigned char) 0, 0xff); // point to xxff
- if (data_polling ())
- puts ("\nWARNING: Write error"); // was: "Write error check (d6)"
- wr_done = 0;
- // verify 256 bytes
- set_ai_data ((unsigned char) 0, 0); // a[7..0]
- set_ai_data ((unsigned char) 2, 0x81); // enable read inc.
- set_ai (3); // read/write data
- set_data_read
- for (i = 0; i < 256; i++)
- if (read_data () != buffer[idx + i])
- {
- err_cnt--;
- wr_done = 1;
- break;
- }
- if (err_cnt == 0)
- {
- fputs ("\nERROR: Programming failed after retry\n", stderr);
- return -1;
- }
- }
- idx += 256;
- }
- /*
- enable_protection();
- disable_protection();
- delay_us (20000);
- */
- return verify_rom_16k (bank);
- }
- static void
- set_page_write (void) // start page write command
- {
- out_adr2_data (0x5555, 0xaa); // 5555:aa adr2,adr1,adr0,data
- out_adr2_data (0x2aaa, 0x55); // 2aaa:55
- out_adr2_data (0x5555, 0xa0); // 5555:a0
- }
- static int
- page_write_128 (unsigned int bank, unsigned char hi_lo, int j, int idx)
- {
- int retry = 3, verify_ok, i;
- while (retry)
- {
- set_page_write (); // each page is 128 bytes
- set_bank (0x2000, (unsigned char) bank); // for MCB1 16k bank
- if (bank)
- set_ai_data ((unsigned char) 1, (unsigned char) (j | 0x40)); // set adr[15..8]
- else
- set_ai_data ((unsigned char) 1, (unsigned char) j);
- set_ai_data ((unsigned char) 0, hi_lo); // a[7..0]
- set_ai_data ((unsigned char) 2, 0x83); // enable flash write inc.
- set_ai (3); // read/write data
- for (i = 0; i < 128; i++)
- write_data (buffer[idx + i]); // write data to EEPROM
- set_ai_data ((unsigned char) 2, 0x80); // disable wr/rd inc.
- delay_us (10); // delay is large enough? - dbjh
- if (wait_status ())
- return -1; // wait_status() prints error message
- // verify data
- reset_to_read (); // return to read mode
- verify_ok = 1; // verify OK
- set_bank (0x2000, (unsigned char) bank); // for MCB1 16k bank
- if (bank)
- set_ai_data ((unsigned char) 1, (unsigned char) (j | 0x40)); // set adr[15..8]
- else
- set_ai_data ((unsigned char) 1, (unsigned char) j);
- set_ai_data ((unsigned char) 0, hi_lo); // a[7..0]
- set_ai_data ((unsigned char) 2, 0x81); // enable inc.
- set_ai (3); // read/write data
- set_data_read
- for (i = 0; i < 128; i++) // page = 128
- if (read_data () != buffer[idx + i])
- {
- verify_ok = 0; // verify error
- break;
- }
- if (verify_ok)
- break;
- else
- {
- retry--;
- if (retry == 0)
- {
- fputs ("\nERROR: Programming failed after retry\n", stderr);
- return -1;
- }
- }
- }
- return 0;
- }
- static int
- mx_write_eeprom_16k (unsigned int bank)
- {
- int idx = 0, j;
- for (j = 0; j < 64; j++)
- { // 16k bytes = 64 x 256 bytes
- if (page_write_128 (bank, 0, j, idx)) // write first 128 bytes
- return -1;
- idx += 128;
- if (page_write_128 (bank, 0x80, j, idx)) // write second 128 bytes
- return -1;
- idx += 128;
- }
- reset_to_read (); // return to read mode
- return verify_rom_16k (bank);
- }
- /*
- static void
- dump_intel_data (void)
- {
- int i;
- out_adr_data (0, 0xff); // read array command
- for (i = 0; i < 64; i++)
- { // read 0x100-0x150 to buffer
- set_adr (i);
- buffer[i] = read_data ();
- }
- dumper (stdout, buffer, 64, 0, DUMPER_HEX);
- }
- static int
- intel_byte_write_32 (unsigned int block_adr, int idx)
- {
- int time_out, i;
- for (i = 0; i < 32; i++)
- {
- out_adr_data (block_adr + idx + i, 0x40); // Write byte command
- out_adr_data (block_adr + idx + i, buffer[idx + i]); // Write data
- time_out = 0x8000;
- if (intel_check_status ())
- {
- fprintf (stderr, "\nERROR: Intel byte write command time out\n"
- " Status = 0x%02x\n", intel_read_status ());
- // dump_intel_data ();
- return -1;
- }
- }
- if (intel_read_status () == 0x80)
- return 0;
- else
- return -1; // error
- }
- */
- static int
- intel_buffer_write_32 (unsigned int block_adr, int idx)
- {
- int time_out = 0x80000, i;
- out_adr_data (block_adr + idx, 0xe8); // Write buffer command
- set_ai_data ((unsigned char) 2, 0x82); // wei enable
- set_ai (3); // default write mode
- // write_data (0xe8); // Write buffer command
- set_data_read // ninit=0, nwrite=1
- while (!(read_data () & 0x80))
- {
- time_out--;
- if (time_out == 0)
- {
- fprintf (stderr, "\nERROR: Intel buffer write command time out\n"
- " Status = 0x%02x\n", intel_read_status ());
- // dump_intel_data ();
- return -1;
- }
- set_data_write
- write_data (0xe8); // out data
- set_data_read
- // out_byte_eeprom (0xe8); // write buffer command
- }
- // out_byte_eeprom (0x1f); // set write byte count command
- write_data (0x1f); // out data
- set_ai_data ((unsigned char) 2, 0x83); // enable flash write inc.
- set_ai (3);
- for (i = 0; i < 32; i++)
- write_data (buffer[idx + i]); // write data to EEPROM
- write_data (0xd0); // write confirm command
- return 0;
- }
- static int
- intel_write_eeprom_16k (unsigned int bank)
- {
- unsigned int block_adr = bank << 14; // convert to real address
- int idx, j;
- if ((bank & 0x07) == 0)
- if (intel_block_erase (block_adr))
- return -1;
- // set_adr_long (block_adr, 0); // set real address
- for (j = 0; j < 512; j++)
- { // 16k bytes = 512 x 32 bytes
- idx = j * 32;
- // if (intel_byte_write_32 (block_adr, idx)) return -1;
- if (intel_buffer_write_32 (block_adr, idx))
- {
- fprintf (stderr, "\nERROR: Write error\n"
- " Status = 0x%02x\n", intel_read_status ());
- return -1;
- }
- }
- if (intel_check_status ())
- {
- fprintf (stderr, "\nERROR: Intel buffer write command error\n"
- " Status = 0x%02x\n", intel_read_status ());
- // dump_intel_data();
- return -1;
- }
- if (intel_read_status () != 0x80)
- return -1; // error
- out_adr_data (0, 0xff); // read array
- set_data_read
- return verify_rom_16k (bank);
- }
- static int
- write_eeprom_16k (unsigned int bank)
- {
- if (eeprom_type == WINBOND) // Winbond 4 Mbits EEPROM
- return win_write_eeprom_16k (bank);
- if (eeprom_type == MX) // MX 16 Mbits EEPROM
- return mx_write_eeprom_16k (bank);
- if (eeprom_type == INTEL) // Intel 64 Mbits EEPROM
- return intel_write_eeprom_16k (bank);
- return -1;
- }
- static void
- enable_sram_bank (void)
- {
- init_port ();
- set_adr (0x0000); // write 0x0000:0x0a default read mode
- out_byte (0x0a); // enable SRAM
- out_byte (0xc0); // disable SRAM
- set_adr (0xa000);
- out_byte (0xa0); // ctr index
- set_adr (0xa100);
- // out_byte(0x00); // ram_off,ram_bank_disable,MBC1
- out_byte (0xc0); // ram_on,ram_bank_enable,MBC1
- set_adr (0x0000); // write 0x0000:0x0a
- out_byte (0x0a); // enable SRAM
- }
- /*
- static void
- usage (char *progname)
- {
- fprintf (stderr, "Usage: %s [-option] <Filename>\n", progname);
- fprintf (stderr, "-l : load ROM file to GB Card.\n");
- fprintf (stderr, "-lsa : load 256k/1Mbits sram from PC to GB Card.\n");
- fprintf (stderr,
- "-lsn : load 64kbits sram file from PC to specific sram bank(-n) in GB card.\n");
- fprintf (stderr, "-lsc : load 1Mbits sram file from PC to Pocket Camera.\n");
- fprintf (stderr, "-b : auto-detect size and backup entire GB Card to PC.\n");
- fprintf (stderr, "-ba : backup full 4Mbits/16Mbits GB Card to PC.\n");
- fprintf (stderr, "-bsa : retrieve all sram data (256k/1Mbits) from GB Card to PC.\n");
- fprintf (stderr,
- "-bsn : retrieve specific bank(-n) sram data(64kbits) from GB Card to PC.\n");
- fprintf (stderr, "-bsc : retrieve 1Mbits sram from Pocket Camera to PC.\n");
- fprintf (stderr, "-v : verify file in PC with GB Card.\n");
- fprintf (stderr, "-e : erase Flash rom.\n");
- fprintf (stderr, "-c : check ROM file header.\n");
- exit (2);
- }
- */
- static int
- check_port_mode (void)
- {
- init_port ();
- set_ai_data ((unsigned char) 1, 0x12);
- set_ai_data ((unsigned char) 0, 0x34);
- set_ai (1);
- set_data_read // ninit=0, nwrite=1
- if (read_data () != 0x12)
- return 1;
- set_ai (0);
- set_data_read // ninit=0, nwrite=1
- if (read_data () != 0x34)
- return 1;
- end_port ();
- return 0;
- }
- static int
- check_port (void)
- {
- if (ucon64.parport_mode == UCON64_EPP && port_8 != 0x3bc)
- port_mode = UCON64_EPP; // if port == 0x3bc => no EPP available
- else
- port_mode = UCON64_SPP;
- if (check_port_mode ())
- {
- port_mode = UCON64_SPP;
- if (check_port_mode ())
- return 1;
- else
- end_port ();
- }
- // If we get here, a GBX was detected
- if (port_mode == UCON64_EPP)
- puts ("GBX found. EPP found");
- else
- puts ("GBX found. EPP not found or not enabled - SPP used");
- return 0;
- }
- #if 0 // not used
- static void
- win_id (void)
- {
- out_data (0, 0x55, 0x55, 0xaa); // software product ID entry
- out_data (0, 0x2a, 0xaa, 0x55); // adr2,adr1,adr0,data
- out_data (0, 0x55, 0x55, 0x80); // adr2,adr1,adr0,data
- out_data (0, 0x55, 0x55, 0xaa); // adr2,adr1,adr0,data
- out_data (0, 0x2a, 0xaa, 0x55); // adr2,adr1,adr0,data
- out_data (0, 0x55, 0x55, 0x60); // adr2,adr1,adr0,data
- delay_us (10);
- set_adr (0); // adr2,adr1,adr0
- printf ("Manufacturer code: 0x%02x\n", read_byte ());
- set_adr (1); // adr2,adr1,adr0
- printf ("Device code: 0x%02x\n", read_byte ());
- /*
- set_adr (2); // adr2,adr1,adr0
- printf ("First 16 k protection code: 0x%02x\n", read_byte ());
- set_bank (0x2000, 0x1f);
- set_adr (0x7ff2); // adr2,adr1,adr0=0x7fff2
- printf("Last 16 k protection code: 0x%02x\n", read_byte ());
- */
- out_data (0, 0x55, 0x55, 0xaa); // software product ID exit
- out_data (0, 0x2a, 0xaa, 0x55); // adr2,adr1,adr0,data
- out_data (0, 0x55, 0x55, 0xf0); // adr2,adr1,adr0,data
- }
- static void
- mx_id (void)
- {
- out_adr2_data (0x5555, 0xaa); // software product ID entry
- out_adr2_data (0x2aaa, 0x55); // adr2,adr1,adr0,data
- out_adr2_data (0x5555, 0x90); // adr2,adr1,adr0,data
- set_adr (0); // adr2,adr1,adr0
- printf ("Manufacturer code: 0x%02x\n", read_byte ());
- set_adr (2); // adr2,adr1,adr0
- printf ("Device code: 0x%02x\n", read_byte ());
- set_adr (4); // adr2,adr1,adr0
- printf ("First 16 k protection code: 0x%02x\n", read_byte ());
- reset_to_read (); // reset to read mode
- }
- static void
- intel_id (void)
- {
- int i;
- out_adr_data (0, 0x98); // read query
- for (i = 0; i < 128; i += 2)
- {
- set_adr (i); // adr2,adr1,adr0
- buffer[i / 2] = read_byte ();
- }
- // dumper (stdout, buffer, 64, 0, DUMPER_HEX);
- printf ("Manufacture code = 0x%02x\n", buffer[0]);
- printf ("Device code = 0x%02x\n", buffer[1]);
- }
- static void
- disp_id (void)
- {
- if (eeprom_type == WINBOND)
- win_id ();
- if (eeprom_type == MX)
- mx_id ();
- if (eeprom_type == INTEL)
- intel_id ();
- }
- static void
- gen_pat (unsigned int offset)
- {
- int i;
- for (i = 0; i < 0x2000; i++) // 8 k words = 16 k bytes
- ((unsigned short int *) buffer)[i] = i + offset;
- }
- static int
- test_sram_v (int n_banks)
- {
- int idx, i, j, bank;
- enable_sram_bank ();
- for (bank = 0; bank < n_banks; bank++)
- {
- idx = 0;
- set_sram_bank (bank);
- gen_pat (bank);
- for (j = 0; j < 0x20; j++)
- { // 32 x 256 = 8192 (8 kbytes)
- set_ai_data ((unsigned char) 1, (unsigned char) (0xa0 + j)); // SRAM at 0xa000-0xbfff
- set_ai_data ((unsigned char) 0, 0); // a[7..0]=0
- set_ai_data ((unsigned char) 2, 0x81); // enable inc
- set_ai (3); // point to data r/w port
- set_data_read
- for (i = 0; i < 256; i++)
- if (read_data () != buffer[i + idx])
- {
- fputs ("ERROR: SRAM verify error\n", stderr);
- return -1;
- }
- set_ai_data ((unsigned char) 2, 0x80); // disable inc
- idx += 256;
- }
- }
- return 0;
- }
- static int
- test_sram_wv (int n_banks)
- {
- int idx, i, j, bank;
- enable_sram_bank ();
- for (bank = 0; bank < n_banks; bank++)
- {
- idx = 0;
- set_sram_bank (bank);
- gen_pat (bank);
- // dumper (stdout, buffer, 0x10, 0, DUMPER_HEX);
- for (j = 0; j < 0x20; j++)
- { // 32 x 256 = 8192(8kbytes)
- set_ai_data ((unsigned char) 1, (unsigned char) (0xa0 + j)); // SRAM at 0xa000-0xbfff
- set_ai_data ((unsigned char) 0, 0); // a[7..0]=0
- set_ai_data ((unsigned char) 2, 0x81); // enable inc
- set_ai (3); // point to data r/w port
- set_data_write
- for (i = 0; i < 256; i++)
- write_data (buffer[i + idx]);
- set_ai_data ((unsigned char) 2, 0x80); // disable inc
- idx += 256;
- }
- }
- return test_sram_v (n_banks);
- }
- int cart_type = 0; // should be set to value of ROM[0x147]
- static void
- set_rom_bank (unsigned char bank)
- {
- // cart_type < 4 is MCB1, other is MCB2
- if (cart_type < 4)
- set_bank (0x2000, bank); // for MCB1
- else
- set_bank (0x2100, bank); // for MCB2
- }
- static void
- try_read (void)
- {
- int i;
- set_ai_data ((unsigned char) 0, 0); // a[7..0]=0
- set_ai_data ((unsigned char) 1, 0x40);
- set_ai_data ((unsigned char) 2, 0x81); // enable inc
- set_ai (3); // point to data r/w port
- for (i = 0; i < 16; i++)
- buffer[i] = read_data ();
- dumper (stdout, buffer, 16, 0, DUMPER_HEX);
- }
- static void
- try_read0 (void)
- {
- int j;
- set_rom_bank (1);
- for (j = 0; j < 4; j++)
- {
- set_sram_bank ((unsigned char) j);
- try_read ();
- }
- set_bank (0x6000, (unsigned char) 1);
- puts ("6000:1");
- for (j = 0; j < 4; j++)
- {
- set_sram_bank ((unsigned char) j);
- try_read ();
- }
- set_bank (0x6000, (unsigned char) 0);
- puts ("6000:0");
- for (j = 0; j < 4; j++)
- {
- set_sram_bank ((unsigned char) j);
- try_read ();
- }
- }
- static void
- test_intel (void)
- {
- int i;
- out_adr2_data (0x0000, 0x90); // software product ID entry
- for (i = 0; i < 128; i += 2)
- {
- set_adr (i); // adr2,adr1,adr0
- buffer[i / 2] = read_byte ();
- }
- dumper (stdout, buffer, 64, 0, DUMPER_HEX);
- out_adr2_data (0x0000, 0x70); // read status register
- printf ("Status register = 0x%02x\n", read_byte ());
- }
- static void gbx_init (unsigned short parport, int read_header);
- static int
- verify_card_from_file (const char *filename, unsigned int parport)
- {
- unsigned int bank, n_banks, filesize;
- FILE *file;
- time_t starttime;
- gbx_init (parport, 1);
- filesize = fsizeof (filename);
- if ((filesize < 0x8000) || (filesize & 0x7fff) || (filesize > 64 * MBIT))
- {
- fputs ("ERROR: File size error\n", stderr);
- exit (1);
- }
- if ((file = fopen (filename, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
- exit (1);
- }
- n_banks = (filesize / 0x8000) * 2; // how many 16k banks (rounded
- starttime = time (NULL); // down to 32k boundary)
- for (bank = 0; bank < n_banks; bank++)
- {
- if (fread (buffer, 1, 0x4000, file) != 0x4000)
- {
- fprintf (stderr, ucon64_msg[READ_ERROR], filename);
- fclose (file);
- exit (1);
- }
- /*
- if (bank == 0)
- {
- // [0x147] = ROM type; [0x148] = ROM size
- if (buffer[0x147] > 0 && buffer[0x147] < 4 && buffer[0x148] > 4)
- mbc1_exp = 1; // MBC1 8 Mbit/16 Mbit
- }
- */
- if (verify_eeprom_16k (bank))
- {
- printf ("Verify card error at bank 0x%x\n", bank);
- fclose (file);
- exit (1);
- }
- ucon64_gauge (starttime, (bank + 1) * 0x4000, filesize);
- }
- fclose (file);
- puts ("\nVerify card OK");
- return 0;
- }
- #endif
- static void
- gbx_init (unsigned short parport, int read_header)
- {
- int i;
- eeprom_type = UNKNOWN_EEPROM;
- rocket_game_no = 0;
- port_8 = parport;
- port_9 = parport + 1;
- port_a = parport + 2;
- port_b = parport + 3;
- port_c = parport + 4;
- parport_print_info ();
- if (check_port () != 0)
- {
- fputs ("ERROR: GBX not found or not turned on\n", stderr);
- exit (1);
- }
- init_port ();
- check_eeprom ();
- if (read_header)
- for (i = 0x100; i < 0x150; i++)
- { // read 0x100-0x150 to buffer
- set_adr (i);
- buffer[i - 0x100] = read_data ();
- }
- /*
- buffer is undefined if read_header == 0. This is not a problem as
- read_header is only 0 if a flash card should be programmed
- (gbx_write_rom()). In that case check_mbc() won't use buffer.
- */
- check_mbc ();
- }
- int
- gbx_read_rom (const char *filename, unsigned short parport)
- {
- unsigned int bank, n_banks, rom_size, n_bytes = 0, totalbytes;
- time_t starttime;
- FILE *file;
- gbx_init (parport, 1);
- rom_size = check_card ();
- if ((file = fopen (filename, "wb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
- end_port ();
- exit (1);
- }
- /*
- 0 256 kbit = 32 kB = 2 banks
- 1 512 kbit = 64 kB = 4 banks
- 2 1 Mbit = 128 kB = 8 banks
- 3 2 Mbit = 256 kB = 16 banks
- 4 4 Mbit = 512 kB = 32 banks
- 5 8 Mbit = 1 MB = 64 banks
- 6 16 Mbit = 2 MB = 128 banks
- */
- n_banks = rom_size / (16 * 1024);
- if (eeprom_type == WINBOND)
- n_banks = 32; // backup 4 Mbit
- if (eeprom_type == MX)
- n_banks = 128; // backup 16 Mbit
- if (eeprom_type == INTEL)
- n_banks = 512; // backup 64 Mbit
- totalbytes = n_banks * 16 * 1024;
- printf ("Receive: %d Bytes (%.4f Mb)\n\n", totalbytes, (float) totalbytes / MBIT);
- starttime = time (NULL);
- for (bank = 0; bank < n_banks; bank++)
- {
- read_rom_16k (bank);
- if (verify_rom_16k (bank))
- printf ("Verify card error at bank 0x%x\n", bank);
- fwrite (buffer, 1, 0x4000, file);
- n_bytes += 16 * 1024;
- ucon64_gauge (starttime, n_bytes, totalbytes);
- }
- fclose (file);
- end_port ();
- return 0;
- }
- int
- gbx_write_rom (const char *filename, unsigned short parport)
- {
- int bank, n_banks, n_bytes = 0;
- time_t starttime;
- FILE *file;
- gbx_init (parport, 0);
- if (eeprom_type == UNKNOWN_EEPROM)
- {
- fputs ("ERROR: Unknown EEPROM type\n", stderr);
- end_port ();
- exit (1);
- }
- if ((ucon64.file_size < 0x8000) || (ucon64.file_size & 0x7fff) ||
- (ucon64.file_size > 64 * MBIT))
- {
- fputs ("ERROR: File size error\n", stderr);
- exit (1);
- }
- n_banks = (ucon64.file_size / 0x8000) * 2; // how many 16k banks (rounded
- // down to 32k boundary)
- if (eeprom_type == MX)
- if (mx_erase ()) // erase 16M flash
- {
- // wait_status() prints error message
- end_port ();
- exit (1);
- }
- if ((file = fopen (filename, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
- end_port ();
- exit (1);
- }
- printf ("Send: %d Bytes (%.4f Mb)\n\n",
- n_banks * 0x4000, (float) (n_banks * 0x4000) / MBIT);
- starttime = time (NULL);
- for (bank = 0; bank < n_banks; bank++)
- {
- if (fread (buffer, 1, 0x4000, file) != 0x4000)
- {
- fprintf (stderr, ucon64_msg[READ_ERROR], filename);
- fclose (file);
- end_port ();
- exit (1);
- }
- if (write_eeprom_16k (bank))
- {
- fprintf (stderr, "ERROR: Write card error at bank 0x%x\n", bank);
- fclose (file);
- end_port ();
- exit (1);
- }
- n_bytes += 0x4000;
- ucon64_gauge (starttime, n_bytes, ucon64.file_size);
- }
- #if 0 // write_eeprom_16k() already calls verify_rom_16k() (indirectly)...
- clear_line (); // remove last gauge
- puts ("Verifying card...\n");
- fseek (file, 0, SEEK_SET);
- n_bytes = 0;
- starttime = time (NULL);
- for (bank = 0; bank < n_banks; bank++)
- {
- if (fread (buffer, 1, 0x4000, file) != 0x4000)
- {
- fprintf (stderr, ucon64_msg[READ_ERROR], filename);
- fclose (file);
- end_port ();
- exit (1);
- }
- if (verify_rom_16k (bank))
- {
- fprintf (stderr, "ERROR: Verify card error at bank 0x%x\n", bank);
- fclose (file);
- end_port ();
- exit (1);
- }
- n_bytes += 0x4000;
- ucon64_gauge (starttime, n_bytes, ucon64.file_size);
- }
- #endif
- fclose (file);
- end_port ();
- return 0;
- }
- static int
- sram_size_banks (int pocket_camera, unsigned char sram_size_byte)
- {
- int n_banks;
- if (eeprom_type == UNKNOWN_EEPROM)
- {
- // it seems reasonable that eeprom_type == UNKNOWN_EEPROM when a pocket
- // camera (1 Mbit SRAM) is plugged in the GBX
- if (pocket_camera)
- n_banks = 16;
- else // no flash card, must be game cartridge
- {
- int x = (sram_size_byte & 7) << 1;
- if (x > 5)
- x = 6;
- if (x)
- x = 1 << (x - 1); // SRAM size in kB
- n_banks = (x + 8192 - 1) / 8192; // round up to 1 bank if it's 2 kB
- }
- }
- else
- {
- // if eeprom_type != UNKNOWN_EEPROM, it has to be WINBOND, MX or INTEL (no
- // need to set n_banks to a default value)
- if (eeprom_type == WINBOND)
- n_banks = 4; // 4 x 8 kB = 32 kB
- else // if (eeprom_type == MX || eeprom_type == INTEL)
- n_banks = 16; // 16 x 8 kB = 128 kB
- }
- return n_banks;
- }
- int
- gbx_read_sram (const char *filename, unsigned short parport, int start_bank)
- {
- int bank, n_banks, n_bytes = 0, totalbytes, idx, i, j;
- time_t starttime;
- FILE *file;
- gbx_init (parport, 1);
- n_banks = sram_size_banks (buffer[0x47] == 0x1f, buffer[0x49]);
- if (!n_banks)
- {
- fputs ("ERROR: No SRAM available\n", stderr);
- end_port ();
- exit (1);
- }
- if (start_bank == -1)
- start_bank = 0;
- else
- {
- if (start_bank >= n_banks)
- {
- fprintf (stderr, "ERROR: Bank must be a value 0 - %d (for this card)\n",
- n_banks - 1);
- end_port ();
- exit (1);
- }
- n_banks = 1;
- }
- if ((file = fopen (filename, "wb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], filename);
- end_port ();
- exit (1);
- }
- memset (buffer, 0, 8192);
- totalbytes = n_banks * 8192;
- printf ("Receive: %d Bytes (%.4f Mb)\n\n", totalbytes, (float) totalbytes / MBIT);
- enable_sram_bank ();
- starttime = time (NULL);
- for (bank = start_bank; bank < start_bank + n_banks; bank++)
- {
- idx = 0;
- set_sram_bank ((unsigned char) bank);
- for (j = 0; j < 32; j++)
- { // 32 x 256 = 8192 (8 kbytes)
- set_ai_data ((unsigned char) 1, (unsigned char) (0xa0 + j)); // SRAM at 0xa000-0xbfff
- set_ai_data ((unsigned char) 0, 0); // a[7..0]=0
- set_ai_data ((unsigned char) 2, 0x81); // enable inc
- set_ai (3); // point to data r/w port
- set_data_read
- for (i = 0; i < 256; i++)
- buffer[idx + i] = read_data ();
- set_ai_data ((unsigned char) 2, 0x80); // disable inc
- idx += 256;
- }
- fwrite (buffer, 1, 8192, file);
- n_bytes += 8192;
- ucon64_gauge (starttime, n_bytes, totalbytes);
- }
- fclose (file);
- end_port ();
- return 0;
- }
- int
- gbx_write_sram (const char *filename, unsigned short parport, int start_bank)
- {
- int bank, n_banks, n_bytes = 0, totalbytes, idx, i, j;
- time_t starttime;
- FILE *file;
- gbx_init (parport, 1);
- n_banks = sram_size_banks (buffer[0x47] == 0x1f, buffer[0x49]);
- if (!n_banks)
- {
- fputs ("ERROR: No SRAM to write to\n", stderr);
- end_port ();
- exit (1);
- }
- if (start_bank == -1)
- {
- start_bank = 0;
- n_banks = MIN (n_banks, (ucon64.file_size + 8192 - 1) / 8192); // "+ 8192 - 1" to round up
- }
- else
- {
- if (start_bank >= n_banks)
- {
- fprintf (stderr, "ERROR: Bank must be a value 0 - %d (for this card)\n",
- n_banks - 1);
- end_port ();
- exit (1);
- }
- n_banks = 1;
- }
- if ((file = fopen (filename, "rb")) == NULL)
- {
- fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], filename);
- end_port ();
- exit (1);
- }
- memset (buffer, 0, 8192);
- totalbytes = n_banks * 8192; // yes, we _send_ totalbytes bytes
- printf ("Send: %d Bytes (%.4f Mb)\n\n", totalbytes, (float) totalbytes / MBIT);
- enable_sram_bank ();
- starttime = time (NULL);
- for (bank = start_bank; bank < start_bank + n_banks; bank++)
- {
- idx = 0;
- if (!fread (buffer, 1, 8192, file))
- { // handle/allow files that are not an exact multiple of 8 kB
- fprintf (stderr, ucon64_msg[READ_ERROR], filename);
- fclose (file);
- end_port ();
- exit (1);
- }
- set_sram_bank ((unsigned char) bank);
- for (j = 0; j < 32; j++)
- { // 32 x 256 = 8192 (8 kbytes)
- set_ai_data ((unsigned char) 1, (unsigned char) (0xa0 + j)); // SRAM at 0xa000-0xbfff
- set_ai_data ((unsigned char) 0, 0); // a[7..0]=0
- set_ai_data ((unsigned char) 2, 0x81); // enable inc
- set_ai (3); // point to data r/w port
- set_data_write
- for (i = 0; i < 256; i++)
- write_data (buffer[idx + i]);
- set_ai_data ((unsigned char) 2, 0x80); // disable inc
- idx += 256;
- }
- n_bytes += 8192;
- ucon64_gauge (starttime, n_bytes, totalbytes);
- }
- fclose (file);
- end_port ();
- return 0;
- }
- #endif // USE_PARALLEL
|