This commit is contained in:
optixx
2009-08-28 08:54:46 +02:00
parent cd948a94d1
commit 98c470dbc0
236 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
351258: UNROM
351298: UNROM
351908
352026: TLROM (w/ LS32 for VROM enable control)
51555: Acclaim, MMC3B mapper, PRG ROM, CHR ROM
53361
54425
55741
56504
AMROM: LS161, VRAM, PRG-ROM
ANROM: LS161+LS02 mapper, PRG-ROM, CHR-RAM
AOROM: LS161 mapper, PRG-ROM, CHR-ROM
BNROM: LS161, VRAM, PRG-ROM (Different LS161 bits? Only used on Deadly Towers)
CNROM: LS161 mapper, PRG-ROM, CHR-ROM?/CHR-RAM
COB: "Glop Top" style board
CPROM: LS04, LS08, LS161, 32K ROM, 16K VRAM (bankswitched, Videomation only)
DEIROM
DEROM
DRROM: MMC3, 4K of nametable RAM (for 4-screen), PRG-ROM, CHR-ROM (only in Gauntlet)
EKROM
ELROM: MMC5, PRG-ROM, CHR-ROM
ETROM: MMC5, PRG-ROM, CHR-ROM, 2x 8k optionnal RAM (battery)
EWROM: MMC5, PRG-ROM, CHR-ROM, 32k optionnal RAM (battery)
GNROM: LS161 mapper, PRG ROM, CHR ROM
HKROM: MMC6B, PRG-ROM, CHR-ROM, Battery
MHROM: LS161 mapper, black blob chips. Mario Bros / Duck Hunt multi
NES-B4: Same as TLROM
NES-BTR: Sunsoft FME7 mapper, PRG ROM, CHR ROM, 8k optionnal RAM
NES-QJ:
NES-RROM: Same as NROM (Only used in Clu Clu land)
NROM: No mapper, PRG-ROM, CHR-ROM
PNROM: MMC2, PRG-ROM, CHR-ROM
SAROM: MMC1B, PRG ROM, CHR ROM, optional 8k of RAM (battery)
SBROM: MMC1A, PRG ROM, CHR ROM (only 32K of CHR ROM)
SCEOROM
SC1ROM: MMC1B, PRG ROM, CHR ROM
SCROM: LS161, LS02, VRAM, PRG-ROM (Similar to UNROM)
SEROM: MMC1B, PRG ROM, CHR ROM
SFROM
SGROM: MMC1B, PRG ROM, 8k CHR RAM
SHROM
SJROM
SKROM: MMC1B, PRG ROM, CHR ROM, 8k optional RAM (battery)
SL1ROM: MMC3, PRG ROM, CHR ROM, LS32 (for 128K 28 pin CHR ROMs)
SL2ROM
SL3ROM
SLROM: MMC1A, PRG ROM, CHR ROM
SLRROM
SN1-ROM AW (Overlord only)
SNROM: MMC1A, PRG ROM, CHR ROM/RAM ?, 8k optional RAM (battery)
SOROM: MMC1B2, PRG ROM, VRAM, 16K of WRAM (Battery) Only 8K battery-backed
SVROM: MMC1B2, PRG ROM, VRAM, WRAM (Battery)
SUROM: MMC1B2, PRG ROM, CHR RAM/(ROM?), 8k battery-backed RAM (DW4???)
TEROM: MMC3A, PRG ROM, CHR ROM, (32k ROMs)
TFROM: MMC3B, PRG ROM, CHR ROM (64K of CHR only)
TGROM: MMC3C, PRG ROM, VRAM (512K of PRG)
TKROM: MMC3A, PRG ROM, CHR ROM, 8k optional RAM (battery)
TL1ROM: Same as TLROM
TLROM: MMC3B, PRG ROM, CHR ROM
TLSROM: Same as TLROM
TQROM: MMC3B+74HC32, PRG ROM, CHR ROM + 8k of CHR-RAM
TSROM: MMC3A, PRG ROM, CHR ROM, 8k optionnal RAM
TVROM: MMC3B, PRG ROM, CHR ROM, 4K of Nametable RAM (4-screen)
UNROM: 74LS32+74LS161 mapper, 128k PRG, 8k CHR-RAM
UOROM

View File

@@ -0,0 +1,782 @@
Name |Maker |RR|Board
--------------------------------------+--------------------+--+----------------
10 Yard Fight |Nintendo |E |NROM
110 in 1 (Canada?) |Supervision | |
1942 |Capcom |C+|NROM
1943 |Capcom |C+|UNROM
6 in 1 |Caltron |A |
720 |Mindscape |C |SGROM
8 Eyes |Taxan |C-|TLROM
A Boy and His Blob |Absolute |C |SLROM
Abadox |Milton Bradley |C |SLROM
Action 52 |Active Enterprises |A |
Addams Family |Ocean |B |SLROM
Adv of Bayou Billy |Konami |C-|SLROM
Adv of Dino Riki |Hudson |C |CNROM
Adv of Lolo |HAL |C+|SEROM
Adv of Lolo 2 |HAL |B-|TEROM
Adv of Lolo 3 |HAL |B+|SLROM
Adv of Tom Saywer |Seta |B |SLROM
Adventure Island |Hudson |D |CNROM
Adventure Island 2 |Hudson |B-|TLROM
Adventure Island 3 |Hudson |B |TLROM
After Burner |Tengen |C+|
Air Fortress |HAL |C |SJROM
Airwolf |Acclaim |C |SHROM
Al Unser Racing |Data East |C |SKROM
Aladdin Deck Enhancer |Camerica |A+|
Alfred Chicken |Mindscape |B+|UNROM
Alien 3 |LJN |B+|55741
Alien Syndrome |Tengen |C+|
All Pro Basketball |Vic Tokai |C |SLROM
Alpha Mission |SNK |C |CNROM
Amagon |American Sammy |C |UNROM
American Gladiators |Gametek |B-|SLROM
Anticipation |Nintendo |C |SEROM
Arch Rivals |Acclaim |C |AMROM
Archon |Activision |B |UNROM
Arkanoid |Taito |B+|CNROM
Arkanoid Controller |Taito |A |
Arkistas Ring |American Sammy |B |CNROM
Astyanax |Jaleco |C |TLROM
Athena |SNK |C |UNROM
Athletic World |Bandai |B-|CNROM
Attack/Killer Tomato |T*HQ |B-|SLROM
Baby Boomer |Color Dreams |B-|
Back to the Future |LJN |D |CNROM
Back to the Future 2 & 3 |LJN |C |SLROM
Bad Dudes |Data East |C |TLROM
Bad News Baseball |Tecmo |B |SLROM
Bad Street Brawler |Mattel |C |SGROM
Balloon Fight |Nintendo |C |NROM
Bandit Kings/China |Koei |B-|ETROM
Barbie |Hi Tech |B |SLROM
Bard's Tale |FCI |B-|SNROM
Base Wars |Ultra |C |TKROM
Baseball |Nintendo |E |NROM
Baseball Simulator |Culture Brain |C+|SKROM
Baseball Stars |SNK |C+|SKROM
Baseball Stars 2 |Romstar |B+|TKROM
Bases Loaded |Jaleco |E |SFROM
Bases Loaded 2 |Jaleco |D |SL3ROM
Bases Loaded 3 |Jaleco |C |TLROM
Bases Loaded 4 |Jaleco |C+|TLROM
Batman |Sunsoft |D |NES_B4
Batman Return/Joker |Sunsoft |B-|NES_BTR
Batman Returns |Konami |B+|TLROM
Battle Chess |Data East |B+|SKROM
Battle of Olympus |Broderbund |C |SGROM
Battle Tank |Absolute |B |CNROM
Battle Toads |Tradewest |D |AOROM
Battle Toads & Double Dragon |Tradewest |B+|AOROM
Battleship |Mindscape |B |CNROM
Bee 52 |Camerica |B+|
Beetlejuice |LJN |C+|AMROM
Best of the Best |Electro Brain |B+|UOROM
Bible Adventures |Wisdom Tree |B+|
Bible Adventures (blue label) |Wisdom Tree |B+|
Bible Buffet |Wisdom Tree |B+|
Big Bird Hide & Speak |Hi Tech |B |SLROM
Big Foot |Acclaim |B-|SLROM
Big Nose Freaks Out |Camerica |A |
Big Nose Freaks Out (Aladdin Cart) |Camerica |A+|
Big Nose the Caveman |Camerica |B |
Bill & Ted Adventure |LJN |C+|SLROM
Bill Elliot NASCAR |Konami |C+|TSROM
Bionic Commando |Capcom |C |SGROM
Black Bass |Hot B |B |UNROM
Blackjack |American Video |A-|
Blades of Steel |Konami |D |UNROM
Blaster Master |Sunsoft |D |SL2ROM
Blue Marlin |Hot B |B+|TLROM
Blues Brothers |Titus |B |UNROM
Bo Jackson Baseball |Data East |C+|TSROM
Bomberman |Hudson |C |NROM
Bomberman 2 |Hudson |B |SNROM
Bonks Adventure |Hudson |B+|TLROM
Boulder Dash |JVC |B+|SEROM
Break Time |FCI |B+|SFROM
Breakthru |Data East |C |(SLROM)
Bubble Bath Babes |Panesian |A+|
Bubble Bobble |Taito |D |SFROM
Bubble Bobble 2 |Taito |B |TLROM
Bucky O'Hare |Konami |B |TLROM
Bugs Bunny Birthday Blowout |Kemco |B |TSROM
Bugs Bunny Castle |Kemco |B+|SBROM
Bump & Jump |Vic Tokai |B-|CNROM
Burai Fighter |Taxan |B-|TEROM
Burger Time |Data East |B-|NROM
Cabal |Milton Bradley |C |AMROM
Caesars Palace |Virgin |B |UNROM
California Games |Milton Bradley |C |UNROM
Captain America |Data East |B |TLROM
Captain Comic |Color Dreams |B |
Captain Planet |Mindscape |B |TLROM
Captain Skyhawk |Milton Bradley |C |AMROM
Casino Kid |Sofel |C+|UNROM
Casino Kid 2 |Sofel |B+|UNROM
Castelian |Triffix |B |UNROM
Castle of Deceit |Bunch Games |B |
Castle of Dragon |Seta |B |UNROM
Castlequest |Nexoft |B |CNROM
Castlevania |Konami |E |UNROM
Castlevania 2 |Konami |D |SLROM
Castlevania 3 |Konami |C-|ELROM
Caveman Games |Data East |B-|SLROM
Challenge of the Dragon |Color Dreams |B |
Championship Bowling |Romstar |B |CNROM
Championship Pool |Mindscape |B+|UNROM
Cheetahman II |Active Enterprises |A |
Chessmaster |Hi Tech |B |SJROM
Chiller |American Game Carts Inc|B+|
Chubby Cherub |Bandai |B |NROM
Circus Caper |Toho |B |SLROM
City Connection |Jaleco |B |CNROM
Clash at Demonhead |Vic Tokai |B-|SLROM
Classic Concentration |Gametek |B-|UNROM
Cliffhanger |Imagesoft |B |TLROM
Clu Clu Land |Nintendo |B-|NES_RROM
Cobra Command |Data East |C |SLROM
Cobra Triangle |Nintendo |B-|ANROM
Codename Viper |Capcom |C |TLROM
Color A Dinosaur |Virgin |A-|UNROM
Commando |Capcom |C |UNROM
Conan |Mindscape |B |UNROM
Conflict |Vic Tokai |C+|SKROM
Conquest Crystal Palace |Asmik |C+|TLROM
Contra |Konami |E |UNROM
Contra Force |Konami |B |TLROM
Cool World |Ocean |B |SLROM
Cowboy Kid |Romstar |A-|TLROM
Crash & the Boys Street Challange |American Technos |B |TLROM
Crash Dummies |LJN |B |55741
Crystal Mines |Color Dreams |B+|
Crystalis |SNK |C |TKROM
Cyberball |Jaleco |B |TLROM
Cybernoid |Acclaim |C |CNROM
Dance Aerobics |Nintendo |C+|SBROM
Darkman |Ocean |B |SLROM
Darkwing Duck |Capcom |B+|SLROM
Dash Galaxy |Data East |C |CNROM
Day Dreamin' Davey |HAL |B+|SLROM
Days of Thunder |Mindscape |C+|TLROM
Deadly Towers |Broderbund |C+|BNROM
Death Race |American Game Carts Inc|B+|
Deathbots |American Video |B+|
Defender 2 |HAL |B |NROM
Defender of the Crown |Ultra |C+|SGROM
Defenders of Dynacron City |JVC |B |TLROM
Deja Vu |Kemco |C+|TKROM
Demon Sword |Taito |C+|SL1ROM
Desert Commander |Kemco |C-|SKROM
Destination Earthstar |Acclaim |C |CNROM
Destiny/Emporer |Capcom |B-|SNROM
Dick Tracy |Bandai |C+|UNROM
Die Hard |Activision |B+|SLROM
Dig Dug 2 |Bandai |B |NROM
Digger |Milton Bradley |B+|AMROM
Dirty Harry |Mindscape |C+|TLROM
Disney Adventure |Capcom |B |SLROM
Dizzy the Adventurer (Aladdin Cart) |Camerica |A+|
Donkey Kong |Nintendo |B-|NROM
Donkey Kong 3 |Nintendo |B-|NROM
Donkey Kong Classics |Nintendo |B-|CNROM
Donkey Kong Jr |Nintendo |B-|NROM
Donkey Kong Jr Math |Nintendo |A-|NROM
Double Dare |Gametek |B |AOROM
Double Dragon |Tradewest |E |SLROM
Double Dragon 2 |Acclaim |D |TL1ROM
Double Dragon 3 |Acclaim |C+|TLROM
Double Dribble |Konami |D |UNROM
Double Strike |American Video |B+|
Dr. Chaos |FCI |C |UNROM
Dr. Jeckyl/Mr. Hyde |Bandai |C+|SFROM (SFDOROM)
Dr. Mario |Nintendo |D |SEROM
Dracula |Imagesoft |B |TSROM
Dragon Fighter |Sofel |B |SLROM
Dragon Power |Bandai |C |GNROM
Dragon Spirit |Bandai |B |TLROM
Dragon Strike |FCI |C |TLROM
Dragon Warrior |Nintendo |E |SAROM
Dragon Warrior 2 |Enix |C+|SNROM
Dragon Warrior 3 |Enix |B+|SVROM
Dragon Warrior 4 |Enix |B |SVROM
Dragon's Lair |Imagesoft |B |UNROM
Duck Hunt |Nintendo |F |NROM
Duck Tales |Capcom |C+|UNROM
Duck Tales 2 |Capcom |B+|UNROM
Dudes with Attitude |American Video |B+|
Dungeon Magic |Taito |C |SKROM
Dusty Diamond All Star Softball |Broderbund |B-|SLROM
Dyno Warz |Bandai |C+|SLROM
Elevator Action |Taito |B-|NROM
Eliminator Boat Duel |Electro Brain |C+|SLROM
Empire Strikes Back |JVC |B |TLROM
Excitebike |Nintendo |E |NROM
Exodus |Wisdom Tree |B+|
F 117 Stealth |Microprose |B+|TLROM
F 15 City War |American Video |B |
F 15 Strike Eagle |Microprose |B+|TLROM
F1 Built to Win |Seta |B+|SKROM
Family Feud |Gametek |B+|SHROM
Fantastic Adv Dizzy (Aladdin Cart) |Camerica |A+|
Fantastic Adventures of Dizzy |Camerica |B-|
Fantasy Zone |Tengen |C |
Faria |Nexoft |B+|SKROM
Fast Break |Tradewest |C |SCROM
Faxanadu |Nintendo |C-|SGROM
Felix the Cat |Hudson |B+|TSROM
Ferrari Grand Prix |Acclaim |B |SLROM
Fester's Quest |Sunsoft |C |SLROM
Fighting Golf |SNK |C |SLROM
Final Fantasy |Nintendo |C+|SNROM
Fire & Ice |Tecmo |A-|TLROM
Fire Hawk |Camerica |B |
Firehouse Rescue |Gametek |B |CNROM
Fist of the North Star |Taxan |C+|UNROM
Flight of the Intruder |Mindscape |B |UNROM
Flintstones |Taito |C+|TLROM
Flintstones 2 |Taito |A+|
Flying Dragon |Culture Brain |C |UNROM
Flying Warriors |Culture Brain |C |SLROM
Frankenstein |Bandai |B+|SLRROM
Freedom Force |Sunsoft |D |SLROM
Friday The 13th |LJN |C-|CNROM
Fun House |Hi Tech |B+|UNROM
G I Joe |Taxan |B+|TLROM
G I Joe Atlantis Factor |Capcom |C+|TLROM
Galactic Crusader |Bunch Games |B |
Galaga |Bandai |B |NROM
Galaxy 5000 |Activision |A-|TLROM
Game Action Replay |STD |A-|
Game Genie |Galoob |D |
Gargoyle's Quest 2 |Capcom |B+|TLROM
Gauntlet (licensed) |Tengen |C |DRROM
Gauntlet (unlicensed) |Tengen |C |
Gauntlet 2 |Mindscape |C |TSROM
Gemfire |Koei |B-|EKROM
Genghis Kahn |Koei |C+|SOROM
George Forman |Acclaim |B |55741
Ghost & Goblins |Capcom |C |UNROM
Ghost Lion |Kemco |B |SKROM
Ghostbusters |Activision |B-|CNROM
Ghostbusters 2 |Activision |B |SLROM
Ghoul School |Electro Brain |B-|SLROM
Gilligans Island |Bandai |B+|UNROM
Goal |Jaleco |D |SL3ROM
Goal 2 |Jaleco |B-|TLSROM
Godzilla |Toho |C+|SLROM
Godzilla 2 |Toho |B |SLROM
Gold Metal Challenge |Capcom |B+|TKROM
Golf |Nintendo |E |NROM
Golf Grand Slam |Atlus |B+|SLROM
Golf Power |Virgin |B+|SNROM
Golgo 13 Top Secret Episode |Vic Tokai |D |SLROM
Goonies 2 |Konami |C+|351258
Gotcha |LJN |C |CNROM
Gradius |Konami |C-|CNROM
Great Waldo Search |T*HQ |B-|SLROM
Gremlins 2 |Sunsoft |B-|TLROM
Guardian Legend |Broderbund |C+|UNROM
Guerrilla War |SNK |C |SLROM
Gum Shoe |Nintendo |C+|GNROM
Gun Nac |Ascii |B |TLROM
Gunsmoke |Capcom |B-|UNROM
Gyromite |Nintendo |E |NROM
Gyruss |Ultra |C+|CNROM
Harlem Globetrotters |Gametek |B |SLROM
Hatris |Bullet Proof |A |SNROM
Heavy Barrel |Data East |C |TLROM
Heavy Shreddin' |Parker Brothers |B-|SLROM
Heroes of the Lance |FCI |C |SKROM
High Speed |Tradewest |B-|TQROM
Hillsfar |FCI |B |SNROM
Hogan's Alley |Nintendo |D |NROM
Hollywood Squares |Gametek |B+|UNROM
Home Alone |T*HQ |B-|TSROM
Home Alone 2 |T*HQ |B-|TLROM
Hook |Imagesoft |B |SLROM
Hoops |Jaleco |D |SLROM
Hot Slots |Panesian |A+|
Hudson Hawk |Imagesoft |B |SLROM
Hunt for Red October |Hi Tech |C |TLROM
Hydlide |FCI |D |NROM
I Can Remember |Gametek |B |CNROM
Ice Climber |Nintendo |C+|NROM
Ice Hockey |Nintendo |D |NROM
Ikari Warriors |SNK |C-|UNROM
Ikari Warriors 2 |SNK |C-|SGROM
Ikari Warriors 3 |SNK |B-|SLROM
Image Fight |Irem |B |TSROM
Immortal |Electronic Arts |B |TLROM
Impossible Mission 2 |American Video |A-|
Impossible Mission 2 |SEI |B+|
Indiana Jones Last Crusade |UBI Soft |B+|UNROM
Indiana Jones Last Crusade |Taito |B+|SGROM
Indiana Jones Temple of Doom |Tengen |B-|
Indiana Jones Temple of Doom |Mindscape |C |TFROM
Indy Heat |Tradewest |B |AMROM
Infiltrator |Mindscape |B |TLROM
Iron Tank |SNK |C |SLROM
Isolated Warrior |NTVIC |B |TLROM
Jack Nicklaus Golf |Konami |B-|351258
Jackal |Konami |C |UNROM
Jackie Chan Kung Fu |Hudson |B |TLROM
James Bond Jr |T*HQ |B-|TLROM
Jaws |LJN |D |CNROM
Jeopardy |Gametek |C |AOROM
Jeopardy 25th Anniversary |Gametek |C+|ANROM
Jeopardy Jr |Gametek |C |ANROM
Jeopardy Super |Gametek |B |SLROM
Jetsons |Taito |B+|TLROM
Jimmy Connors Tennis |UBI Soft |B+|UNROM
Joe & Mac |Data East |B+|TLROM
Jordan vs. Bird |Milton Bradley |C |UNROM
Joshua |Wisdom Tree |B+|
Journey to Silius |Sunsoft |C+|SLROM
Joust |HAL |B |CNROM
Jungle Book |Virgin |A-|TLROM
Jurassic Park |Ocean |B |TSROM
Karate Champ |Data East |C |CNROM
Karate Kid |LJN |C |CNROM
Karnov |Data East |C |DEIROM
Kick Master |Taito |C+|TLROM
Kickle Cubicle |Irem |B+|TLROM
Kid Icarus |Nintendo |C-|SNROM
Kid Klown |Kemco |B |TSROM
Kid Kool |Vic Tokai |C+|UNROM
Kid Niki |Data East |C |SGROM
King Neptune's Adventure |Color Dreams |B+|
King of Kings |Wisdom Tree |B+|
King of Kings (cartoon mule) |Wisdom Tree |B+|
King of the Ring |Acclaim |B+|55741
Kings Knight |Square |C+|CNROM
Kings of the Beach |Ultra |C |CNROM
Kings Quest 5 |Konami |B+|TSROM
Kirbys Adventure |Nintendo |B-|TKROM
Kiwi Kraze |Taito |B+|TLROM
Klash Ball |Sofel |B-|UNROM
Klax |Tengen |B+|
Knight Rider |Acclaim |B-|SCIROM
Krazy Kreatures |American Video |B+|
Krion Conquest |Vic Tokai |B |TLROM
Krusty's Fun House |Acclaim |C+|TLROM
Kung Fu |Nintendo |E |NROM
Kung Fu Heroes |Culture Brain |C |CNROM
L'Empereur |Koei |B |ETROM
Laser Invasion |Konami |B-|ELROM
Last Action Hero |Imagesoft |B+|TLROM
Last Ninja |Jaleco |B-|TLROM
Last Starfighter |Mindscape |C+|CNROM
Legacy/Wizard |Broderbund |C |TFROM
Legend of Kage |Taito |C-|CNROM
Legendary Wings |Capcom |B |UNROM
Legends/Diamond |Bandai |B+|TLROM
Lemmings |Sunsoft |B-|SLROM
Lethal Weapon |Ocean |B |SLROM
Life Force |Konami |C |351258
Linus Spacehead |Camerica |B |
Linus Spacehead (Aladdin Cart) |Camerica |A+|
Little League Baseball |SNK |B-|SLROM
Little Mermaid |Capcom |B |UNROM
Little Nemo |Capcom |B+|TLROM
Little Ninja Brothers |Culture Brain |C |TLROM
Little Sampson |Taito |B |TLROM
Lode Runner |Broderbund |B |NROM
Lone Ranger |Konami |B-|TLROM
Loopz |Mindscape |B+|UNROM
Low G Man |Taxan |C |TLROM
Lunar Pool |FCI |C+|NROM
M C Kids |Virgin |C+|TSROM
M.U.L.E. |Mindscape |C+|SNROM
Mach Rider |Nintendo |C-|NROM
Mad Max |Mindscape |C+|TLROM
Mafat Conspiracy |Vic Tokai |C |TLROM
Magic Darts |Romstar |B |SLRROM
Magic of Scheherazade |Culture Brain |C-|SLROM
Magician |Taxan |A-|TKROM
Magmax |FCI |C-|NROM
Major League Baseball |LJN |E |CNROM
Maniac Mansion |Jaleco |C+|SNROM
Mappyland |Taxan |C+|TFROM
Marble Madness |Milton Bradley |C+|ANROM
Mario Brothers |Nintendo |B-|NROM
Mario Is Missing |Mindscape |B |TLROM
Mario Time Machine |Mindscape |A-|TLROM
Marvel's X-Men |LJN |B-|UNROM
Master Chu & the Drunkard Hu |Color Dreams |B |
Maxi 15 |American Video |A |
Mechanized Attack |SNK |C |SCROM
Mega Man |Capcom |B-|UNROM
Mega Man 2 |Capcom |C |SGROM
Mega Man 3 |Capcom |C |TLROM
Mega Man 4 |Capcom |B-|TGROM
Mega Man 5 |Capcom |B |TLROM
Mega Man 6 |Nintendo |B+|TGROM
Menace Beach |Color Dreams |A-|
Mendel Palace |Hudson |B |TLROM
Mermaids of Atlantis |American Video |B+|
Metal Fighter |Color Dreams |B |
Metal Gear |Ultra |D |UNROM
Metal Mech |Jaleco |B-|SLROM
Metal Storm |Irem |B+|TLROM
Metroid |Nintendo |D |SNROM
Michael Andretti World GP |American Sammy |B-|TLROM
Mickey Mousecapade |Capcom |C+|CNROM
Mickey Numbers |Hi Tech |B+|TLROM
Mickey's Safari in Letterland |Hi Tech |B+|55741
Micro Machines |Camerica |A-|
Micro Machines (Aladdin Cart) |Camerica |A+|
Mig 29 |Camerica |C+|
Might & Magic |American Sammy |B+|TKROM
Mighty Bombjack |Tecmo |B |CNROM
Mighty Final Fight |Capcom |B+|TLROM
Mike Tyson's Punch Out |Nintendo |D |PNROM
Millipede |HAL |B |NROM
Milon's Secret Castle |Hudson |C |CNROM
Miracle Piano |Mindscape |A-|SJROM
Mission Cobra |Bunch Games |A-|
Mission Impossible |Ultra |C+|352026
Monopoly |Parker Brothers |B-|SLROM
Monster in my Pocket |Konami |B+|TLROM
Monster Party |Bandai |B |SLROM
Monster Truck Rally |INTV |B |CNROM
Moon Ranger |Bunch Games |C |
Motor City Patrol |Matchbox |C+|SLROM
Ms. Pacman |Namco |A |NROM
Ms. Pacman |Tengen |B+|
Muppet Adventure |Hi Tech |B |SGROM
Muscle |Bandai |B-|NROM
Mutant Virus |American Software |B+|SLROM
Mystery Quest |Taxan |C+|CNROM
NARC |Acclaim |C |AMROM
NES Open Golf |Nintendo |B-|SNROM
NFL Football |LJN |C |UNROM
Nigel Mansell |Gametek |B+|SLROM
Nightmare on Elm Street |LJN |B |AMROM
Nightshade |Ultra |C+|TLROM
Ninja Crusaders |American Sammy |B |TGROM
Ninja Gaiden |Tecmo |E |SLROM
Ninja Gaiden 2 |Tecmo |C-|TLROM
Ninja Gaiden 3 |Tecmo |C+|TLROM
Ninja Kid |Bandai |C+|CNROM
Nombunagas Ambition |Koei |C |SOROM
Nombunagas Ambition 2 |Koei |B |ETROM
North & South |Kemco |B+|TSROM
Operation Secret Storm |Color Dreams |A |
Operation Wolf |Taito |D |SLROM
ORB-3D |Hi Tech |C |SCROM
Othello |Acclaim |C |NROM
Overlord |Virgin |B-|SN1
P'radikus Conflict |Color Dreams |B |
Pac Man |Namco |A |56504
Pac Man (licensed) |Tengen |B-|NROM
Pac Man (unlicensed) |Tengen |B-|
Pac Mania |Tengen |A |
Palamedes |Hot B |B+|SEROM
Panic Resturant |Taito |B |TLROM
Paperboy |Mindscape |C |CNROM
Paperboy 2 |Mindscape |B |UOROM
Parodius (England) |Palcom | |
Pebble Beach Golf |Bandai |C+|CNROM
Peek A Boo Poker |Panesian |A+|
Perfect Fit |Gametek |B |CNROM
Pesterminator |Color Dreams |B |
Peter Pan & the Pirates |T*HQ |B-|SFROM
Phantom Fighter |FCI |C+|SGROM
Pictionary |LJN |B-|SLROM
Pinball |Nintendo |D |NROM
Pinball Quest |Jaleco |B |SLROM
Pinbot |Nintendo |B |TQROM
Pipe Dream |Bullet Proof |B |CNROM
Pirates |Ultra |B |SKROM
Platoon |Sunsoft |D |SLROM
Play Action Football |Nintendo |D |TLSROM
Pool of Radiance |FCI |B+|TKROM
Popeye |Nintendo |B-|NROM
POW |SNK |C |SLROM
Power Blade |Taito |B-|TLROM
Power Blade 2 |Taito |B-|TLROM
Power Punch 2 |American Softworks |B |TLROM
Predator |Activision |C+|SLROM
Prince of Persia |Virgin |C+|UNROM
Princess Tomato |Hudson |B+|SGROM
Pro Am |Nintendo |D |SEROM
Pro Am 2 |Tradewest |B |AOROM
Pro Sport Hockey |Jaleco |B+|TLSROM
Pro Wrestling |Nintendo |D |UNROM
Puggsly's Scavenger Hunt |Ocean |B |SLROM
Punch Out |Nintendo |C+|PNROM
Punisher |LJN |B |TLROM
Puss N Boots |Electro Brain |B-|UNROM
Puzzle |American Video |A-|
Puzznic |Taito |B+|CNROM
Pyramid |American Video |A-|
Q*Bert |Ultra |B-|CNROM
Qix |Taito |A |SNROM
Quantum Fighter |HAL |B |TLROM
Quarterback |Tradewest |D |CNROM
Quattro Adventure |Camerica |B+|
Quattro Adventure (Aladdin Cart) |Camerica |A+|
Quattro Arcade |Camerica |A-|
Quattro Sports |Camerica |B |
Quattro Sports (Aladdin Cart) |Camerica |A+|
Race America |Absolute |B+|SLROM
Racket Attack |Jaleco |C-|SLROM
Rad Gravity |Activision |B-|SLROM
Rad Racer |Nintendo |D |SGROM
Rad Racer 2 |Square |B-|TVROM
Rad Racket |American Video |A-|
Raid 2020 |Color Dreams |B |
Raid on Bungling Bay |Broderbund |B |NROM
Rainbow Island |Taito |B+|UNROM
Rally Bike |Romstar |B |UNROM
Rambo |Acclaim |E |UNROM
Rampage |Data East |C+|TFROM
Rampart |Jaleco |B |TLROM
RBI Baseball (licensed) |Tengen |C+|DEROM
RBI Baseball (unlicensed) |Tengen |C |
RBI Baseball 2 |Tengen |C+|
RBI Baseball 3 |Tengen |B-|
Remote Control |Hi Tech |C |SLROM
Ren + Stimpy Buckaroos |T*HQ |B-|TLROM
Renegade |Taito |C-|UNROM
Rescue |Kemco |C-|SLROM
Rescue Rangers |Capcom |C+|SLROM
Rescue Rangers 2 |Capcom |B+|SLROM
Ring King |Data East |C |DEROM
River City Ransom |American Technos |C |TLROM
Road Blasters |Mindscape |C+|SLROM
Road Runner |Tengen |B+|
Robin Hood |Virgin |C+|SGROM
Robo Cop |Data East |C |TL1ROM
Robo Cop 2 |Data East |B-|SLROM
Robo Cop 3 |Ocean |B |SLROM
Robo Demons |Color Dreams |B |
Robo Warrior |Jaleco |B |UNROM
Rock N Ball |NTVIC |B |TFROM
Rocket Ranger |Kemco |B-|SGROM
Rocketeer |Bandai |B-|SGROM
Rockin Kats |Atlus |B+|TLROM
Rocky & Bullwinkle |T*HQ |B-|TLROM
Roger Clemens |LJN |C |53361
Roller Games |Ultra |B-|TLROM
Rollerball |HAL |B |SFROM
Rollerblade Racer |Hi Tech |B |53361
Rolling Thunder |Tengen |C+|
Romance/3 Kingdoms |Koei |C |SOROM
Romance/3 Kingdoms 2 |Koei |B |EWROM
Roundball |Mindscape |B-|TSROM
Rush N Attack |Konami |D |UNROM
Rygar |Tecmo |C |UNROM
SCAT |Natsume |B |SLROM
Secret Scout |Color Dreams |A |
Section Z |Capcom |C |UNROM
Seicross |FCI |D |NROM
Sesame Street 1-2-3 |Hi Tech |C+|SEROM (SCROROM)
Sesame Street 123/ABC |Hi Tech |B |SLROM
Sesame Street A-B-C |Hi Tech |C+|SEROM
Sesame Street Countdown |Hi Tech |A-|SLROM
Shadow of the Ninja |Natsume |B |TLROM
Shadowgate |Kemco |C+|TKROM
Shatterhand |Jaleco |B-|TLROM
Shingen the Ruler |Hot B |C |SNROM
Shinobi |Tengen |C+|
Shockwave |American Game Carts Inc|B |
Shooting Range |Bandai |B |CNROM
Short Order/Eggsplode |Nintendo |B+|SBROM
Side Pocket |Data East |B |UNROM
Silent Assault |Color Dreams |B |
Silent Service |Ultra |C-|351258
Silk Worm |American Sammy |C |SLROM
Silver Surfer |Arcadia |B |TSROM
Simpsons Bart Meets Radioactive Man |Acclaim |B+|55741
Simpsons Bart Vs Space Mutants |Acclaim |D |SLROM
Simpsons Bart Vs World |Acclaim |B-|53361
Skate or Die |Ultra |D |351258
Skate or Die 2 |Electronic Arts |B |SLROM
Ski or Die |Ultra |B-|351908
Skull & Crossbones |Tengen |B |
Sky Kid |Sunsoft |B-|SCEOROM
Sky Shark |Taito |D |SL1ROM
Slalom |Nintendo |B-|NROM
Smash TV |Acclaim |C+|51555
Snake Rattle & Roll |Nintendo |C+|SEROM
Snakes Revenge |Ultra |C |SLROM
Snoopy Silly Sports |Kemco |B+|SLROM
Snow Brothers |Capcom |B |SLROM
Soccer |Nintendo |D |NROM
Solar Jetman |Tradewest |C |AOROM
Solitaire |American Video |A-|
Soloman's Key |Tecmo |C+|CNROM
Solstice |Imagesoft |C |ANROM
Space Shuttle |Absolute |B+|SGROM
Spelunker |Broderbund |C+|NROM
Spiderman |LJN |B-|53361
Spiritual Warfare |Wisdom Tree |B+|
Spot |Arcadia |B-|SNROM
Spy Hunter |Sunsoft |C |CNROM
Spy vs. Spy |Kemco |B-|NROM
Sqoon |Irem |B+|NROM
Stack Up |Nintendo |A-|HVC
Stadium Events |Bandai |B |
Stanley |Electro Brain |B |TLROM
Star Force |Tecmo |C+|CNROM
Star Soldier |Taxan |C-|CNROM
Star Trek 25th Anniversary |Ultra |B |TLROM
Star Trek: The Next Generation |Absolute |A-|UNROM
Star Tropics |Nintendo |C-|HKROM
Star Voyager |Acclaim |C+|CNROM
Star Wars |JVC |B |TSROM
Starship Hector |Hudson |B-|UNROM
Stealth ATF |Activision |C+|SLROM
Stinger |Konami |B-|UNROM
Street Cop |Bandai |A-|SLROM
Street Fighter 2010 |Capcom |B |TLROM
Strider |Capcom |C |SGROM
Stunt Kids |Camerica |A-|
Sunday Funday |Wisdom Tree |B+|
Super C |Konami |C |352026
Super Cars |Electro Brain |B+|UNROM
Super Dodge Ball |Imagesoft |C |SLROM
Super Glove Ball |Mattel |C |UNROM
Super Mario Brothers |Nintendo |F |NROM
Super Mario Brothers 2 |Nintendo |D |TSROM
Super Mario Brothers 3 |Nintendo |D |TSROM
Super Mario/Duck Hunt |Nintendo |F |MH
Super Mario/Duck Hunt/Track Meet |Nintendo |C |COB
Super Off Road |Tradewest |C-|AMROM
Super Pitfall |Activision |C+|UNROM
Super Spike V'Ball |Nintendo |C-|TLROM
Super Spike/World Cup |Nintendo |B-|COB
Super Sprint |Tengen |C |COB
Super Spy Hunter |Sunsoft |B+|TLROM
Super Team Games |Nintendo |C-|CNROM
Superman |Kemco |B+|SLROM
Swamp Thing |T*HQ |C+|SLROM
Sword Master |Activision |A-|TLROM
Swords & Serpents |Acclaim |B+|UNROM
T&C Surf Design |LJN |E |CNROM
Taboo |Tradewest |C+|SEROM
Tag Team Wrestling |Data East |C |NROM
Taggin Dragon |Bunch Games |B |
Talespin |Capcom |B |SLROM
Target Renegade |Taito |C+|SLROM
Tecmo Baseball |Tecmo |C |SGROM
Tecmo Basketball |Tecmo |C+|TKROM
Tecmo Bowl |Tecmo |E |SLROM
Tecmo Cup Soccer |Tecmo |B+|SLROM
Tecmo Super Bowl |Tecmo |C-|TKROM
Tecmo Wrestling |Tecmo |C |SLROM
Teenage Turtles |Ultra |E |351908
Teenage Turtles 2 |Ultra |D |TLROM
Teenage Turtles 3 |Konami |B-|TLROM
Teenage Turtles Tournament Fighters |Konami |B+|TLROM
Tennis |Nintendo |D |NROM
Terminator |Mindscape |B+|TLROM
Terminator 2 Judgement Day |LJN |B-|53361
Terra Cresta |Vic Tokai |B+|UNROM
Tetris |Tengen |A-|
Tetris |Nintendo |D |SEROM
Tetris 2 |Nintendo |B-|TSROM
Three Stooges |Activision |C+|SLROM
Thrilla Safari |LJN |B |53361
Thunder & Lightning |Romstar |B+|GNROM
Thunderbirds |Activision |C+|SLROM
Thundercade |American Sammy |C+|UNROM
Tiger Heli |Acclaim |C+|CNROM
Tiles of Fate |American Video |B+|
Time Lord |Milton Bradley |C |AMROM
Times of Lore |Toho |B-|UNROM
Tiny Toon |Konami |C+|TLROM
Tiny Toon Cartoon Workshop |Konami |B+|TSROM
Tiny Toons 2 |Konami |B+|TLROM
To The Earth |Nintendo |C+|TEROM
Toki |Taito |B+|TLROM
Tom & Jerry |Hi Tech |B+|TLROM
Tombs & Treasures |Infocom |A-|SGROM
Toobin |Tengen |B |
Top Gun |Konami |D |351298
Top Gun 2 |Konami |D |352026
Top Players Tennis |Asmik |C+|SLROM
Total Recall |Acclaim |D |UNROM
Totally Rad |Jaleco |B-|TLROM
Touchdown Fever |SNK |B+|SFROM
Toxic Crusader |Bandai |B |TLROM
Track & Field |Konami |D |CNROM
Track & Field 2 |Konami |D |SLROM
Treasure Master |American Softworks |A-|SLROM
Trick Shooting |Nintendo |C+|SCROM
Trog |Acclaim |B+|UNROM
Trojan |Capcom |C |UNROM
Trolls on Treasure Island |American Video |A-|
Twin Cobra |American Sammy |C+|TLROM
Twin Eagle |Romstar |C+|UNROM
Ultima/Exodus |FCI |C-|SNROM
Ultima/Quest Avatar |FCI |B |SNROM
Ultima/War Destiny |FCI |B+|SNROM
Ultimate Air Combat |Activision |B+|TLROM
Ultimate Basketball |American Sammy |C |TLROM
Ultimate League Soccer |American Video |A-|
Ultimate Stuntman |Camerica |C+|
Uncharted Waters |Koei |B-|ETROM
Uninvited |Kemco |B+|TKROM
Untouchables |Ocean |B-|SLROM
Urban Champion |Nintendo |D |NROM
Vegas Dream |HAL |B |SKROM
Venice Beach Volleyball |American Video |A-|
Vice Project Doom |American Sammy |C+|TLROM
Videomation |T*HQ |B+|CPROM
Vindicators |Tengen |C |
Volleyball |Nintendo |C |NROM
Wacky Races |Atlus |B+|TLROM
Wall Street Kid |Sofel |B |UNROM
Wally Bear and the No Gang |American Video |A-|
Wario Woods |Nintendo |B+|TKROM
Wayne Gretzky |T*HQ |C+|UNROM
Wayne's World |T*HQ |B |TLROM
Werewolf |Data East |C |TLROM
Wheel/Fortune |Gametek |C |AOROM
Wheel/Fortune/Family |Gametek |C |ANROM
Wheel/Fortune/Junior |Gametek |C |ANROM
Wheel/Fortune/Vanna |Gametek |B |AOROM
Where in Time is Carmen |Konami |B |TSROM
Where's Waldo |T*HQ |C+|TSROM
Who Framed Roger Rabbit |LJN |B-|ANROM
Whomp Em |Jaleco |B |TLROM
Widget |Atlus |B |TLROM
Wild Gunman |Nintendo |C |NROM
Willow |Capcom |B-|SLROM
Win Lose or Draw |Hi Tech |C |SGROM
Winter Games |Acclaim |B-|UNROM
Wizardry |Nexoft |C+|SKROM
Wizardry 2 Knight of Diamonds |Ascii |B+|TKROM
Wizards & Warriors |Acclaim |D |ANROM
Wizards & Warriors 2 - Ironsword |Acclaim |D |AOROM
Wizards & Warriors 3 |Acclaim |C-|54425
Wolverine |LJN |B-|TLROM
World Champ |Romstar |B+|TLROM
World Championship Wrestling |FCI |D |TLROM
World Class Track Meet |Nintendo |D |CNROM
World Cup Soccer |Nintendo |C-|TLROM
World Games |Milton Bradley |B-|ANROM
World Runner 3D |Acclaim |C-|UNROM
Wrath of the Black Manta |Taito |C+|SLROM
Wrecking Crew |Nintendo |C+|NROM
Wrestlemania |Acclaim |D |ANROM
Wrestlemania Challenge |LJN |C-|UNROM
Wrestlemania Steel Cage |LJN |C+|53361
Wurm |Asmik |B-|TLROM
Xenophobe |Sunsoft |B-|SFROM
Xevious |Bandai |C+|NROM
Xexyz |Hudson |C+|SLROM
Yo Noid |Capcom |C+|SLROM
Yoshi |Nintendo |C-|SFROM
Yoshi's Cookie |Nintendo |B-|TFROM
Young Indy |Jaleco |B+|TLROM
Zanac |FCI |C+|UNROM
Zelda |Nintendo |E |SNROM
Zelda 2 |Nintendo |D |SKROM
Zen |Konami |B |TLROM
Zoda's Revenge, Startropics 2 |Nintendo |B-|HKROM
Zombie Nation |Meldac |B |TLROM

View File

@@ -0,0 +1,38 @@
/*
console.h - single header for all console functions
Copyright (c) 2003 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include "dc.h"
#include "gb.h"
#include "gba.h"
#include "genesis.h"
#include "jaguar.h"
#include "lynx.h"
#include "n64.h"
#include "neogeo.h"
#include "nes.h"
#include "ngp.h"
#include "pce.h"
#include "psx.h"
#include "sms.h"
#include "snes.h"
#include "swan.h"
#endif // CONSOLE_H

View File

@@ -0,0 +1,646 @@
/*
dc.c - Dreamcast support for uCON64
Copyright (c) 2004 NoisyB <noisyb@gmx.net>
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "misc/file.h"
#include "misc/misc.h"
#include "misc/property.h"
#include "misc/string.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "dc.h"
const st_getopt2_t dc_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Dreamcast" /* "1998 SEGA http://www.sega.com" */,
NULL
},
{
"dc", 0, 0, UCON64_DC,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_DC_SWITCH]
},
#if 0
{
"vms", 1, 0, UCON64_VMS,
"SAV", "convert NES SAV file to a VMS file for use with NesterDC",
NULL
},
#endif
{
"scr", 0, 0, UCON64_SCR,
NULL, "scramble 1ST_READ.BIN for selfboot CDs",
&ucon64_wf[WF_OBJ_DC_DEFAULT]
},
{
"unscr", 0, 0, UCON64_UNSCR,
NULL, "unscramble 1ST_READ.BIN for non-selfboot CDs",
&ucon64_wf[WF_OBJ_DC_DEFAULT]
},
#if 0
{
"ip", 1, 0, UCON64_IP,
"FILE", "extract ip.bin FILE from IMAGE; " OPTION_LONG_S "rom=IMAGE",
NULL
},
#endif
{
"mkip", 0, 0, UCON64_MKIP,
NULL, "generate IP.BIN file with default values",
&ucon64_wf[WF_OBJ_DC_NO_ROM]
},
{
"parse", 1, 0, UCON64_PARSE,
"TEMPLATE", "parse TEMPLATE file into a IP.BIN;\n"
"creates an empty template when TEMPLATE does not exist",
&ucon64_wf[WF_OBJ_DC_NO_ROM]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
static int
calc_crc (const unsigned char *buf, int size)
{
int i, c, n = 0xffff;
for (i = 0; i < size; i++)
{
n ^= (buf[i] << 8);
for (c = 0; c < 8; c++)
if (n & 0x8000)
n = (n << 1) ^ 4129;
else
n = (n << 1);
}
return n & 0xffff;
}
static void
update_crc (char *ip)
{
int n = calc_crc ((unsigned char *) (ip + 0x40), 16);
char buf[5];
sprintf (buf, "%04X", n);
if (memcmp (buf, ip + 0x20, 4))
{
printf ("Setting CRC to %s (was %.4s)\n", buf, ip + 0x20);
memcpy (ip + 0x20, buf, 4);
}
}
static unsigned int seed;
static void
dc_srand (unsigned int n)
{
seed = n & 0xffff;
}
static unsigned int
dc_rand ()
{
seed = (seed * 2109 + 9273) & 0x7fff;
return (seed + 0xc000) & 0xffff;
}
#if 0
// header for SAV -> VMS conversion
static const uint8_t nstrsave_bin[1024] = {
0x4e, 0x45, 0x53, 0x52, 0x4f, 0x4d, 0x2e, 0x4e, // 0x8 (8)
0x45, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 (16)
0x4e, 0x65, 0x73, 0x74, 0x65, 0x72, 0x44, 0x43, // 0x18 (24)
0x20, 0x53, 0x61, 0x76, 0x65, 0x52, 0x61, 0x6d, // 0x20 (32)
0x20, 0x46, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, // 0x28 (40)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 (48)
0x2a, 0x2a, 0x2a, 0x4e, 0x65, 0x73, 0x74, 0x65, // 0x38 (56)
0x72, 0x44, 0x43, 0x2a, 0x2a, 0x2a, 0x00, 0x00, // 0x40 (64)
0x01, 0x00, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, // 0x48 (72)
0x80, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 (80)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 (88)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 (96)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 (104)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 (112)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 (120)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 (128)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 (136)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 (144)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 (152)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa0 (160)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xa8 (168)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb0 (176)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xb8 (184)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc0 (192)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xc8 (200)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd0 (208)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xd8 (216)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe0 (224)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xe8 (232)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf0 (240)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xf8 (248)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x100 (256)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x108 (264)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x110 (272)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x118 (280)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x120 (288)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x128 (296)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x130 (304)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x138 (312)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x140 (320)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x148 (328)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x150 (336)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x158 (344)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x160 (352)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x168 (360)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x170 (368)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x178 (376)
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x180 (384)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x188 (392)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x190 (400)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x198 (408)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a0 (416)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1a8 (424)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b0 (432)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1b8 (440)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c0 (448)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1c8 (456)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d0 (464)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1d8 (472)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e0 (480)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1e8 (488)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f0 (496)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x1f8 (504)
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, // 0x200 (512)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x208 (520)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x210 (528)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x218 (536)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x220 (544)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x228 (552)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x230 (560)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x238 (568)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x240 (576)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x248 (584)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x250 (592)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x258 (600)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x260 (608)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x268 (616)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x270 (624)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x278 (632)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, // 0x280 (640)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x288 (648)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x290 (656)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x298 (664)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a0 (672)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2a8 (680)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b0 (688)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2b8 (696)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c0 (704)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2c8 (712)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d0 (720)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2d8 (728)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e0 (736)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2e8 (744)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f0 (752)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x2f8 (760)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x300 (768)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x308 (776)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x310 (784)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x318 (792)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x320 (800)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x328 (808)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x330 (816)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x338 (824)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x340 (832)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x348 (840)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x350 (848)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x358 (856)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x360 (864)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x368 (872)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x370 (880)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x378 (888)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x380 (896)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x388 (904)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x390 (912)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x398 (920)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a0 (928)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3a8 (936)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b0 (944)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3b8 (952)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c0 (960)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3c8 (968)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d0 (976)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3d8 (984)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e0 (992)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3e8 (1000)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f0 (1008)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x3f8 (1016)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 0x400 (1024)
};
#endif
int
dc_init (st_rominfo_t *rominfo)
{
int result = -1;
rominfo->console_usage = dc_usage[0].help;
return result;
}
static int
check_areasym (char *ptr, int len)
{
int i, a = 0;
for (i = 0; i < len; i++)
switch (ptr[i])
{
case 'J':
a |= (1<<0);
break;
case 'U':
a |= (1<<1);
break;
case 'E':
a |= (1<<2);
break;
case ' ':
break;
default:
fprintf (stderr, "ERROR: Unknown area symbol '%c'\n", ptr[i]);
return -1;
}
for (i = 0; i < len; i++)
if ((a & (1<<i)) == 0)
ptr[i] = ' ';
else
ptr[i] = "JUE"[i];
return 0;
}
typedef struct
{
char *name;
int pos;
int len;
int (*extra_check) (char *, int);
char *def;
char *comment;
} st_templ_t;
st_templ_t templ[] =
{
{"hardware_id", 0x0, 0x10, NULL, "SEGA SEGAKATANA", "Hardware ID (always \"SEGA SEGAKATANA\")"},
{"maker_id", 0x10, 0x10, NULL, "SEGA ENTERPRISES", "Maker ID (always \"SEGA ENTERPRISES\")"},
{"device_info", 0x20, 0x10, NULL, "0000 CD-ROM1/1", "Device Information"},
{"area_symbols", 0x30, 0x8, check_areasym, "JUE", "Area Symbols"},
{"peripherals", 0x38, 0x8, NULL, "E000F10", "Peripherals"},
{"product_no", 0x40, 0xa, NULL, "T0000", "Product number (\"HDR-nnnn\" etc.)"},
{"version", 0x4a, 0x6, NULL, "V1.000", "Product version"},
{"release_date", 0x50, 0x10, NULL, "20000627", "Release date (YYYYMMDD)"},
{"boot_filename", 0x60, 0x10, NULL, "1ST_READ.BIN", "Boot filename (usually \"1ST_READ.BIN\")"},
{"sw_maker_name", 0x70, 0x10, NULL, "YOUR NAME HERE", "Name of the company that produced the disc"},
{"game_title", 0x80, 0x80, NULL, "TITLE OF THE SOFTWARE", "Name of the software"},
{NULL, 0, 0, NULL, NULL, NULL}
};
static int
parse_templ (const char *templ_file, char *ip)
{
int filled_in[MAXBUFSIZE];
static char buf[MAXBUFSIZE];
int i;
memset (filled_in, 0, sizeof (filled_in));
for (i = 0; templ[i].name; i++)
{
char *p = buf;
get_property (templ_file, templ[i].name, p, templ[i].def);
strtriml (strtrimr (p));
if (!(*p))
continue;
memset (ip + templ[i].pos, ' ', templ[i].len);
if ((int) strlen (p) > templ[i].len)
{
fprintf (stderr, "ERROR: Data for field \"%s\" is too long... stripping to %d chars\n",
templ[i].name, templ[i].len);
p[templ[i].len] = 0;
}
memcpy (ip + templ[i].pos, p, strlen (p));
if (templ[i].extra_check)
if (templ[i].extra_check (ip + templ[i].pos, templ[i].len) == -1)
return -1;
filled_in[i] = 1;
}
for (i = 0; templ[i].name; i++)
if (!filled_in[i])
{
fprintf (stderr, "ERROR: Missing value for \"%s\"\n", templ[i].name);
return -1;
}
return 0;
}
int
dc_parse (const char *templ_file)
{
char ip[0x8000], dest_name[FILENAME_MAX];
if (access (templ_file, F_OK) == -1)
{
int i = 0;
printf ("Creating empty template file: \"%s\"\n", templ_file);
for (i = 0; templ[i].name; i++)
set_property (templ_file, templ[i].name, templ[i].def, templ[i].comment);
printf (ucon64_msg[WROTE], templ_file);
}
if (parse_templ (templ_file, ip) == -1)
return -1;
update_crc (ip);
strcpy (dest_name, "ip.bin");
ucon64_file_handler (dest_name, NULL, 0);
ucon64_fwrite (ip, 0, 0x8000, dest_name, "wb");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
dc_mkip (void)
{
dc_parse ("default");
return 0;
}
static int
load_chunk (FILE * fh, unsigned char *ptr, int32_t sz)
{
#define MAXCHUNK (2048*1024)
static int idx[MAXCHUNK / 32];
int32_t i;
/* Convert chunk size to number of slices */
sz /= 32;
/* Initialize index table with unity,
so that each slice gets loaded exactly once */
for (i = 0; i < sz; i++)
idx[i] = i;
for (i = sz - 1; i >= 0; --i)
{
/* Select a replacement index */
int x = (dc_rand () * i) >> 16;
/* Swap */
int tmp = idx[i];
idx[i] = idx[x];
idx[x] = tmp;
/* Load resulting slice */
if (fread (ptr + 32 * idx[i], 1, 32, fh) != 32)
return -1;
}
return 0;
}
static int
load_file (FILE * fh, unsigned char *ptr, uint32_t filesz)
{
uint32_t chunksz;
dc_srand (filesz);
/* Descramble 2 meg blocks for as long as possible, then
gradually reduce the window down to 32 bytes (1 slice) */
for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1)
while (filesz >= chunksz)
{
load_chunk (fh, ptr, chunksz);
filesz -= chunksz;
ptr += chunksz;
}
/* Load final incomplete slice */
if (filesz)
if (fread (ptr, 1, filesz, fh) != filesz)
return -1;
return 0;
}
static int
save_chunk (FILE * fh, unsigned char *ptr, int32_t sz)
{
static int idx[MAXCHUNK / 32];
int32_t i;
/* Convert chunk size to number of slices */
sz /= 32;
/* Initialize index table with unity,
so that each slice gets saved exactly once */
for (i = 0; i < sz; i++)
idx[i] = i;
for (i = sz - 1; i >= 0; --i)
{
/* Select a replacement index */
int x = (dc_rand () * i) >> 16;
/* Swap */
int tmp = idx[i];
idx[i] = idx[x];
idx[x] = tmp;
/* Save resulting slice */
if (fwrite (ptr + 32 * idx[i], 1, 32, fh) != 32)
return -1;
}
return 0;
}
static int
save_file (FILE * fh, unsigned char *ptr, uint32_t filesz)
{
uint32_t chunksz;
dc_srand (filesz);
/* Descramble 2 meg blocks for as long as possible, then
gradually reduce the window down to 32 bytes (1 slice) */
for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1)
while (filesz >= chunksz)
{
save_chunk (fh, ptr, chunksz);
filesz -= chunksz;
ptr += chunksz;
}
/* Save final incomplete slice */
if (filesz)
if (fwrite (ptr, 1, filesz, fh) != filesz)
return -1;
return 0;
}
static int
descramble (const char *src, char *dst)
{
unsigned char *ptr = NULL;
uint32_t sz = 0;
FILE *fh;
if (!(fh = fopen (src, "rb")))
return -1;
sz = fsizeof (src);
if (!(ptr = (unsigned char *) malloc (sz)))
return -1;
load_file (fh, ptr, sz);
fclose (fh);
if (!(fh = fopen (dst, "wb")))
return -1;
if (fwrite (ptr, 1, sz, fh) != sz)
return -1;
fclose (fh);
free (ptr);
return 0;
}
static int
scramble (const char *src, char *dst)
{
unsigned char *ptr = NULL;
uint32_t sz = 0;
FILE *fh;
if (!(fh = fopen (src, "rb")))
return -1;
sz = fsizeof (src);
if (!(ptr = (unsigned char *) malloc (sz)))
return -1;
if (fread (ptr, 1, sz, fh) != sz)
return -1;
fclose (fh);
if (!(fh == fopen (dst, "wb")))
return -1;
save_file (fh, ptr, sz);
fclose (fh);
free (ptr);
return 0;
}
int
dc_scramble (void)
{
char dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
if (!scramble (ucon64.rom, dest_name))
printf (ucon64_msg[WROTE], dest_name);
else
fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name);
return 0;
}
int
dc_unscramble (void)
{
char dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
if (!descramble (ucon64.rom, dest_name))
printf (ucon64_msg[WROTE], dest_name);
else
fprintf (stderr, ucon64_msg[WRITE_ERROR], dest_name);
return 0;
}

View File

@@ -0,0 +1,29 @@
/*
dc.h - Dreamcast support for uCON64
Copyright (c) 2004 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef DC_H
#define DC_H
extern int dc_init (st_rominfo_t *rominfo);
extern const st_getopt2_t dc_usage[];
extern int dc_parse (const char *template_file);
extern int dc_mkip (void);
extern int dc_scramble (void);
extern int dc_unscramble (void);
#endif

View File

@@ -0,0 +1,703 @@
/*
gb.c - Game Boy support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2001 - 2004 dbjh
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include "misc/file.h"
#include "misc/misc.h"
#include "misc/string.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "console/nes.h"
#include "backup/gbx.h"
#include "backup/mgd.h"
#include "backup/ssc.h"
#include "patch/ips.h"
#include "patch/bsl.h"
#include "gb.h"
#define GAMEBOY_HEADER_START 0x100
#define GAMEBOY_HEADER_LEN (sizeof (st_gameboy_header_t))
#define GB_NAME_LEN 15
const st_getopt2_t gameboy_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Game Boy/(Super GB)/GB Pocket/Color GB/(GB Advance)"
/*"1989/1994/1996/1998/2001 Nintendo http://www.nintendo.com"*/,
NULL
},
{
"gb", 0, 0, UCON64_GB,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_GB_SWITCH]
},
{
"n", 1, 0, UCON64_N,
"NEW_NAME", "change internal ROM name to NEW_NAME",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"logo", 0, 0, UCON64_LOGO,
NULL, "restore ROM logo character data (offset: 0x104-0x134)",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"mgd", 0, 0, UCON64_MGD,
NULL, "convert to Multi Game*/MGD2/RAW",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"ssc", 0, 0, UCON64_SSC,
NULL, "convert to Super Smart Card/SSC",
&ucon64_wf[WF_OBJ_GB_DEFAULT]
},
{
"sgb", 0, 0, UCON64_SGB,
NULL, "convert from GB Xchanger/GB/GBC to Super Backup Card/GX/GBX",
&ucon64_wf[WF_OBJ_GB_DEFAULT]
},
{
"gbx", 0, 0, UCON64_GBX,
NULL, "convert from Super Backup Card/GX/GBX to GB Xchanger/GB/GBC",
&ucon64_wf[WF_OBJ_GB_DEFAULT]
},
{
"n2gb", 1, 0, UCON64_N2GB,
"NESROM", "KAMI's FC EMUlator (NES emulator);\n"
"ROM should be KAMI's FC Emulator ROM image\n"
"NESROM should contain 16 kB of PRG data and 8 kB of CHR data",
&ucon64_wf[WF_OBJ_GB_DEFAULT]
},
{
"chk", 0, 0, UCON64_CHK,
NULL, "fix ROM checksum",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
/*
0148 ROM size:
0 - 256kBit = 32kB = 2 banks
1 - 512kBit = 64kB = 4 banks
2 - 1Mb = 128kB = 8 banks
3 - 2Mb = 256kB = 16 banks
4 - 4Mb = 512kB = 32 banks
0149 RAM size:
0 - None
1 - 16kBit = 2kB = 1 bank
2 - 64kBit = 8kB = 1 bank
3 - 256kBit = 32kB = 4 banks
*/
typedef struct st_gameboy_header
{
unsigned char opcode1; // 0x00 usually 0x00, NOP
unsigned char opcode2; // 0x01 usually 0xc3, JP
unsigned char start_low; // 0x02 first byte of parameter of JP
unsigned char start_high; // 0x03 second byte
unsigned char logo[GB_LOGODATA_LEN]; // 0x04
unsigned char name[GB_NAME_LEN]; // 0x34
unsigned char gb_type; // 0x43
unsigned char maker_high; // 0x44
unsigned char maker_low; // 0x45
unsigned char pad;
unsigned char rom_type; // 0x47
unsigned char rom_size; // 0x48
unsigned char sram_size; // 0x49
unsigned char country; // 0x4a
unsigned char maker; // 0x4b
unsigned char version; // 0x4c
unsigned char header_checksum; // 0x4d
unsigned char checksum_high; // 0x4e
unsigned char checksum_low; // 0x4f
} st_gameboy_header_t;
static st_gameboy_header_t gameboy_header;
const unsigned char gb_logodata[] = // Note: not a static variable
{
0xce, 0xed, 0x66, 0x66, 0xcc, 0x0d, 0x00, 0x0b,
0x03, 0x73, 0x00, 0x83, 0x00, 0x0c, 0x00, 0x0d,
0x00, 0x08, 0x11, 0x1f, 0x88, 0x89, 0x00, 0x0e,
0xdc, 0xcc, 0x6e, 0xe6, 0xdd, 0xdd, 0xd9, 0x99,
0xbb, 0xbb, 0x67, 0x63, 0x6e, 0x0e, 0xec, 0xcc,
0xdd, 0xdc, 0x99, 0x9f, 0xbb, 0xb9, 0x33, 0x3e
},
rocket_logodata[] = // idem
{
0x11, 0x23, 0xf1, 0x1e, 0x01, 0x22, 0xf0, 0x00,
0x08, 0x99, 0x78, 0x00, 0x08, 0x11, 0x9a, 0x48,
0x11, 0x23, 0xf0, 0x0e, 0x70, 0x01, 0xf8, 0x80,
0x22, 0x44, 0x44, 0x22, 0x22, 0x21, 0x00, 0x1e,
0x99, 0x10, 0x00, 0x1e, 0x19, 0x22, 0x44, 0x22,
0x22, 0x47, 0x00, 0x0e, 0x11, 0x22, 0x00, 0x00
};
typedef struct st_gameboy_chksum
{
unsigned short value;
unsigned char header;
} st_gameboy_chksum_t;
static st_gameboy_chksum_t checksum;
static st_gameboy_chksum_t gameboy_chksum (st_rominfo_t *rominfo);
int
gameboy_logo (st_rominfo_t *rominfo)
{
char dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite ((unsigned char *)
((gameboy_header.rom_type >= 0x97 && gameboy_header.rom_type <= 0x99) ?
rocket_logodata : gb_logodata),
rominfo->buheader_len + GAMEBOY_HEADER_START + 4, GB_LOGODATA_LEN,
dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gameboy_n2gb (st_rominfo_t *rominfo, const char *nesrom)
{
#define EMULATOR_LEN 0x10000
st_ines_header_t ines_header;
int n = 0, crc = 0;
unsigned char *buf;
char dest_name[FILENAME_MAX];
if (ucon64.file_size - rominfo->buheader_len != EMULATOR_LEN)
{
fprintf (stderr, "ERROR: %s does not appear to be KAMI's FC emulator\n", ucon64.rom);
return -1;
}
ucon64_fread (&ines_header, 0, INES_HEADER_LEN, nesrom);
if (memcmp (ines_header.signature, INES_SIG_S, 4))
{
fprintf (stderr, "ERROR: Only NES ROMs with iNES header are supported\n");
return -1;
}
if (ines_header.prg_size != 1 || ines_header.chr_size != 1)
{
fprintf (stderr,
"ERROR: Only NES ROMs with 0.1250 Mb of ROM (PRG) and 0.0625 Mb of VROM (CHR)\n"
" are supported by KAMI's FC emulator\n");
return -1;
}
if (!(buf = (unsigned char *) malloc (ucon64.file_size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], ucon64.file_size);
return -1;
}
ucon64_fread (buf, 0, ucon64.file_size, ucon64.rom);
ucon64_fread (rominfo->buheader_len + buf + 0x4000, INES_HEADER_LEN,
0x4000 + 0x2000, nesrom); // read PRG & CHR data
for (n = 0; n < ucon64.file_size - rominfo->buheader_len; n++)
{
if ((n == GAMEBOY_HEADER_START + 0x4e) || (n == GAMEBOY_HEADER_START + 0x4f))
continue;
else
crc += buf[rominfo->buheader_len + n];
}
buf[rominfo->buheader_len + GAMEBOY_HEADER_START + 0x4e] = crc >> 8;
buf[rominfo->buheader_len + GAMEBOY_HEADER_START + 0x4f] = crc;
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
ucon64_fwrite (buf, 0, ucon64.file_size, dest_name, "wb");
free (buf);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
static int
gameboy_convert_data (st_rominfo_t *rominfo, unsigned char *conversion_table,
const char *suffix)
{
char dest_name[FILENAME_MAX], src_name[FILENAME_MAX];
unsigned char buf[MAXBUFSIZE];
int x, n, n_bytes;
strcpy (src_name, ucon64.rom);
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, suffix);
ucon64_file_handler (dest_name, src_name, 0);
x = rominfo->buheader_len;
while ((n_bytes = ucon64_fread (buf, x, MAXBUFSIZE, src_name)))
{
for (n = 0; n < n_bytes; n++)
buf[n] = conversion_table[(int) buf[n]];
ucon64_fwrite (buf, x, n_bytes, dest_name, x == rominfo->buheader_len ? "wb" : "ab");
x += n_bytes;
}
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gameboy_gbx (st_rominfo_t *rominfo)
{
unsigned char gbx2gbc[] =
{
0xB4, 0xBC, 0xA4, 0xAC, 0x94, 0x9C, 0x84, 0x8C,
0xF4, 0xFC, 0xE4, 0xEC, 0xD4, 0xDC, 0xC4, 0xCC,
0x34, 0x3C, 0x24, 0x2C, 0x14, 0x1C, 0x04, 0x0C,
0x74, 0x7C, 0x64, 0x6C, 0x54, 0x5C, 0x44, 0x4C,
0xB5, 0xBD, 0xA5, 0xAD, 0x95, 0x9D, 0x85, 0x8D,
0xF5, 0xFD, 0xE5, 0xED, 0xD5, 0xDD, 0xC5, 0xCD,
0x35, 0x3D, 0x25, 0x2D, 0x15, 0x1D, 0x05, 0x0D,
0x75, 0x7D, 0x65, 0x6D, 0x55, 0x5D, 0x45, 0x4D,
0xB6, 0xBE, 0xA6, 0xAE, 0x96, 0x9E, 0x86, 0x8E,
0xF6, 0xFE, 0xE6, 0xEE, 0xD6, 0xDE, 0xC6, 0xCE,
0x36, 0x3E, 0x26, 0x2E, 0x16, 0x1E, 0x06, 0x0E,
0x76, 0x7E, 0x66, 0x6E, 0x56, 0x5E, 0x46, 0x4E,
0xB7, 0xBF, 0xA7, 0xAF, 0x97, 0x9F, 0x87, 0x8F,
0xF7, 0xFF, 0xE7, 0xEF, 0xD7, 0xDF, 0xC7, 0xCF,
0x37, 0x3F, 0x27, 0x2F, 0x17, 0x1F, 0x07, 0x0F,
0x77, 0x7F, 0x67, 0x6F, 0x57, 0x5F, 0x47, 0x4F,
0xB0, 0xB8, 0xA0, 0xA8, 0x90, 0x98, 0x80, 0x88,
0xF0, 0xF8, 0xE0, 0xE8, 0xD0, 0xD8, 0xC0, 0xC8,
0x30, 0x38, 0x20, 0x28, 0x10, 0x18, 0x00, 0x08,
0x70, 0x78, 0x60, 0x68, 0x50, 0x58, 0x40, 0x48,
0xB1, 0xB9, 0xA1, 0xA9, 0x91, 0x99, 0x81, 0x89,
0xF1, 0xF9, 0xE1, 0xE9, 0xD1, 0xD9, 0xC1, 0xC9,
0x31, 0x39, 0x21, 0x29, 0x11, 0x19, 0x01, 0x09,
0x71, 0x79, 0x61, 0x69, 0x51, 0x59, 0x41, 0x49,
0xB2, 0xBA, 0xA2, 0xAA, 0x92, 0x9A, 0x82, 0x8A,
0xF2, 0xFA, 0xE2, 0xEA, 0xD2, 0xDA, 0xC2, 0xCA,
0x32, 0x3A, 0x22, 0x2A, 0x12, 0x1A, 0x02, 0x0A,
0x72, 0x7A, 0x62, 0x6A, 0x52, 0x5A, 0x42, 0x4A,
0xB3, 0xBB, 0xA3, 0xAB, 0x93, 0x9B, 0x83, 0x8B,
0xF3, 0xFB, 0xE3, 0xEB, 0xD3, 0xDB, 0xC3, 0xCB,
0x33, 0x3B, 0x23, 0x2B, 0x13, 0x1B, 0x03, 0x0B,
0x73, 0x7B, 0x63, 0x6B, 0x53, 0x5B, 0x43, 0x4B
};
const char *old_suffix = get_suffix (ucon64.rom), *new_suffix;
new_suffix = stricmp (old_suffix, ".GBX") ? ".GB" : ".GBC";
return gameboy_convert_data (rominfo, gbx2gbc, new_suffix);
}
int
gameboy_sgb (st_rominfo_t *rominfo)
{
unsigned char gbc2gbx[] =
{
0x96, 0xB6, 0xD6, 0xF6, 0x16, 0x36, 0x56, 0x76,
0x97, 0xB7, 0xD7, 0xF7, 0x17, 0x37, 0x57, 0x77,
0x94, 0xB4, 0xD4, 0xF4, 0x14, 0x34, 0x54, 0x74,
0x95, 0xB5, 0xD5, 0xF5, 0x15, 0x35, 0x55, 0x75,
0x92, 0xB2, 0xD2, 0xF2, 0x12, 0x32, 0x52, 0x72,
0x93, 0xB3, 0xD3, 0xF3, 0x13, 0x33, 0x53, 0x73,
0x90, 0xB0, 0xD0, 0xF0, 0x10, 0x30, 0x50, 0x70,
0x91, 0xB1, 0xD1, 0xF1, 0x11, 0x31, 0x51, 0x71,
0x9E, 0xBE, 0xDE, 0xFE, 0x1E, 0x3E, 0x5E, 0x7E,
0x9F, 0xBF, 0xDF, 0xFF, 0x1F, 0x3F, 0x5F, 0x7F,
0x9C, 0xBC, 0xDC, 0xFC, 0x1C, 0x3C, 0x5C, 0x7C,
0x9D, 0xBD, 0xDD, 0xFD, 0x1D, 0x3D, 0x5D, 0x7D,
0x9A, 0xBA, 0xDA, 0xFA, 0x1A, 0x3A, 0x5A, 0x7A,
0x9B, 0xBB, 0xDB, 0xFB, 0x1B, 0x3B, 0x5B, 0x7B,
0x98, 0xB8, 0xD8, 0xF8, 0x18, 0x38, 0x58, 0x78,
0x99, 0xB9, 0xD9, 0xF9, 0x19, 0x39, 0x59, 0x79,
0x86, 0xA6, 0xC6, 0xE6, 0x06, 0x26, 0x46, 0x66,
0x87, 0xA7, 0xC7, 0xE7, 0x07, 0x27, 0x47, 0x67,
0x84, 0xA4, 0xC4, 0xE4, 0x04, 0x24, 0x44, 0x64,
0x85, 0xA5, 0xC5, 0xE5, 0x05, 0x25, 0x45, 0x65,
0x82, 0xA2, 0xC2, 0xE2, 0x02, 0x22, 0x42, 0x62,
0x83, 0xA3, 0xC3, 0xE3, 0x03, 0x23, 0x43, 0x63,
0x80, 0xA0, 0xC0, 0xE0, 0x00, 0x20, 0x40, 0x60,
0x81, 0xA1, 0xC1, 0xE1, 0x01, 0x21, 0x41, 0x61,
0x8E, 0xAE, 0xCE, 0xEE, 0x0E, 0x2E, 0x4E, 0x6E,
0x8F, 0xAF, 0xCF, 0xEF, 0x0F, 0x2F, 0x4F, 0x6F,
0x8C, 0xAC, 0xCC, 0xEC, 0x0C, 0x2C, 0x4C, 0x6C,
0x8D, 0xAD, 0xCD, 0xED, 0x0D, 0x2D, 0x4D, 0x6D,
0x8A, 0xAA, 0xCA, 0xEA, 0x0A, 0x2A, 0x4A, 0x6A,
0x8B, 0xAB, 0xCB, 0xEB, 0x0B, 0x2B, 0x4B, 0x6B,
0x88, 0xA8, 0xC8, 0xE8, 0x08, 0x28, 0x48, 0x68,
0x89, 0xA9, 0xC9, 0xE9, 0x09, 0x29, 0x49, 0x69
};
const char *old_suffix = get_suffix (ucon64.rom), *new_suffix;
new_suffix = stricmp (old_suffix, ".GBC") ? ".GX" : ".GBX";
return gameboy_convert_data (rominfo, gbc2gbx, new_suffix);
}
int
gameboy_n (st_rominfo_t *rominfo, const char *name)
{
char buf[GB_NAME_LEN], dest_name[FILENAME_MAX];
memset (buf, 0, GB_NAME_LEN);
strncpy (buf, name, GB_NAME_LEN);
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (buf, rominfo->buheader_len + GAMEBOY_HEADER_START + 0x34,
GB_NAME_LEN, dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gameboy_chk (st_rominfo_t *rominfo)
{
char buf[4], dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
buf[0] = checksum.header;
buf[1] = rominfo->current_internal_crc >> 8;
buf[2] = rominfo->current_internal_crc;
ucon64_fwrite (buf, rominfo->buheader_len + GAMEBOY_HEADER_START + 0x4d, 3,
dest_name, "r+b");
dumper (stdout, buf, 3, GAMEBOY_HEADER_START + rominfo->buheader_len + 0x4d, DUMPER_HEX);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gameboy_mgd (st_rominfo_t *rominfo)
// TODO: convert the ROM data
{
char src_name[FILENAME_MAX], dest_name[FILENAME_MAX];
int size = ucon64.file_size - rominfo->buheader_len;
strcpy (src_name, ucon64.rom);
mgd_make_name (ucon64.rom, UCON64_GB, size, dest_name);
ucon64_file_handler (dest_name, src_name, OF_FORCE_BASENAME);
fcopy (src_name, rominfo->buheader_len, size, dest_name, "wb");
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
mgd_write_index_file ((char *) basename2 (dest_name), 1);
return 0;
}
int
gameboy_ssc (st_rominfo_t *rominfo)
// TODO: convert the ROM data
{
st_unknown_header_t header;
char src_name[FILENAME_MAX], dest_name[FILENAME_MAX];
const char *p = NULL;
int size = ucon64.file_size - rominfo->buheader_len;
memset (&header, 0, UNKNOWN_HEADER_LEN);
header.size_low = size / 8192;
header.size_high = size / 8192 >> 8;
header.id1 = 0xaa;
header.id2 = 0xbb;
#if 0 // TODO: find out correct value. 2 is used for Magic Super Griffin
header.type = 2;
#endif
strcpy (src_name, ucon64.rom);
p = basename2 (ucon64.rom);
// TODO: find out if this is correct (giving the file name a prefix)
if ((p[0] == 'G' || p[0] == 'g') && (p[1] == 'B' || p[1] == 'b'))
strcpy (dest_name, p);
else
sprintf (dest_name, "gb%s", p);
set_suffix (dest_name, ".gb");
ucon64_file_handler (dest_name, src_name, 0);
ucon64_fwrite (&header, 0, UNKNOWN_HEADER_LEN, dest_name, "wb");
fcopy (src_name, rominfo->buheader_len, size, dest_name, "ab");
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
return 0;
}
int
gameboy_init (st_rominfo_t *rominfo)
{
int result = -1, value, x;
char buf[MAXBUFSIZE];
static const char *gameboy_romtype1[0x20] =
{
"ROM only",
"ROM + MBC1",
"ROM + MBC1 + RAM",
"ROM + MBC1 + RAM + Battery",
NULL,
"ROM + MBC2",
"ROM + MBC2 + Battery",
NULL,
"ROM + RAM", // correct? - dbjh
"ROM + RAM + Battery", // correct? - dbjh
NULL,
"ROM + MMM01",
"ROM + MMM01 + SRAM",
"ROM + MMM01 + SRAM + Battery",
NULL,
"ROM + MBC3 + Battery + Timer",
"ROM + MBC3 + RAM + Battery + Timer",
"ROM + MBC3",
"ROM + MBC3 + RAM",
"ROM + MBC3 + RAM + Battery",
NULL,
NULL,
NULL,
NULL,
NULL,
"ROM + MBC5",
"ROM + MBC5 + RAM",
"ROM + MBC5 + RAM + Battery",
"ROM + MBC5 + Rumble",
"ROM + MBC5 + SRAM + Rumble",
"ROM + MBC5 + SRAM + Battery + Rumble",
"Nintendo Pocket Camera"
},
*gameboy_romtype2[3] =
{
"Rocket Games",
NULL,
"Rocket Games 2-in-1"
},
*gameboy_romtype3[3] =
{
"Bandai TAMA5",
"Hudson HuC-3",
"Hudson HuC-1"
},
*str;
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ? ucon64.buheader_len : 0;
ucon64_fread (&gameboy_header, rominfo->buheader_len + GAMEBOY_HEADER_START,
GAMEBOY_HEADER_LEN, ucon64.rom);
if (gameboy_header.opcode1 == 0x00 && gameboy_header.opcode2 == 0xc3)
result = 0;
else
{
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : (int) SSC_HEADER_LEN;
ucon64_fread (&gameboy_header, rominfo->buheader_len + GAMEBOY_HEADER_START,
GAMEBOY_HEADER_LEN, ucon64.rom);
if (gameboy_header.opcode1 == 0x00 && gameboy_header.opcode2 == 0xc3)
result = 0;
else
result = -1;
}
if (ucon64.console == UCON64_GB)
result = 0;
rominfo->header_start = GAMEBOY_HEADER_START;
rominfo->header_len = GAMEBOY_HEADER_LEN;
rominfo->header = &gameboy_header;
// internal ROM name
strncpy (rominfo->name, (const char *) gameboy_header.name, GB_NAME_LEN);
rominfo->name[GB_NAME_LEN] = 0; // terminate string
// ROM maker
if (gameboy_header.maker == 0x33)
{
int ih = gameboy_header.maker_high <= '9' ?
gameboy_header.maker_high - '0' : gameboy_header.maker_high - 'A' + 10,
il = gameboy_header.maker_low <= '9' ?
gameboy_header.maker_low - '0' : gameboy_header.maker_low - 'A' + 10;
x = ih * 36 + il;
}
else
x = (gameboy_header.maker >> 4) * 36 + (gameboy_header.maker & 0x0f);
/*
I added the first if statement, because I didn't want to expand
nintendo_maker by a large amount for only one publisher and because index 0
is used when the publisher code is unknown (so it shouldn't be set to
"Rocket Games"). - dbjh
*/
if (x == 33 * 36 + 33 || x == 0) // publisher code XX/00
x = 2; // Rocket Games
else if (x < 0 || x >= NINTENDO_MAKER_LEN)
x = 0;
rominfo->maker = NULL_TO_UNKNOWN_S (nintendo_maker[x]);
// ROM country
rominfo->country = gameboy_header.country == 0 ? "Japan" : "U.S.A. & Europe";
// misc stuff
// Don't move division by 4 to shift parameter (gameboy_header.rom_size can be < 2)
sprintf (buf, "Internal size: %.4f Mb\n", (1 << gameboy_header.rom_size) / 4.0f);
strcat (rominfo->misc, buf);
if (gameboy_header.rom_type <= 0x1f)
str = NULL_TO_UNKNOWN_S (gameboy_romtype1[gameboy_header.rom_type]);
else if (gameboy_header.rom_type >= 0x97 && gameboy_header.rom_type <= 0x99)
str = gameboy_romtype2[gameboy_header.rom_type - 0x97];
else if (gameboy_header.rom_type >= 0xfd)
str = gameboy_romtype3[gameboy_header.rom_type - 0xfd];
else
str = "Unknown";
sprintf (buf, "ROM type: %s\n", str);
strcat (rominfo->misc, buf);
if (!gameboy_header.sram_size)
sprintf (buf, "Save RAM: No\n");
else
{
value = (gameboy_header.sram_size & 7) << 1; // 0/1/2/4/5
if (value)
value = 1 << (value - 1);
sprintf (buf, "Save RAM: Yes, %d kBytes\n", value);
}
strcat (rominfo->misc, buf);
sprintf (buf, "Version: 1.%d\n", gameboy_header.version);
strcat (rominfo->misc, buf);
sprintf (buf, "Game Boy type: %s\n",
(gameboy_header.gb_type == 0x80) ? "Color" :
// (OFFSET (gameboy_header, 0x46) == 0x03) ? "Super" :
"Standard (4 colors)");
strcat (rominfo->misc, buf);
value = gameboy_header.start_high << 8;
value += gameboy_header.start_low;
sprintf (buf, "Start address: 0x%04x\n", value);
strcat (rominfo->misc, buf);
strcat (rominfo->misc, "Logo data: ");
if (memcmp (gameboy_header.logo,
(gameboy_header.rom_type >= 0x97 && gameboy_header.rom_type <= 0x99) ?
rocket_logodata : gb_logodata,
GB_LOGODATA_LEN) == 0)
{
#ifdef USE_ANSI_COLOR
if (ucon64.ansi_color)
strcat (rominfo->misc, "\x1b[01;32mOk\x1b[0m");
else
#endif
strcat (rominfo->misc, "Ok");
}
else
{
#ifdef USE_ANSI_COLOR
if (ucon64.ansi_color)
strcat (rominfo->misc, "\x1b[01;31mBad\x1b[0m");
else
#endif
strcat (rominfo->misc, "Bad");
}
if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0)
{
rominfo->has_internal_crc = 1;
rominfo->internal_crc_len = 2;
checksum = gameboy_chksum (rominfo);
rominfo->current_internal_crc = checksum.value;
rominfo->internal_crc = (gameboy_header.checksum_high << 8) +
gameboy_header.checksum_low;
x = gameboy_header.header_checksum;
sprintf (rominfo->internal_crc2,
"Header checksum: %s, 0x%02x (calculated) %c= 0x%02x (internal)",
#ifdef USE_ANSI_COLOR
ucon64.ansi_color ?
((checksum.header == x) ?
"\x1b[01;32mOk\x1b[0m" : "\x1b[01;31mBad\x1b[0m")
:
((checksum.header == x) ? "Ok" : "Bad"),
#else
(checksum.header == x) ? "Ok" : "Bad",
#endif
checksum.header, (checksum.header == x) ? '=' : '!', x);
}
rominfo->console_usage = gameboy_usage[0].help;
rominfo->copier_usage = (!rominfo->buheader_len ? mgd_usage[0].help : ssc_usage[0].help);
return result;
}
st_gameboy_chksum_t
gameboy_chksum (st_rominfo_t *rominfo)
{
st_gameboy_chksum_t sum = { 0, 0 };
unsigned char *rom_buffer;
int size = ucon64.file_size - rominfo->buheader_len, i;
if (!(rom_buffer = (unsigned char *) malloc (size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size);
return sum;
}
ucon64_fread (rom_buffer, rominfo->buheader_len, size, ucon64.rom);
for (i = GAMEBOY_HEADER_START + 0x34; i < GAMEBOY_HEADER_START + 0x4d; i++)
sum.header += ~rom_buffer[i];
for (i = 0; i < size; i++)
sum.value += rom_buffer[i];
sum.value -= (rom_buffer[GAMEBOY_HEADER_START + 0x4d] - sum.header) +
rom_buffer[GAMEBOY_HEADER_START + 0x4e] +
rom_buffer[GAMEBOY_HEADER_START + 0x4f];
free (rom_buffer);
return sum;
}

View File

@@ -0,0 +1,39 @@
/*
gb.h - Game Boy support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef GB_H
#define GB_H
#define GB_LOGODATA_LEN 48
extern const st_getopt2_t gameboy_usage[];
extern const unsigned char gb_logodata[], rocket_logodata[];
extern int gameboy_chk (st_rominfo_t *rominfo);
extern int gameboy_gbx (st_rominfo_t *rominfo);
extern int gameboy_mgd (st_rominfo_t *rominfo);
extern int gameboy_n (st_rominfo_t *rominfo, const char *name);
extern int gameboy_n2gb (st_rominfo_t *rominfo, const char *emu_rom);
extern int gameboy_sgb (st_rominfo_t *rominfo);
extern int gameboy_ssc (st_rominfo_t *rominfo);
extern int gameboy_init (st_rominfo_t *rominfo);
extern int gameboy_logo (st_rominfo_t *rominfo);
#endif

View File

@@ -0,0 +1,850 @@
/*
gba.c - Game Boy Advance support for uCON64
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2001 - 2004 dbjh
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/stat.h>
#include "misc/file.h"
#include "misc/misc.h"
#include "misc/property.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "misc/string.h"
#include "ucon64.h"
#include "ucon64_misc.h"
#include "gba.h"
#include "backup/fal.h"
#define GBA_NAME_LEN 12
#define GBA_HEADER_START 0
#define GBA_HEADER_LEN (sizeof (st_gba_header_t))
static int gba_chksum (void);
const st_getopt2_t gba_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Game Boy Advance"/*"2001 Nintendo http://www.nintendo.com"*/,
NULL
},
{
"gba", 0, 0, UCON64_GBA,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_GBA_SWITCH]
},
{
"n", 1, 0, UCON64_N,
"NEW_NAME", "change internal ROM name to NEW_NAME",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"logo", 0, 0, UCON64_LOGO,
NULL, "restore ROM logo character data (offset: 0x04-0x9F)",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"chk", 0, 0, UCON64_CHK,
NULL, "fix ROM header checksum",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"sram", 0, 0, UCON64_SRAM,
NULL, "patch ROM for SRAM saving",
&ucon64_wf[WF_OBJ_GBA_DEFAULT]
},
{
"crp", 1, 0, UCON64_CRP,
"WAIT_TIME", "slow down ROM access (\"crash patch\");\n"
"WAIT_TIME=0 default in most crash patches\n"
"WAIT_TIME=4 faster than 0, slower than 8\n"
"WAIT_TIME=8 faster than 4, slower than 28\n"
"WAIT_TIME=12 slowest cartridge access speed\n"
"WAIT_TIME=16 faster than 28, but slower than 20\n"
"WAIT_TIME=20 default in most original cartridges\n"
"WAIT_TIME=24 fastest cartridge access speed\n"
"WAIT_TIME=28 faster than 8 but slower than 16",
&ucon64_wf[WF_OBJ_GBA_DEFAULT]
},
// "n 0 and 28, with a stepping of 4. I.e. 0, 4, 8, 12 ...\n"
{
"multi", 1, 0, UCON64_MULTI,
"SIZE", "make multi-game file for use with FAL/F2A flash card, truncated\n"
"to SIZE Mbit; file with loader must be specified first, then\n"
"all the ROMs, multi-game file to create last",
&ucon64_wf[WF_OBJ_ALL_INIT_PROBE_STOP]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
/*
Offset 00h-03h - Start Address - A 32 bit ARM B command with jump destination
to the start address of the program, cannot be manipulated
with this tool, there's no reason.
Offset 04h-9fh - Nintendo logo character data - The fix Nintendo logo graphics
needed to start a ROM on the real machine as it is verified
by it.
Offset a0h-abh - Game title - The game title is an ASCII string, officially
can use only ASCII characters between the ASCII code 20h and
60h. Although it is not a strict rule for hobby programmers,
it is fun to follow such a rules in my opinion. As I know
developers can choose their own game title here describing
the product in short.
Offset ach-afh - Game code - The 4 bytes long code of the game is an ASCII
string too, officially can use only ASCII characters between
the ASCII code 20h and 60h. The first letter is always A as I
know, probably stands for GBA, so it won't change unless a
higher hardware with backwards compatibility won't be
introduced and this letter could hold some more infos about
it. The second and third letters are the shortened version of
the name of the game. And the fourth letter is the territory
code. Don't afraid, there's no territory lockout, this is for
information purposes only. So far as I know J stands for
Japan and Asia, E stands for USA and the whole American
continent and P stands for Europe, Australia and Africa
(probably came from that these are the PAL video standard
territories, but I could be wrong). Although it is not a
strict rule for hobby programmers, it is fun to follow such a
rules in my opinion. Developers get this 4 letter code right
from Nintendo and they have to use that.
Offset b0h-b1h - Maker code - The 2 bytes long code of the developer company
is an ASCII string too, officially can use only ASCII
characters between the ASCII code 20h and 60h. Although it is
not a strict rule for hobby programmers, it is fun to follow
such a rules in my opinion. Developers get this 2 letter code
right from Nintendo and they have to use that.
Offset b2h-b2h - 96h - Fixed 96h byte without any useful information.
Offset b3h-b3h - Main unit code - This hexadecimal byte is the destination
hardware code. It is always 00h at the moment as it stands
for Game Boy Advance, so it won't change in the future either
unless a higher hardware with backwards compatibility won't
be introduced and this byte could hold some more infos about
it. There's no reason to change this or write something
different than 00h into it.
Offset b4h-b4h - Device type - This hexadecimal byte is the device type code.
It is always 00h as the only other possible value stands for
a debugger cart what I assume won't be available on the
streets and I assume even if a developer works with such a
hardware, he or she doesn't have to change this byte, however
he or she easily can of course. So there's no reason to
change this or write something different than 00h into it.
Offset b5h-bbh - Reserved area - Fixed, 00h filled area without any useful
information.
Offset bch-bch - Mask ROM version number - This hexadecimal byte holds the
version number of the ROM. As I know it works somehow that
way, the first published (and released on the streets) is
always the first version and for that 00h is stored here. In
the case it is getting updated, so in the same territory the
very same game with the very same title is getting replaced
with a new version, what is happening rarely, the number here
is getting increased by one. So usually this byte holds 00h
and there isn't too much reason to write something here and
something else than 00h.
Offset bdh-bdh - Complement check - This hexadecimal byte have to be
calculated automatically, when the whole header is in its
final state, so nothing will change inside of it. (Manually
it would be hard to calculate.) Add the bytes between offset
a0h and bch together, take the number's two's complement and
add 19h to the result. Store the lowest 8 bits here. Or
calculate automatically with GBARM. The hardware is
verifying this byte just like the Nintendo logo character
data and in the case it isn't correct, the game won't start
on the real machine.
Offset beh-bfh - Reserved area - Fixed, 00h filled area without any useful
information.
*/
typedef struct st_gba_header
{
unsigned char start[4]; // 0x00
unsigned char logo[GBA_LOGODATA_LEN]; // 0x04
unsigned char name[GBA_NAME_LEN]; // 0xa0
unsigned char game_id_prefix; // 0xac
unsigned char game_id_low; // 0xad
unsigned char game_id_high; // 0xae
unsigned char game_id_country; // 0xaf
unsigned char maker_high; // 0xb0
unsigned char maker_low; // 0xb1
unsigned char pad1;
unsigned char gba_type; // 0xb3
unsigned char device_type; // 0xb4
unsigned char pad2[7];
unsigned char version; // 0xbc
unsigned char checksum; // 0xbd
unsigned char pad3[2];
} st_gba_header_t;
static st_gba_header_t gba_header;
const unsigned char gba_logodata[] = // Note: not a static variable
{
0x24, 0xff, 0xae, 0x51,
0x69, 0x9a, 0xa2, 0x21, 0x3d, 0x84, 0x82, 0x0a,
0x84, 0xe4, 0x09, 0xad, 0x11, 0x24, 0x8b, 0x98,
0xc0, 0x81, 0x7f, 0x21, 0xa3, 0x52, 0xbe, 0x19,
0x93, 0x09, 0xce, 0x20, 0x10, 0x46, 0x4a, 0x4a,
0xf8, 0x27, 0x31, 0xec, 0x58, 0xc7, 0xe8, 0x33,
0x82, 0xe3, 0xce, 0xbf, 0x85, 0xf4, 0xdf, 0x94,
0xce, 0x4b, 0x09, 0xc1, 0x94, 0x56, 0x8a, 0xc0,
0x13, 0x72, 0xa7, 0xfc, 0x9f, 0x84, 0x4d, 0x73,
0xa3, 0xca, 0x9a, 0x61, 0x58, 0x97, 0xa3, 0x27,
0xfc, 0x03, 0x98, 0x76, 0x23, 0x1d, 0xc7, 0x61,
0x03, 0x04, 0xae, 0x56, 0xbf, 0x38, 0x84, 0x00,
0x40, 0xa7, 0x0e, 0xfd, 0xff, 0x52, 0xfe, 0x03,
0x6f, 0x95, 0x30, 0xf1, 0x97, 0xfb, 0xc0, 0x85,
0x60, 0xd6, 0x80, 0x25, 0xa9, 0x63, 0xbe, 0x03,
0x01, 0x4e, 0x38, 0xe2, 0xf9, 0xa2, 0x34, 0xff,
0xbb, 0x3e, 0x03, 0x44, 0x78, 0x00, 0x90, 0xcb,
0x88, 0x11, 0x3a, 0x94, 0x65, 0xc0, 0x7c, 0x63,
0x87, 0xf0, 0x3c, 0xaf, 0xd6, 0x25, 0xe4, 0x8b,
0x38, 0x0a, 0xac, 0x72, 0x21, 0xd4, 0xf8, 0x07
};
int
gba_n (st_rominfo_t *rominfo, const char *name)
{
char buf[GBA_NAME_LEN], dest_name[FILENAME_MAX];
memset (buf, 0, GBA_NAME_LEN);
strncpy (buf, name, GBA_NAME_LEN);
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (buf, GBA_HEADER_START + rominfo->buheader_len + 0xa0, GBA_NAME_LEN,
dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gba_logo (st_rominfo_t *rominfo)
{
char dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (gba_logodata, GBA_HEADER_START + rominfo->buheader_len + 0x04,
GBA_LOGODATA_LEN, dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gba_chk (st_rominfo_t *rominfo)
{
char buf, dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
buf = rominfo->current_internal_crc;
ucon64_fputc (dest_name, GBA_HEADER_START + rominfo->buheader_len + 0xbd,
buf, "r+b");
dumper (stdout, &buf, 1, GBA_HEADER_START + rominfo->buheader_len + 0xbd, DUMPER_HEX);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gba_sram (void)
// This function is based on Omar Kilani's gbautil 1.1
{
unsigned char st_orig[2][10] =
{
{ 0x0E, 0x48, 0x39, 0x68, 0x01, 0x60, 0x0E, 0x48, 0x79, 0x68 },
{ 0x13, 0x4B, 0x18, 0x60, 0x13, 0x48, 0x01, 0x60, 0x13, 0x49 }
},
st_repl[2][10] =
{
{ 0x00, 0x48, 0x00, 0x47, 0x01, 0xFF, 0xFF, 0x08, 0x79, 0x68 },
{ 0x01, 0x4C, 0x20, 0x47, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x08 }
},
fl_orig[2][24] =
{
{
0xD0, 0x20, 0x00, 0x05, 0x01, 0x88, 0x01, 0x22, 0x08, 0x1C,
0x10, 0x40, 0x02, 0x1C, 0x11, 0x04, 0x08, 0x0C, 0x00, 0x28,
0x01, 0xD0, 0x1B, 0xE0
},
{
0xD0, 0x21, 0x09, 0x05, 0x01, 0x23, 0x0C, 0x4A, 0x08, 0x88,
0x18, 0x40, 0x00, 0x28, 0x08, 0xD1, 0x10, 0x78, 0x00, 0x28,
0xF8, 0xD0, 0x08, 0x88
}
},
fl_repl[2][24] =
{
{
0xE0, 0x20, 0x00, 0x05, 0x01, 0x88, 0x01, 0x22, 0x08, 0x1C,
0x10, 0x40, 0x02, 0x1C, 0x11, 0x04, 0x08, 0x0C, 0x00, 0x28,
0x01, 0xD0, 0x1B, 0xE0
},
{
0xE0, 0x21, 0x09, 0x05, 0x01, 0x23, 0x0C, 0x4A, 0x08, 0x88,
0x18, 0x40, 0x00, 0x28, 0x08, 0xD1, 0x10, 0x78, 0x00, 0x28,
0xF8, 0xD0, 0x08, 0x88
}
},
p_repl[2][188] =
{
{
0x39, 0x68, 0x27, 0x48, 0x81, 0x42, 0x23, 0xD0, 0x89, 0x1C,
0x08, 0x88, 0x01, 0x28, 0x02, 0xD1, 0x24, 0x48, 0x78, 0x60,
0x33, 0xE0, 0x00, 0x23, 0x00, 0x22, 0x89, 0x1C, 0x10, 0xB4,
0x01, 0x24, 0x08, 0x68, 0x20, 0x40, 0x5B, 0x00, 0x03, 0x43,
0x89, 0x1C, 0x52, 0x1C, 0x06, 0x2A, 0xF7, 0xD1, 0x10, 0xBC,
0x39, 0x60, 0xDB, 0x01, 0x02, 0x20, 0x00, 0x02, 0x1B, 0x18,
0x0E, 0x20, 0x00, 0x06, 0x1B, 0x18, 0x7B, 0x60, 0x39, 0x1C,
0x08, 0x31, 0x08, 0x88, 0x09, 0x38, 0x08, 0x80, 0x16, 0xE0,
0x15, 0x49, 0x00, 0x23, 0x00, 0x22, 0x10, 0xB4, 0x01, 0x24,
0x08, 0x68, 0x20, 0x40, 0x5B, 0x00, 0x03, 0x43, 0x89, 0x1C,
0x52, 0x1C, 0x06, 0x2A, 0xF7, 0xD1, 0x10, 0xBC, 0xDB, 0x01,
0x02, 0x20, 0x00, 0x02, 0x1B, 0x18, 0x0E, 0x20, 0x00, 0x06,
0x1B, 0x18, 0x08, 0x3B, 0x3B, 0x60, 0x0B, 0x48, 0x39, 0x68,
0x01, 0x60, 0x0A, 0x48, 0x79, 0x68, 0x01, 0x60, 0x0A, 0x48,
0x39, 0x1C, 0x08, 0x31, 0x0A, 0x88, 0x80, 0x21, 0x09, 0x06,
0x0A, 0x43, 0x02, 0x60, 0x07, 0x48, 0x00, 0x47, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x04, 0x00,
0x00, 0x0E, 0xD4, 0x00, 0x00, 0x04, 0xD8, 0x00, 0x00, 0x04,
0xDC, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0x08
},
{
0x22, 0x4C, 0x84, 0x42, 0x20, 0xD0, 0x80, 0x1C, 0x04, 0x88,
0x01, 0x25, 0x2C, 0x40, 0x01, 0x2C, 0x02, 0xD1, 0x80, 0x1E,
0x1E, 0x49, 0x2E, 0xE0, 0x00, 0x23, 0x00, 0x24, 0x80, 0x1C,
0x40, 0xB4, 0x01, 0x26, 0x05, 0x68, 0x35, 0x40, 0x5B, 0x00,
0x2B, 0x43, 0x80, 0x1C, 0x64, 0x1C, 0x06, 0x2C, 0xF7, 0xD1,
0x40, 0xBC, 0xDB, 0x01, 0x02, 0x24, 0x24, 0x02, 0x1B, 0x19,
0x0E, 0x24, 0x24, 0x06, 0x1B, 0x19, 0x19, 0x1C, 0x09, 0x3A,
0x16, 0xE0, 0x12, 0x48, 0x00, 0x23, 0x00, 0x24, 0x40, 0xB4,
0x01, 0x26, 0x05, 0x68, 0x35, 0x40, 0x5B, 0x00, 0x2B, 0x43,
0x80, 0x1C, 0x64, 0x1C, 0x06, 0x2C, 0xF7, 0xD1, 0x40, 0xBC,
0xDB, 0x01, 0x02, 0x24, 0x24, 0x02, 0x1B, 0x19, 0x0E, 0x24,
0x24, 0x06, 0x1B, 0x19, 0x08, 0x3B, 0x18, 0x1C, 0x08, 0x4C,
0x20, 0x60, 0x08, 0x4C, 0x21, 0x60, 0x08, 0x49, 0x80, 0x20,
0x00, 0x06, 0x02, 0x43, 0x0A, 0x60, 0x06, 0x4C, 0x20, 0x47,
0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x0E, 0x04, 0x00,
0x00, 0x0E, 0xD4, 0x00, 0x00, 0x04, 0xD8, 0x00, 0x00, 0x04,
0xDC, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0x08
}
},
major, minor, micro, *buffer, *bufferptr, *ptr, value;
char dest_name[FILENAME_MAX];
int p_size[2] = { 188, 168 }, p_off, st_off;
unsigned int fsize = ucon64.file_size;
FILE *destfile;
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
if ((destfile = fopen (dest_name, "rb+")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name);
return -1;
}
if (!(buffer = (unsigned char *) malloc (fsize)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], fsize);
fclose (destfile);
exit (1);
}
if (fread (buffer, 1, fsize, destfile) != fsize)
{
fprintf (stderr, ucon64_msg[READ_ERROR], dest_name);
free (buffer);
fclose (destfile);
return -1;
}
bufferptr = buffer + 160 + 12 + 4;
ptr = (unsigned char *) memmem2 (bufferptr, fsize, "EEPROM_", 7, 0);
if (ptr == 0)
{
printf ("This ROM does not appear to use EEPROM saving\n");
free (buffer);
fclose (destfile);
return -1;
}
major = ptr[8] - '0';
minor = ptr[9] - '0';
micro = ptr[10] - '0';
if (ucon64.quiet < 0)
printf ("version: %d.%d.%d; offset: 0x%08x\n",
major, minor, micro, (int) (ptr - buffer));
if (minor > 2)
{
fputs ("ERROR: ROMs with an EEPROM minor version higher than 2 are not supported\n", stderr);
free (buffer);
fclose (destfile);
return -1;
}
ptr = (unsigned char *) memmem2 (bufferptr, fsize,
fl_orig[minor - 1], sizeof (fl_orig[minor - 1]), 0);
if (ptr == 0)
{
fputs ("ERROR: Could not find fl pattern. Perhaps this file is already patched?\n", stderr);
free (buffer);
fclose (destfile);
return -1;
}
if (ucon64.quiet < 0)
printf ("fl offset: 0x%08x\n", (int) (ptr - buffer));
fseek (destfile, ptr - buffer, SEEK_SET);
fwrite (fl_repl[minor - 1], 1, sizeof (fl_repl[minor - 1]), destfile);
ptr = buffer + fsize - 1;
value = *ptr;
do
ptr--;
while (*ptr == value && ptr - buffer > 0);
p_off = (ptr - buffer + 0xff) & ~0xff; // align at 256 byte boundary
if (ucon64.quiet < 0)
printf ("p_off: 0x%08x\n", p_off);
// if the SRAM function won't fit at the end of the ROM, abort
if ((minor == 1 && (int) (fsize - 188) < p_off) ||
(minor == 2 && (int) (fsize - 168) < p_off))
{
fputs ("ERROR: Not enough room for SRAM function at end of ROM\n", stderr);
free (buffer);
fclose (destfile);
return -1;
}
ptr = (unsigned char *) memmem2 (bufferptr, fsize,
st_orig[minor - 1], sizeof (st_orig[minor - 1]), 0);
if (ptr == 0)
{
fputs ("ERROR: Could not find st pattern\n", stderr);
free (buffer);
fclose (destfile);
return -1;
}
st_off = ptr - buffer;
if (ucon64.quiet < 0)
printf ("st offset: 0x%08x\n", st_off);
bufferptr = buffer + p_off;
switch (minor)
{
case 1:
// these are the offsets to the caller function, it handles all saving and
// is at st_off
p_repl[minor - 1][184] = (unsigned char) (st_off + 0x21);
p_repl[minor - 1][186] = (unsigned char) (st_off >> 16);
if (*(bufferptr - 1) == 0xff)
p_repl[minor - 1][185] = (unsigned char) (st_off >> 8);
else
{
st_off += 0x1f;
p_repl[minor - 1][185] = (unsigned char) (st_off >> 8);
}
// tell the calling function where the SRAM function is (p_off)
st_repl[minor - 1][5] = (unsigned char) (p_off >> 8);
st_repl[minor - 1][6] = (unsigned char) (p_off >> 16);
break;
case 2:
// offsets to the caller function
p_repl[minor - 1][164] = (unsigned char) (st_off + 0x13);
p_repl[minor - 1][165] = (unsigned char) (st_off >> 8);
p_repl[minor - 1][166] = (unsigned char) (st_off >> 16);
// tell the calling function where the SRAM function is
st_repl[minor - 1][7] = (unsigned char) (p_off >> 8);
st_repl[minor - 1][8] = (unsigned char) (p_off >> 16);
break;
}
fseek (destfile, st_off, SEEK_SET);
fwrite (st_repl[minor - 1], 1, sizeof (st_repl[minor - 1]), destfile);
fseek (destfile, p_off, SEEK_SET);
fwrite (p_repl[minor - 1], 1, p_size[minor - 1], destfile);
free (buffer);
fclose (destfile);
puts ("SRAM patch applied");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
gba_crp (st_rominfo_t *rominfo, const char *value)
{
FILE *srcfile, *destfile;
int bytesread, n = 0;
char buffer[32 * 1024], src_name[FILENAME_MAX], dest_name[FILENAME_MAX],
replace[2], wait_time = atoi (value);
if (wait_time % 4 != 0 || wait_time > 28 || wait_time < 0)
{
fprintf (stderr, "ERROR: You specified an incorrect WAIT_TIME value\n");
return -1;
}
puts ("Applying crash patch...");
strcpy (src_name, ucon64.rom);
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, src_name, 0);
if ((srcfile = fopen (src_name, "rb")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], src_name);
return -1;
}
if ((destfile = fopen (dest_name, "wb")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], dest_name);
return -1;
}
if (rominfo->buheader_len) // copy header (if present)
{
fread (buffer, 1, rominfo->buheader_len, srcfile);
fwrite (buffer, 1, rominfo->buheader_len, destfile);
}
replace[0] = wait_time;
replace[1] = 0x40;
while ((bytesread = fread (buffer, 1, 32 * 1024, srcfile)))
{ // '!' == ASCII 33 (\x21), '*' == 42 (\x2a)
n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\x14\x40", 6, '*', '!', replace, 1, -1);
n += change_mem (buffer, bytesread, "\x02\x00\x04\x14\x40\x00", 6, '*', '!', replace, 1, -2);
n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\xB4\x45", 6, '*', '!', replace, 2, -1);
n += change_mem (buffer, bytesread, "\x3E\xE0\x00\x00\xB4\x45", 6, '*', '!', replace, 2, -1);
n += change_mem (buffer, bytesread, "\x04\x02\x00\x04\x94\x44", 6, '*', '!', replace, 2, -1);
fwrite (buffer, 1, bytesread, destfile);
}
fclose (srcfile);
fclose (destfile);
printf ("Found %d pattern%s\n", n, n != 1 ? "s" : "");
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
return 0;
}
int
gba_init (st_rominfo_t *rominfo)
{
int result = -1, value;
char buf[MAXBUFSIZE];
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : 0;
ucon64_fread (&gba_header, GBA_HEADER_START +
rominfo->buheader_len, GBA_HEADER_LEN, ucon64.rom);
if (/*gba_header.game_id_prefix == 'A' && */ // 'B' in Mario vs. Donkey Kong
gba_header.start[3] == 0xea && gba_header.pad1 == 0x96 && gba_header.gba_type == 0)
result = 0;
else
{
#if 0 // AFAIK (dbjh) GBA ROMs never have a header
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : UNKNOWN_HEADER_LEN;
ucon64_fread (&gba_header, GBA_HEADER_START +
rominfo->buheader_len, GBA_HEADER_LEN, ucon64.rom);
if (gba_header.game_id_prefix == 'A' && gba_header.gba_type == 0)
result = 0;
else
#endif
result = -1;
}
if (ucon64.console == UCON64_GBA)
result = 0;
rominfo->header_start = GBA_HEADER_START;
rominfo->header_len = GBA_HEADER_LEN;
rominfo->header = &gba_header;
// internal ROM name
strncpy (rominfo->name, (const char *) gba_header.name, GBA_NAME_LEN);
rominfo->name[GBA_NAME_LEN] = 0;
// ROM maker
{
int ih = gba_header.maker_high <= '9' ?
gba_header.maker_high - '0' : gba_header.maker_high - 'A' + 10,
il = gba_header.maker_low <= '9' ?
gba_header.maker_low - '0' : gba_header.maker_low - 'A' + 10;
value = ih * 36 + il;
}
if (value < 0 || value >= NINTENDO_MAKER_LEN)
value = 0;
rominfo->maker = NULL_TO_UNKNOWN_S (nintendo_maker[value]);
// ROM country
rominfo->country =
(gba_header.game_id_country == 'J') ? "Japan/Asia" :
(gba_header.game_id_country == 'E') ? "U.S.A." :
(gba_header.game_id_country == 'P') ? "Europe, Australia and Africa" :
"Unknown country";
// misc stuff
sprintf (buf, "Version: %d\n", gba_header.version);
strcat (rominfo->misc, buf);
sprintf (buf, "Device type: 0x%02x\n", gba_header.device_type);
strcat (rominfo->misc, buf);
/*
start address = current address + (parameter of B instruction * 4) + 8
gba_header.start[3] is opcode of B instruction (0xea)
*/
value = 0x8000008 +
(gba_header.start[2] << 18 | gba_header.start[1] << 10 | gba_header.start[0] << 2);
sprintf (buf, "Start address: 0x%08x\n", value);
strcat (rominfo->misc, buf);
strcat (rominfo->misc, "Logo data: ");
if (memcmp (gba_header.logo, gba_logodata, GBA_LOGODATA_LEN) == 0)
{
#ifdef USE_ANSI_COLOR
if (ucon64.ansi_color)
strcat (rominfo->misc, "\x1b[01;32mOk\x1b[0m");
else
#endif
strcat (rominfo->misc, "Ok");
}
else
{
#ifdef USE_ANSI_COLOR
if (ucon64.ansi_color)
strcat (rominfo->misc, "\x1b[01;31mBad\x1b[0m");
else
#endif
strcat (rominfo->misc, "Bad");
}
// internal ROM crc
if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0)
{
rominfo->has_internal_crc = 1;
rominfo->internal_crc_len = 1;
rominfo->current_internal_crc = gba_chksum ();
rominfo->internal_crc = gba_header.checksum;
rominfo->internal_crc2[0] = 0;
}
rominfo->console_usage = gba_usage[0].help;
// We use fal_usage, but we could just as well use f2a_usage
rominfo->copier_usage = (!rominfo->buheader_len ? fal_usage[0].help : unknown_usage[0].help);
return result;
}
int
gba_chksum (void)
// Note that this function only calculates the checksum of the internal header
{
unsigned char sum = 0x19, *ptr = (unsigned char *) &gba_header + 0xa0;
while (ptr < (unsigned char *) &gba_header + 0xbd)
sum += *ptr++;
sum = -sum;
return sum;
}
int
gba_multi (int truncate_size, char *multi_fname)
// TODO: Check if 1024 Mbit multi-game files are supported by the FAL code
{
#define BUFSIZE (32 * 1024)
int n, n_files, file_no, bytestowrite, byteswritten, totalsize = 0, done,
truncated = 0, size_pow2_lesser = 1, size_pow2 = 1, truncate_size_ispow2 = 0;
struct stat fstate;
FILE *srcfile, *destfile;
char buffer[BUFSIZE], fname[FILENAME_MAX], *fname_ptr;
if (truncate_size == 0)
{
fprintf (stderr, "ERROR: Can't make multi-game file of 0 bytes\n");
return -1;
}
#if 0
if (truncate_size != 64 * MBIT && truncate_size != 128 * MBIT &&
truncate_size != 256 * MBIT && truncate_size != 512 * MBIT &&
truncate_size != 1024 * MBIT)
{
fprintf (stderr, "ERROR: Truncate size must be 64, 128, 256, 512 or 1024\n");
return -1;
}
#endif
if (multi_fname != NULL) // -xfalmulti
{
strcpy (fname, multi_fname);
n_files = ucon64.argc;
}
else // -multi
{
strcpy (fname, ucon64.argv[ucon64.argc - 1]);
n_files = ucon64.argc - 1;
}
ucon64_file_handler (fname, NULL, OF_FORCE_BASENAME);
if ((destfile = fopen (fname, "wb")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], fname);
return -1;
}
printf ("Creating multi-game file for FAL(/F2A): %s\n", fname);
file_no = 0;
for (n = 1; n < n_files; n++)
{
if (access (ucon64.argv[n], F_OK))
continue; // "file" does not exist (option)
stat (ucon64.argv[n], &fstate);
if (!S_ISREG (fstate.st_mode))
continue;
if (file_no == 0)
{
if (multi_fname != NULL) // -xfalmulti
{
get_property_fname (ucon64.configfile, "gbaloader", fname, "loader.bin");
if (access (fname, F_OK))
{
fprintf (stderr, "ERROR: Cannot open loader binary (%s)\n", fname);
return -1;
}
fname_ptr = fname;
// NOTE: loop counter is modified, because we have to insert
// loader in the file list
n--;
}
else // -multi
fname_ptr = ucon64.argv[n];
printf ("Loader: %s\n", fname_ptr);
if (fsizeof (fname_ptr) > 64 * 1024)
printf ("WARNING: Are you sure %s is a loader binary?\n", fname_ptr);
}
else
{
fname_ptr = ucon64.argv[n];
printf ("ROM%d: %s\n", file_no, fname_ptr);
}
if ((srcfile = fopen (fname_ptr, "rb")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], fname_ptr);
continue;
}
done = 0;
byteswritten = 0; // # of bytes written per file
while (!done)
{
bytestowrite = fread (buffer, 1, BUFSIZE, srcfile);
if (totalsize + bytestowrite > truncate_size)
{
bytestowrite = truncate_size - totalsize;
done = 1;
truncated = 1;
printf ("Output file is %d Mbit, truncating %s, skipping %d bytes\n",
truncate_size / MBIT, fname_ptr,
fsizeof (fname_ptr) - (byteswritten + bytestowrite));
// DON'T use fstate.st_size, because file could be compressed
}
totalsize += bytestowrite;
if (bytestowrite == 0)
done = 1;
fwrite (buffer, 1, bytestowrite, destfile);
byteswritten += bytestowrite;
}
fclose (srcfile);
if (truncated)
break;
file_no++;
}
fclose (destfile);
/*
Display a notification if a truncate size was specified that is not exactly
the size of one of the flash card sizes.
*/
n = truncate_size;
while (n >>= 1)
size_pow2 <<= 1;
if (truncate_size == size_pow2)
truncate_size_ispow2 = 1;
n = totalsize - 1;
while (n >>= 1)
size_pow2_lesser <<= 1;
size_pow2 = size_pow2_lesser << 1;
if (totalsize > 64 * MBIT && !truncate_size_ispow2)
printf("\n"
"NOTE: This multi-game file can only be written to a card >= %d Mbit.\n"
" Use -multi=%d to create a file truncated to %d Mbit.\n"
" Current size is %.5f Mbit\n", // 5 digits to have 1 byte resolution
size_pow2 / MBIT, size_pow2_lesser / MBIT, size_pow2_lesser / MBIT,
totalsize / (float) MBIT);
return 0;
}

View File

@@ -0,0 +1,37 @@
/*
gba.h - Game Boy Advance support for uCON64
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef GBA_H
#define GBA_H
#define GBA_LOGODATA_LEN 156
extern const st_getopt2_t gba_usage[];
extern const unsigned char gba_logodata[];
extern int gba_chk (st_rominfo_t *rominfo);
extern int gba_crp (st_rominfo_t *rominfo, const char *value);
extern int gba_init (st_rominfo_t *rominfo);
extern int gba_logo (st_rominfo_t *rominfo);
extern int gba_n (st_rominfo_t *rominfo, const char *name);
extern int gba_sram (void);
extern int gba_multi (int truncate_size, char *fname);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
/*
genesis.h - Sega Genesis/Mega Drive support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2002 - 2003 dbjh
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.
*/
#ifndef GENESIS_H
#define GENESIS_H
typedef enum { SMD = 1, BIN, MGD_GEN } genesis_file_t;
extern const st_getopt2_t genesis_usage[];
extern genesis_file_t genesis_get_file_type (void);
extern int genesis_1991 (st_rominfo_t *rominfo);
extern int genesis_chk (st_rominfo_t *rominfo);
extern int genesis_j (st_rominfo_t *rominfo);
extern int genesis_n (st_rominfo_t *rominfo, const char *name);
extern int genesis_n2 (st_rominfo_t *rominfo, const char *name);
extern int genesis_s (st_rominfo_t *rominfo);
extern int genesis_smd (st_rominfo_t *rominfo);
extern int genesis_smds (void);
extern int genesis_bin (st_rominfo_t *rominfo);
extern int genesis_mgd (st_rominfo_t *rominfo);
extern int genesis_multi (int truncate_size, char *fname);
extern int genesis_init (st_rominfo_t *rominfo);
extern int genesis_f (st_rominfo_t *rominfo);
#endif

View File

@@ -0,0 +1,109 @@
/*
jaguar.c - Atari Jaguar support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include "misc/misc.h"
#include "misc/file.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "jaguar.h"
const st_getopt2_t jaguar_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Panther(32bit prototype)/Jaguar64/Jaguar64 CD"/*"1989 Flare2/1993 Atari/1995 Atari"*/,
NULL
},
{
"jag", 0, 0, UCON64_JAG,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_JAG_SWITCH]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
typedef struct st_jaguar
{
char pad[16];
} st_jaguar_t;
#define JAGUAR_HEADER_START 0x400
#define JAGUAR_HEADER_LEN (sizeof (st_jaguar_t))
st_jaguar_t jaguar_header;
int
jaguar_init (st_rominfo_t *rominfo)
{
int result = -1, x, value;
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : 0;
ucon64_fread (&jaguar_header, JAGUAR_HEADER_START +
rominfo->buheader_len, JAGUAR_HEADER_LEN, ucon64.rom);
value = 0;
for (x = 0; x < 12; x++)
value += OFFSET (jaguar_header, x);
if (value == 0xb0)
result = 0;
else
{
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : (int) UNKNOWN_HEADER_LEN;
ucon64_fread (&jaguar_header, JAGUAR_HEADER_START +
rominfo->buheader_len, JAGUAR_HEADER_LEN, ucon64.rom);
value = 0;
for (x = 0; x < 12; x++)
value += OFFSET (jaguar_header, x);
if (value == 0xb0)
result = 0;
else
result = -1;
}
if (ucon64.console == UCON64_JAG)
result = 0;
rominfo->header_start = JAGUAR_HEADER_START;
rominfo->header_len = JAGUAR_HEADER_LEN;
rominfo->header = &jaguar_header;
rominfo->console_usage = jaguar_usage[0].help;
rominfo->copier_usage = unknown_usage[0].help;
return result;
}

View File

@@ -0,0 +1,27 @@
/*
jaguar.h - Atari Jaguar support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef JAGUAR_H
#define JAGUAR_H
extern const st_getopt2_t jaguar_usage[];
extern int jaguar_init (st_rominfo_t *rominfo);
#endif

View File

@@ -0,0 +1,357 @@
/*
lynx.c - Atari Lynx support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2002 - 2003 dbjh
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "misc/bswap.h"
#include "misc/file.h"
#include "misc/misc.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "lynx.h"
const st_getopt2_t lynx_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Handy (prototype)/Lynx/Lynx II"/*"1987 Epyx/1989 Atari/1991 Atari"*/,
NULL
},
{
"lynx", 0, 0, UCON64_LYNX,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_LYNX_SWITCH]
},
{
"lyx", 0, 0, UCON64_LYX,
NULL, "convert to LYX/RAW (strip 64 Bytes LNX header)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"lnx", 0, 0, UCON64_LNX,
NULL, "convert to LNX (uses default values for the header);\n"
"adjust the LNX header with the following options",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"n", 1, 0, UCON64_N,
"NEW_NAME", "change internal ROM name to NEW_NAME (LNX only)",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"nrot", 0, 0, UCON64_NROT,
NULL, "set no rotation (LNX only)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"rotl", 0, 0, UCON64_ROTL,
NULL, "set rotation left (LNX only)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"rotr", 0, 0, UCON64_ROTR,
NULL, "set rotation right (LNX only)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"b0", 1, 0, UCON64_B0,
"N", "change Bank0 kBytes size to N={0,64,128,256,512} (LNX only)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{
"b1", 1, 0, UCON64_B1,
"N", "change Bank1 kBytes size to N={0,64,128,256,512} (LNX only)",
&ucon64_wf[WF_OBJ_LYNX_DEFAULT]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
const char *lynx_lyx_desc = "convert to LYX/RAW (strip 64 Bytes LNX header)";
//static const char *lnx_usage[] = "LNX header";
#define LNX_HEADER_START 0
#define LNX_HEADER_LEN (sizeof (st_lnx_header_t))
st_lnx_header_t lnx_header;
int
lynx_lyx (st_rominfo_t *rominfo)
{
char dest_name[FILENAME_MAX];
if (!rominfo->buheader_len)
{
fprintf (stderr, "ERROR: This is no LNX file\n\n");
return -1;
}
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".lyx");
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, rominfo->buheader_len, ucon64.file_size, dest_name, "wb");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
lynx_lnx (st_rominfo_t *rominfo)
{
st_lnx_header_t header;
char dest_name[FILENAME_MAX];
int size = ucon64.file_size;
if (rominfo->buheader_len != 0)
{
fprintf (stderr, "ERROR: This seems to already be an LNX file\n\n");
return -1;
}
header.page_size_bank0 = size > 4 * MBIT ? 4 * MBIT / 256 : size / 256;
header.page_size_bank1 = size > 4 * MBIT ? (size - (4 * MBIT)) / 256 : 0;
#ifdef WORDS_BIGENDIAN
header.page_size_bank0 = bswap_16 (header.page_size_bank0);
header.page_size_bank1 = bswap_16 (header.page_size_bank1);
#endif
memset (header.cartname, 0, sizeof (header.cartname));
memset (header.manufname, 0, sizeof (header.manufname));
memset (header.spare, 0, sizeof (header.spare));
#ifdef WORDS_BIGENDIAN
header.version = bswap_16 (1);
#else
header.version = 1;
#endif
memcpy (header.magic, "LYNX", 4);
header.rotation = 0;
strncpy (header.cartname, ucon64.rom, sizeof (header.cartname));
strcpy (header.manufname, "Atari");
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".lnx");
ucon64_file_handler (dest_name, NULL, 0);
ucon64_fwrite (&header, 0, sizeof (st_lnx_header_t), dest_name, "wb");
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "ab");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
static int
lynx_rot (st_rominfo_t *rominfo, int rotation)
{
st_lnx_header_t header;
char dest_name[FILENAME_MAX];
if (!rominfo->buheader_len)
{
fprintf (stderr, "ERROR: This is no LNX file\n\n");
return -1;
}
ucon64_fread (&header, 0, sizeof (st_lnx_header_t), ucon64.rom);
header.rotation = rotation; // header.rotation is an 8-bit field
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (&header, 0, sizeof (st_lnx_header_t), dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
lynx_nrot (st_rominfo_t *rominfo)
{
return lynx_rot (rominfo, 0); // no rotation
}
int
lynx_rotl (st_rominfo_t *rominfo)
{
return lynx_rot (rominfo, 1); // rotate left
}
int
lynx_rotr (st_rominfo_t *rominfo)
{
return lynx_rot (rominfo, 2); // rotate right
}
int
lynx_n (st_rominfo_t *rominfo, const char *name)
{
st_lnx_header_t header;
char dest_name[FILENAME_MAX];
if (!rominfo->buheader_len)
{
fprintf (stderr, "ERROR: This is no LNX file\n\n");
return -1;
}
ucon64_fread (&header, 0, sizeof (st_lnx_header_t), ucon64.rom);
memset (header.cartname, 0, sizeof (header.cartname));
strncpy (header.cartname, name, sizeof (header.cartname));
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (&header, 0, sizeof (st_lnx_header_t), dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
static int
lynx_b (st_rominfo_t *rominfo, int bank, const char *value)
{
st_lnx_header_t header;
short int *bankvar;
char dest_name[FILENAME_MAX];
if (!rominfo->buheader_len)
{
fprintf (stderr, "ERROR: This is no LNX file\n\n");
return -1;
}
ucon64_fread (&header, 0, sizeof (st_lnx_header_t), ucon64.rom);
bankvar = (bank == 0 ? &header.page_size_bank0 : &header.page_size_bank1);
if ((atol (value) % 64) != 0 || (atol (value) > 512))
*bankvar = 0;
else
#ifdef WORDS_BIGENDIAN
*bankvar = bswap_16 (atol (value) * 4);
#else
*bankvar = atol (value) * 4;
#endif
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (&header, 0, sizeof (st_lnx_header_t), dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
lynx_b0 (st_rominfo_t *rominfo, const char *value)
{
return lynx_b (rominfo, 0, value);
}
int
lynx_b1 (st_rominfo_t *rominfo, const char *value)
{
return lynx_b (rominfo, 1, value);
}
int
lynx_init (st_rominfo_t *rominfo)
{
int result = -1;
rominfo->console_usage = lynx_usage[0].help;
rominfo->copier_usage = unknown_usage[0].help;
ucon64_fread (&lnx_header, 0, LNX_HEADER_LEN, ucon64.rom);
if (!strncmp (lnx_header.magic, "LYNX", 4))
result = 0;
else
result = -1;
if (ucon64.console == UCON64_LYNX)
result = 0;
if (!strncmp (lnx_header.magic, "LYNX", 4))
{
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : (int) LNX_HEADER_LEN;
if (UCON64_ISSET (ucon64.buheader_len) && !ucon64.buheader_len)
return ucon64.console == UCON64_LYNX ? 0 : result;
ucon64_fread (&lnx_header, 0, LNX_HEADER_LEN, ucon64.rom);
rominfo->buheader = &lnx_header;
// internal ROM name
strcpy (rominfo->name, lnx_header.cartname);
// ROM maker
rominfo->maker = lnx_header.manufname;
// misc stuff
sprintf (rominfo->misc,
"Internal Size: Bank0 %hd Bytes (%.4f Mb)\n"
" Bank1 %hd Bytes (%.4f Mb)\n"
"Version: %hd\n"
"Rotation: %s",
#ifdef WORDS_BIGENDIAN
bswap_16 (lnx_header.page_size_bank0) * 256,
TOMBIT_F (bswap_16 (lnx_header.page_size_bank0) * 256),
bswap_16 (lnx_header.page_size_bank1) * 256,
TOMBIT_F (bswap_16 (lnx_header.page_size_bank1) * 256),
bswap_16 (lnx_header.version),
#else
lnx_header.page_size_bank0 * 256,
TOMBIT_F (lnx_header.page_size_bank0 * 256),
lnx_header.page_size_bank1 * 256,
TOMBIT_F (lnx_header.page_size_bank1 * 256),
lnx_header.version,
#endif
(!lnx_header.rotation) ? "No" : ((lnx_header.rotation == 1) ? "Left" : "Right"));
}
return result;
}

View File

@@ -0,0 +1,54 @@
/*
lynx.h - Atari Lynx support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef LYNX_H
#define LYNX_H
typedef struct st_lnx_header
{
char magic[4];
short int page_size_bank0;
short int page_size_bank1;
short int version;
char cartname[32];
char manufname[16];
unsigned char rotation;
unsigned char spare[5];
} st_lnx_header_t;
extern int lynxer_main(const char *FileName);
extern int lynx_b0 (st_rominfo_t *rominfo, const char *value);
extern int lynx_b1 (st_rominfo_t *rominfo, const char *value);
extern int lynx_lnx (st_rominfo_t *rominfo);
extern int lynx_lyx (st_rominfo_t *rominfo);
extern const char *lynx_lyx_desc;
extern int lynx_n (st_rominfo_t *rominfo, const char *name);
extern int lynx_nrot (st_rominfo_t *rominfo);
extern int lynx_rotl (st_rominfo_t *rominfo);
extern int lynx_rotr (st_rominfo_t *rominfo);
extern int lynx_init (st_rominfo_t *rominfo);
extern const st_getopt2_t lynx_usage[];
#endif // LYNX_H

View File

@@ -0,0 +1,743 @@
/*
n64.c - Nintendo 64 support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2002 - 2004 dbjh
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "misc/chksum.h"
#include "misc/file.h"
#include "misc/misc.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "n64.h"
#include "patch/ips.h"
#include "patch/aps.h"
#include "backup/doctor64.h"
#include "backup/doctor64jr.h"
#include "backup/cd64.h"
#include "backup/dex.h"
#include "backup/z64.h"
#define N64_HEADER_LEN (sizeof (st_n64_header_t))
#define N64_SRAM_SIZE 512
#define N64_NAME_LEN 20
#define N64_BC_SIZE (0x1000 - N64_HEADER_LEN)
#define LAC_ROM_SIZE 1310720
const st_getopt2_t n64_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Nintendo 64"/*"1996 Nintendo http://www.nintendo.com"*/,
NULL
},
{
"n64", 0, 0, UCON64_N64,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_N64_SWITCH]
},
{
"int", 0, 0, UCON64_INT,
NULL, "force ROM is in interleaved format (2143, V64)",
&ucon64_wf[WF_OBJ_ALL_SWITCH]
},
{
"nint", 0, 0, UCON64_NINT,
NULL, "force ROM is not in interleaved format (1234, Z64)",
&ucon64_wf[WF_OBJ_ALL_SWITCH]
},
{
"n", 1, 0, UCON64_N,
"NEW_NAME", "change internal ROM name to NEW_NAME",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"v64", 0, 0, UCON64_V64,
NULL, "convert to Doctor V64 (and compatibles/interleaved)",
&ucon64_wf[WF_OBJ_N64_DEFAULT]
},
{
"z64", 0, 0, UCON64_Z64,
NULL, "convert to Mr. Backup Z64 (not interleaved)",
&ucon64_wf[WF_OBJ_N64_DEFAULT]
},
{
"dint", 0, 0, UCON64_DINT,
NULL, "convert ROM to (non-)interleaved format (1234 <-> 2143)",
&ucon64_wf[WF_OBJ_ALL_INIT_PROBE]
},
{
"swap", 0, 0, UCON64_SWAP,
NULL, "same as " OPTION_LONG_S "dint, byte-swap ROM",
&ucon64_wf[WF_OBJ_ALL_INIT_PROBE]
},
{
"swap2", 0, 0, UCON64_SWAP2,
NULL, "word-swap ROM (1234 <-> 3412)",
NULL
},
#if 0
{
"f", 0, 0, UCON64_F,
NULL, "remove NTSC/PAL protection",
NULL
},
#endif
{
"bot", 1, 0, UCON64_BOT,
"BOOTCODE", "replace/extract BOOTCODE (4032 Bytes) in/from ROM;\n"
"extracts automatically if BOOTCODE does not exist",
&ucon64_wf[WF_OBJ_N64_DEFAULT]
},
{
"lsram", 1, 0, UCON64_LSRAM,
"SRAM", "LaC's SRAM upload tool; ROM should be LaC's ROM image\n"
"the SRAM must have a size of 512 Bytes\n"
"this option generates a ROM which can be used to transfer\n"
"SRAMs to your cartridge's SRAM (EEPROM)",
&ucon64_wf[WF_OBJ_N64_INIT_PROBE]
},
{
"usms", 1, 0, UCON64_USMS,
"SMSROM", "Jos Kwanten's UltraSMS (Sega Master System/Game Gear emulator);\n"
"ROM should be Jos Kwanten's UltraSMS ROM image\n"
"works only for SMS ROMs which are <= 4 Mb in size",
&ucon64_wf[WF_OBJ_N64_DEFAULT]
},
{
"chk", 0, 0, UCON64_CHK,
NULL, "fix ROM checksum\n"
"supports only 6102 and 6105 boot codes",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
#if 0
{
"bios", 1, 0, UCON64_BIOS,
"BIOS", "enable backup in Doctor V64 BIOS",
NULL
},
#endif
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
typedef struct st_n64_header
{
unsigned char pad[64];
#if 0
unsigned char validation[2];
unsigned char compression;
unsigned char pad1;
unsigned long clockrate;
unsigned long programcounter;
unsigned long release;
unsigned long crc1;
unsigned long crc2;
unsigned char pad2[8];
unsigned char name[20];
unsigned char pad3[7];
unsigned char maker;
unsigned char cartridgeid[2];
unsigned char countrycode;
unsigned char pad4;
#endif
} st_n64_header_t;
st_n64_header_t n64_header;
typedef struct st_n64_chksum
{
unsigned int crc1;
unsigned int crc2;
} st_n64_chksum_t;
static st_n64_chksum_t n64crc;
static int n64_chksum (st_rominfo_t *rominfo, const char *filename);
int
n64_v64 (st_rominfo_t *rominfo)
{
char dest_name[FILENAME_MAX];
if (rominfo->interleaved)
{
fprintf (stderr, "ERROR: Already in V64 format\n");
exit (1);
}
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".v64");
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fbswap16 (dest_name, 0, ucon64.file_size);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_z64 (st_rominfo_t *rominfo)
{
char dest_name[FILENAME_MAX];
if (!rominfo->interleaved)
{
fprintf (stderr, "ERROR: Already in Z64 format\n");
exit (1);
}
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".z64");
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fbswap16 (dest_name, 0, ucon64.file_size);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_n (st_rominfo_t *rominfo, const char *name)
{
char buf[N64_NAME_LEN], dest_name[FILENAME_MAX];
memset (buf, ' ', N64_NAME_LEN);
strncpy (buf, name, strlen (name) > N64_NAME_LEN ? N64_NAME_LEN : strlen (name));
if (rominfo->interleaved)
ucon64_bswap16_n (buf, N64_NAME_LEN);
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (buf, rominfo->buheader_len + 32, N64_NAME_LEN, dest_name, "r+b");
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_f (st_rominfo_t *rominfo)
{
// TODO: PAL/NTSC fix
(void) rominfo; // warning remover
fputs ("ERROR: The function for cracking N64 region protections is not yet implemented\n", stderr);
return 0;
}
static void
n64_update_chksum (st_rominfo_t *rominfo, const char *filename, char *buf)
{
uint64_t crc;
int x;
// n64crc is set by n64_chksum() when called from n64_init()
crc = (((uint64_t) n64crc.crc1) << 32) | n64crc.crc2;
for (x = 0; x < 8; x++)
{
buf[x] = (char) (crc >> 56);
crc <<= 8;
}
if (rominfo->interleaved)
ucon64_bswap16_n (buf, 8);
ucon64_fwrite (buf, rominfo->buheader_len + 16, 8, filename, "r+b");
}
int
n64_chk (st_rominfo_t *rominfo)
{
char buf[8], dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
n64_update_chksum (rominfo, dest_name, buf);
dumper (stdout, buf, 8, rominfo->buheader_len + 16, DUMPER_HEX);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_sram (st_rominfo_t *rominfo, const char *sramfile)
// Function to insert an SRAM file in LaC's SRAM upload tool (which is an N64
// program)
{
char sram[N64_SRAM_SIZE], dest_name[FILENAME_MAX], buf[8];
if (access (sramfile, F_OK))
{
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], sramfile);
exit (1);
}
if (fsizeof (sramfile) != N64_SRAM_SIZE || ucon64.file_size != LAC_ROM_SIZE)
{
fprintf (stderr, "ERROR: ROM is not %d bytes and/or SRAM is not %d bytes\n",
LAC_ROM_SIZE, N64_SRAM_SIZE);
exit (1);
}
ucon64_fread (sram, 0, N64_SRAM_SIZE, sramfile);
if (rominfo->interleaved)
ucon64_bswap16_n (sram, N64_SRAM_SIZE);
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (sram, 0x286c0, N64_SRAM_SIZE, dest_name, "r+b");
n64_chksum (rominfo, dest_name); // calculate the checksum of the modified file
n64_update_chksum (rominfo, dest_name, buf);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_bot (st_rominfo_t *rominfo, const char *bootfile)
{
char buf[N64_BC_SIZE], dest_name[FILENAME_MAX];
if (!access (bootfile, F_OK))
{
strcpy (dest_name, ucon64.rom);
ucon64_fread (buf, 0, N64_BC_SIZE, bootfile);
if (rominfo->interleaved)
ucon64_bswap16_n (buf, N64_BC_SIZE);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (buf, rominfo->buheader_len + N64_HEADER_LEN, N64_BC_SIZE,
dest_name, "r+b");
}
else
{
strcpy (dest_name, bootfile);
// set_suffix (dest_name, ".bot");
ucon64_file_handler (dest_name, NULL, OF_FORCE_BASENAME | OF_FORCE_SUFFIX);
fcopy (ucon64.rom, rominfo->buheader_len + N64_HEADER_LEN, N64_BC_SIZE,
dest_name, "wb");
if (rominfo->interleaved)
ucon64_fbswap16 (dest_name, 0, fsizeof (dest_name));
}
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_usms (st_rominfo_t *rominfo, const char *smsrom)
{
char dest_name[FILENAME_MAX], *usmsbuf;
int size;
if (access (smsrom, F_OK))
{
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], smsrom);
exit (1);
}
size = fsizeof (smsrom);
// must be smaller than 4 Mbit, 524288 bytes will be inserted
// from 0x1b410 to 0x9b40f (0x7ffff)
if (size > 4 * MBIT)
{
fprintf (stderr, "ERROR: The Sega Master System/Game Gear ROM must be 524288 bytes or less\n");
exit (1);
}
if (!(usmsbuf = (char *) malloc (4 * MBIT)))
{
fprintf (stderr, ucon64_msg[BUFFER_ERROR], 4 * MBIT);
exit (1);
}
memset (usmsbuf, 0xff, 4 * MBIT);
ucon64_fread (usmsbuf, 0, size, smsrom);
if (rominfo->interleaved)
ucon64_bswap16_n (usmsbuf, size);
// Jos Kwanten's rominserter.exe produces a file named Patched.v64
strcpy (dest_name, "Patched.v64");
ucon64_file_handler (dest_name, NULL, OF_FORCE_BASENAME | OF_FORCE_SUFFIX);
fcopy (ucon64.rom, rominfo->buheader_len, ucon64.file_size, dest_name, "wb");
ucon64_fwrite (usmsbuf, rominfo->buheader_len + 0x01b410, 4 * MBIT, dest_name, "r+b");
free (usmsbuf);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
n64_init (st_rominfo_t *rominfo)
{
int result = -1, x;
unsigned int value = 0;
#define N64_MAKER_MAX 0x50
const char *n64_maker[N64_MAKER_MAX] =
{
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, "Nintendo", NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "Nintendo", NULL
},
#define N64_COUNTRY_MAX 0x5a
*n64_country[N64_COUNTRY_MAX] =
{
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "Germany", "U.S.A.",
"France", NULL, NULL, "Italy", "Japan",
NULL, NULL, NULL, NULL, NULL,
"Europe", NULL, NULL, "Spain", NULL,
"Australia", NULL, NULL, "France, Germany, The Netherlands", NULL // Holland is an incorrect name for The Netherlands
};
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ? ucon64.buheader_len : 0;
ucon64_fread (&n64_header, rominfo->buheader_len, N64_HEADER_LEN, ucon64.rom);
value = OFFSET (n64_header, 0);
value += OFFSET (n64_header, 1) << 8;
value += OFFSET (n64_header, 2) << 16;
value += OFFSET (n64_header, 3) << 24;
/*
0x41123780 and 0x12418037 can be found in te following files:
2 Blokes & An Armchair - Nintendo 64 Remix Remix (PD)
Zelda Boot Emu V1 (PD)
Zelda Boot Emu V2 (PD)
*/
if (value == 0x40123780 || value == 0x41123780) // 0x80371240, 0x80371241
{
rominfo->interleaved = 0;
result = 0;
}
else if (value == 0x12408037 || value == 0x12418037) // 0x37804012, 0x37804112
{
rominfo->interleaved = 1;
result = 0;
}
else
result = -1;
if (UCON64_ISSET (ucon64.interleaved))
rominfo->interleaved = ucon64.interleaved;
if (ucon64.console == UCON64_N64)
result = 0;
// internal ROM header
rominfo->header_start = 0;
rominfo->header_len = N64_HEADER_LEN;
rominfo->header = &n64_header;
// internal ROM name
strncpy (rominfo->name, (char *) &OFFSET (n64_header, 32), N64_NAME_LEN);
if (rominfo->interleaved)
ucon64_bswap16_n (rominfo->name, N64_NAME_LEN);
rominfo->name[N64_NAME_LEN] = 0;
// ROM maker
rominfo->maker = NULL_TO_UNKNOWN_S (n64_maker[MIN (OFFSET
(n64_header, 59 ^ rominfo->interleaved), N64_MAKER_MAX - 1)]);
// ROM country
rominfo->country = NULL_TO_UNKNOWN_S (n64_country[MIN (OFFSET
(n64_header, 63 ^ (!rominfo->interleaved)), N64_COUNTRY_MAX - 1)]);
// CRC stuff
if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0)
{
rominfo->has_internal_crc = 1;
rominfo->internal_crc_len = 4;
n64_chksum (rominfo, ucon64.rom);
rominfo->current_internal_crc = n64crc.crc1;
value = 0;
for (x = 0; x < 4; x++)
{
rominfo->internal_crc <<= 8;
rominfo->internal_crc += OFFSET (n64_header, 16 + (x ^ rominfo->interleaved));
value <<= 8;
value += OFFSET (n64_header, 20 + (x ^ rominfo->interleaved));
}
sprintf (rominfo->internal_crc2,
"2nd Checksum: %s, 0x%08x (calculated) %c= 0x%08x (internal)%s",
#ifdef USE_ANSI_COLOR
ucon64.ansi_color ?
((n64crc.crc2 == value) ?
"\x1b[01;32mOk\x1b[0m" : "\x1b[01;31mBad\x1b[0m")
:
((n64crc.crc2 == value) ? "Ok" : "Bad"),
#else
(n64crc.crc2 == value) ? "Ok" : "Bad",
#endif
n64crc.crc2,
(n64crc.crc2 == value) ? '=' : '!', value,
(n64crc.crc2 != value) ?
"\nNOTE: The checksum routine supports only 6102 and 6105 boot codes" :
"");
}
rominfo->console_usage = n64_usage[0].help;
rominfo->copier_usage = (!rominfo->buheader_len ?
((!rominfo->interleaved) ? z64_usage[0].help : doctor64_usage[0].help) : unknown_usage[0].help);
return result;
}
/*
ROM check sum routine is based on chksum64 V1.2 by Andreas Sterbenz
<stan@sbox.tu-graz.ac.at>, a program to calculate the ROM checksum of
Nintendo 64 ROMs.
*/
#define ROL(i, b) (((i) << (b)) | ((i) >> (32 - (b))))
#define BYTES2LONG(b, s) ( (b)[0^(s)] << 24 | \
(b)[1^(s)] << 16 | \
(b)[2^(s)] << 8 | \
(b)[3^(s)] )
#define CHECKSUM_START 0x1000 //(N64_HEADER_LEN + N64_BC_SIZE)
#define CHECKSUM_LENGTH 0x100000
#define CHECKSUM_STARTVALUE1 0xf8ca4ddc
#define CHECKSUM_STARTVALUE2 0xdf26f436
#define CALC_CRC32 // see this as a marker, don't disable
int
n64_chksum (st_rominfo_t *rominfo, const char *filename)
{
unsigned char bootcode_buf[CHECKSUM_START], chunk[MAXBUFSIZE & ~3]; // size must be a multiple of 4
unsigned int i, c1, k1, k2, t1, t2, t3, t4, t5, t6, clen = CHECKSUM_LENGTH,
rlen = (ucon64.file_size - rominfo->buheader_len) - CHECKSUM_START,
n = 0, bootcode; // using ucon64.file_size is ok for n64_init() & n64_sram()
FILE *file;
#ifdef CALC_CRC32
unsigned int scrc32 = 0, fcrc32 = 0; // search CRC32 & file CRC32
unsigned char *crc32_mem;
#endif
if (rlen < CHECKSUM_START + CHECKSUM_LENGTH)
{
#ifdef CALC_CRC32
n = ucon64.file_size - rominfo->buheader_len;
if ((crc32_mem = (unsigned char *) malloc (n)) == NULL)
{
fprintf (stderr, ucon64_msg[BUFFER_ERROR], n);
return -1;
}
ucon64_fread (crc32_mem, rominfo->buheader_len, n, filename);
if (!rominfo->interleaved)
{
ucon64.fcrc32 = crc32 (0, crc32_mem, n);
ucon64_bswap16_n (crc32_mem, n);
}
ucon64.crc32 = crc32 (0, crc32_mem, n);
free (crc32_mem);
#endif
return -1; // ROM is too small
}
if (!(file = fopen (filename, "rb")))
return -1;
#ifdef CALC_CRC32
if (!rominfo->interleaved)
{
if ((crc32_mem = (unsigned char *) malloc (MAXBUFSIZE)) == NULL)
{
fprintf (stderr, ucon64_msg[BUFFER_ERROR], MAXBUFSIZE);
fclose (file);
return -1;
}
}
else
crc32_mem = chunk;
fseek (file, rominfo->buheader_len, SEEK_SET);
fread (crc32_mem, 1, CHECKSUM_START, file);
memcpy (bootcode_buf, crc32_mem + N64_HEADER_LEN, N64_BC_SIZE);
if (!rominfo->interleaved)
{
fcrc32 = crc32 (0, crc32_mem, CHECKSUM_START);
ucon64_bswap16_n (crc32_mem, CHECKSUM_START);
}
else
ucon64_bswap16_n (bootcode_buf, N64_BC_SIZE);
scrc32 = crc32 (0, crc32_mem, CHECKSUM_START);
#else
fseek (file, rominfo->buheader_len + N64_HEADER_LEN, SEEK_SET);
fread (bootcode_buf, 1, N64_BC_SIZE, file);
if (rominfo->interleaved)
ucon64_bswap16_n (bootcode_buf, N64_BC_SIZE);
#endif
if (crc32 (0, bootcode_buf, N64_BC_SIZE) == 0x98bc2c86)
{
bootcode = 6105;
i = CHECKSUM_STARTVALUE2;
}
else
{
bootcode = 0; // everything else
i = CHECKSUM_STARTVALUE1;
}
t1 = i;
t2 = i;
t3 = i;
t4 = i;
t5 = i;
t6 = i;
while (1)
{
if (rlen > 0)
{
if ((n = fread (chunk, 1, MIN (sizeof (chunk), clen), file)))
{
#ifdef CALC_CRC32
if (!rominfo->interleaved)
{
memcpy (crc32_mem, chunk, n);
fcrc32 = crc32 (fcrc32, crc32_mem, n);
ucon64_bswap16_n (crc32_mem, n);
}
scrc32 = crc32 (scrc32, crc32_mem, n);
#endif
}
}
else
n = MIN (sizeof (chunk), clen);
n &= ~3;
if (n == 0)
break;
for (i = 0; i < n; i += 4)
{
c1 = BYTES2LONG (&chunk[i], rominfo->interleaved);
k1 = t6 + c1;
if (k1 < t6)
t4++;
t6 = k1;
t3 ^= c1;
k2 = c1 & 0x1f;
k1 = ROL (c1, k2);
t5 += k1;
if (c1 < t2)
t2 ^= k1;
else
t2 ^= t6 ^ c1;
if (bootcode == 6105)
{
k1 = 0x710 + (i & 0xff);
//t1 += BYTES2LONG (&bootcode_buf[k1], 0) ^ c1;
t1 += ((bootcode_buf[k1] << 24) | (bootcode_buf[k1 + 1] << 16) |
(bootcode_buf[k1 + 2] << 8) | (bootcode_buf[k1 + 3])) ^ c1;
}
else
t1 += c1 ^ t5;
}
if (rlen > 0)
{
rlen -= n;
if (rlen <= 0)
memset (chunk, 0, sizeof (chunk));
}
clen -= n;
}
n64crc.crc1 = t6 ^ t4 ^ t3;
n64crc.crc2 = t5 ^ t2 ^ t1;
#ifdef CALC_CRC32
if (!rominfo->interleaved)
{
free (crc32_mem);
crc32_mem = chunk;
}
while ((n = fread (crc32_mem, 1, sizeof (chunk), file)))
{
if (!rominfo->interleaved)
{
fcrc32 = crc32 (fcrc32, crc32_mem, n);
ucon64_bswap16_n (crc32_mem, n);
}
scrc32 = crc32 (scrc32, crc32_mem, n);
}
ucon64.crc32 = scrc32;
if (!rominfo->interleaved)
ucon64.fcrc32 = fcrc32;
#endif
fclose (file);
return 0;
}

View File

@@ -0,0 +1,37 @@
/*
n64.h - Nintendo 64 support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef N64_H
#define N64_H
extern const st_getopt2_t n64_usage[];
extern int n64_bot (st_rominfo_t *rominfo, const char *bootfile);
extern int n64_chk (st_rominfo_t *rominfo);
extern int n64_f (st_rominfo_t *rominfo);
extern int n64_init (st_rominfo_t *rominfo);
extern int n64_n (st_rominfo_t *rominfo, const char *name);
extern int n64_sram (st_rominfo_t *rominfo, const char *sramfile);
extern int n64_usms (st_rominfo_t *rominfo, const char *smsrom);
extern int n64_v64 (st_rominfo_t *rominfo);
extern int n64_z64 (st_rominfo_t *rominfo);
#endif

View File

@@ -0,0 +1,259 @@
/*
neogeo.c - NeoGeo support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "misc/misc.h"
#include "misc/file.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "neogeo.h"
const st_getopt2_t neogeo_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Neo Geo/Neo Geo CD(Z)/MVS"/*"1990/1994 SNK http://www.neogeo.co.jp"*/,
NULL
},
{
"ng", 0, 0, UCON64_NG,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_NG_SWITCH]
},
#if 0
" " OPTION_LONG_S "ns force ROM is not split\n"
"TODO: " OPTION_LONG_S "mgd convert to Multi Game Doctor/MGD2/RAW\n"
"TODO: " OPTION_LONG_S "mvs convert to Arcade/MVS\n"
#endif
{
"bios", 1, 0, UCON64_BIOS,
"BIOS", "convert NeoCD BIOS to work with NeoCD emulator" /*;\n"
"http://www.illusion-city.com/neo/"*/,
&ucon64_wf[WF_OBJ_NG_DEFAULT]
},
#if 0
"TODO: " OPTION_S "j join split ROM"
"TODO: " OPTION_S "s split ROM into 4Mb parts (for backup unit(s) with fdd)"
"TODO: " OPTION_LONG_S "ngs convert Neo Geo sound to WAV; " OPTION_LONG_S "rom=*_m1.rom or *_v*.rom"
#endif
{
"sam", 1, 0, UCON64_SAM,
"SAMFILE", "convert SAM/M.A.M.E. sound to WAV",
&ucon64_wf[WF_OBJ_NG_DEFAULT]
},
// "TODO: " OPTION_LONG_S "chkm check/fix Multiple Arcade Machine Emulator/M.A.M.E. ROMs;\n"
// " " OPTION_LONG_S "rom=DIRECTORY"
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
static int sam2wav (const char *filename);
#define NEOGEO_HEADER_START 0
#define NEOGEO_HEADER_LEN 0
int
neogeo_bios (const char *fname)
{
char dest_name[FILENAME_MAX];
strcpy (dest_name, fname);
set_suffix (dest_name, ".tmp");
ucon64_file_handler (dest_name, NULL, 0);
fcopy (fname, 0, MBIT, dest_name, "wb");
ucon64_fbswap16 (dest_name, 0, MBIT);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
int
neogeo_sam (const char *fname)
{
if (sam2wav (fname) == -1)
fprintf (stderr, "ERROR: SAM header seems to be corrupt\n");
return 0;
}
int
neogeo_mgd (void)
{
return 0;
}
int
neogeo_mvs (void)
{
return 0;
}
int
neogeo_s (void)
{
return 0;
}
int
neogeo_init (st_rominfo_t *rominfo)
{
int result = -1;
rominfo->console_usage = neogeo_usage[0].help;
rominfo->copier_usage = unknown_usage[0].help;
return result;
}
int
sam2wav (const char *filename)
{
unsigned char buf[32];
FILE *fh, *fh2;
unsigned datasize, wavesize, riffsize, freq, bits, rate;
if (fsizeof (filename) < 16)
return -1;
if (!(fh = fopen (filename, "rb")))
return -1;
strcpy ((char *) buf, filename);
set_suffix ((char *) buf, ".wav");
if (!(fh2 = fopen ((char *) buf, "wb")))
return -1;
fread (buf, 1, 4, fh);
if (strncmp ((char *) buf, "MAME", 4) != 0)
return -1;
fread (buf, 1, 4, fh);
datasize = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
wavesize = /* "fmt " */ 4 + 4 + 4 + 2 + 2;
riffsize = /* RIFF */ 4 + 4 + 4 + 4 + 4 + wavesize + datasize;
buf[0] = riffsize & 0xff;
buf[1] = (riffsize >> 8) & 0xff;
buf[2] = (riffsize >> 16) & 0xff;
buf[3] = (riffsize >> 24) & 0xff;
fwrite ("RIFF", 1, 4, fh2);
fwrite (buf, 1, 4, fh2);
fwrite ("WAVE", 1, 4, fh2);
fwrite ("fmt ", 1, 4, fh2);
buf[0] = wavesize & 0xff;
buf[1] = (wavesize >> 8) & 0xff;
buf[2] = (wavesize >> 16) & 0xff;
buf[3] = (wavesize >> 24) & 0xff;
fwrite (buf, 1, 4, fh2);
/* number of channels - alway 1 for MAME samples */
fwrite ("\001\000\001\000", 1, 4, fh2);
/* read frequency */
fread (buf, 1, 4, fh);
freq = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
/* write frequency */
fwrite (buf, 1, 4, fh2);
/* read bits, amplitude and extension */
fread (buf, 1, 4, fh);
bits = buf[0];
if (bits == 16)
rate = freq * 2;
else
rate = freq;
buf[0] = rate & 0xff;
buf[1] = (rate >> 8) & 0xff;
buf[2] = (rate >> 16) & 0xff;
buf[3] = (rate >> 24) & 0xff;
/* write bytes per second */
fwrite (buf, 1, 4, fh2);
/* write alignment */
if (bits == 16)
fwrite ("\002\000", 1, 2, fh2);
else
fwrite ("\001\000", 1, 2, fh2);
buf[0] = bits & 0xff;
buf[1] = (bits >> 8) & 0xff;
/* write bits per sample */
fwrite (buf, 1, 2, fh2);
fwrite ("data", 1, 4, fh2);
buf[0] = datasize & 0xff;
buf[1] = (datasize >> 8) & 0xff;
buf[2] = (datasize >> 16) & 0xff;
buf[3] = (datasize >> 24) & 0xff;
fwrite (buf, 1, 4, fh2);
if (bits == 16)
{
for (;;)
{
if (fread (buf, 1, 2, fh) != 2)
break;
fwrite (buf, 1, 2, fh2);
}
}
else
{
for (;;)
{
if (fread (buf, 1, 1, fh) != 1)
break;
buf[0] = buf[0] ^ 0x80;
fwrite (buf, 1, 1, fh2);
}
}
fclose (fh2);
fclose (fh);
return 0;
}

View File

@@ -0,0 +1,33 @@
/*
neogeo.h - NeoGeo support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef NEOGEO_H
#define NEOGEO_H
extern int neogeo_bios (const char *fname);
extern int neogeo_init (st_rominfo_t *rominfo);
extern int neogeo_mgd (void);
extern int neogeo_mvs (void);
extern int neogeo_s (void);
extern int neogeo_sam (const char *fname);
extern const st_getopt2_t neogeo_usage[];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
/*
nes.h - Nintendo Entertainment System support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2002 - 2003 dbjh
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.
*/
#ifndef NES_H
#define NES_H
typedef enum { INES = 1, UNIF, PASOFAMI, FFE, FDS, FAM } nes_file_t;
extern const st_getopt2_t nes_usage[];
/*
iNES Format (.NES)
------------------
Following the iNES header description (size = $10 bytes):
+--------+------+------------------------------------------+
| Offset | Size | Content(s) |
+--------+------+------------------------------------------+
| 0 | 3 | 'NES' |
| 3 | 1 | $1A |
| 4 | 1 | 16K PRG-ROM page count (size=x*0x4000) |
| 5 | 1 | 8K CHR-ROM page count (size=y*0x2000) |
| 6 | 1 | ROM Control Byte #1 |
| | | %####vTsM |
| | | | ||||+- 0=Horizontal Mirroring |
| | | | |||| 1=Vertical Mirroring |
| | | | |||+-- 1=SaveRAM enabled ($6000) |
| | | | ||+--- 1=Trainer data (512 bytes) |
| | | | |+---- 1=Four-screen mirroring |
| | | | | ($2000,$2400,$2800,$2C00) |
| | | +--+----- Mapper # (lower 4-bits) |
| 7 | 1 | ROM Control Byte #2 |
| | | %####00PU |
| | | | | |+- 1=VS Unisystem arcade |
| | | | | +-- 1=Playchoice-10 arcade |
| | | +--+----- Mapper # (upper 4-bits) |
| 8-15 | 8 | $00 |
| 16-.. | | Actual 16K PRG-ROM pages (in linear |
| ... | | order). If a trainer exists, it precedes |
| ... | | the first PRG-ROM bank. |
| ..-EOF | | CHR-ROM pages (in ascending order). |
+--------+------+------------------------------------------+
IMPORTANT: the iNES format DOES NOT support mappers greater than 255.
There are a couple of Famicom mappers > 255. They use byte #7 (low 4 bits),
which conflicts with VS Unisystem/PlayChoice-10 identification.
*/
#define INES_SIG_S "NES\x1a"
// flags in st_ines_header_t.ctrl1
#define INES_MIRROR 0x01
#define INES_SRAM 0x02
#define INES_TRAINER 0x04
#define INES_4SCREEN 0x08
#define INES_HEADER_START 0
#define INES_HEADER_LEN (sizeof (st_ines_header_t))
typedef struct
{
char signature[4]; // 0x4e,0x45,0x53,0x1a (NES file signature)
unsigned char prg_size; // # 16 kB banks
unsigned char chr_size; // # 8 kB banks
unsigned char ctrl1;
unsigned char ctrl2;
unsigned int reserved1; // 0
unsigned int reserved2; // 0
} st_ines_header_t;
#define UNIF_SIG_S "UNIF"
#define UNIF_REVISION 8 // the "official" spec is at version 7 (10/08/2002)
// numeric values of id strings in little endian format, e.g.
// UNIF_ID == 'F' << 24 | 'I' << 16 | 'N' << 8 | 'U'
#define UNIF_ID 0x46494E55
#define MAPR_ID 0x5250414D
#define READ_ID 0x44414552
#define NAME_ID 0x454D414E
#define TVCI_ID 0x49435654
#define DINF_ID 0x464E4944
#define CTRL_ID 0x4C525443
#define BATR_ID 0x52544142
#define VROR_ID 0x524F5256
#define MIRR_ID 0x5252494D
#define PCK0_ID 0x304B4350
#define PCK1_ID 0x314B4350
#define PCK2_ID 0x324B4350
#define PCK3_ID 0x334B4350
#define PCK4_ID 0x344B4350
#define PCK5_ID 0x354B4350
#define PCK6_ID 0x364B4350
#define PCK7_ID 0x374B4350
#define PCK8_ID 0x384B4350
#define PCK9_ID 0x394B4350
#define PCKA_ID 0x414B4350
#define PCKB_ID 0x424B4350
#define PCKC_ID 0x434B4350
#define PCKD_ID 0x444B4350
#define PCKE_ID 0x454B4350
#define PCKF_ID 0x464B4350
#define CCK0_ID 0x304B4343
#define CCK1_ID 0x314B4343
#define CCK2_ID 0x324B4343
#define CCK3_ID 0x334B4343
#define CCK4_ID 0x344B4343
#define CCK5_ID 0x354B4343
#define CCK6_ID 0x364B4343
#define CCK7_ID 0x374B4343
#define CCK8_ID 0x384B4343
#define CCK9_ID 0x394B4343
#define CCKA_ID 0x414B4343
#define CCKB_ID 0x424B4343
#define CCKC_ID 0x434B4343
#define CCKD_ID 0x444B4343
#define CCKE_ID 0x454B4343
#define CCKF_ID 0x464B4343
#define PRG0_ID 0x30475250
#define PRG1_ID 0x31475250
#define PRG2_ID 0x32475250
#define PRG3_ID 0x33475250
#define PRG4_ID 0x34475250
#define PRG5_ID 0x35475250
#define PRG6_ID 0x36475250
#define PRG7_ID 0x37475250
#define PRG8_ID 0x38475250
#define PRG9_ID 0x39475250
#define PRGA_ID 0x41475250
#define PRGB_ID 0x42475250
#define PRGC_ID 0x43475250
#define PRGD_ID 0x44475250
#define PRGE_ID 0x45475250
#define PRGF_ID 0x46475250
#define CHR0_ID 0x30524843
#define CHR1_ID 0x31524843
#define CHR2_ID 0x32524843
#define CHR3_ID 0x33524843
#define CHR4_ID 0x34524843
#define CHR5_ID 0x35524843
#define CHR6_ID 0x36524843
#define CHR7_ID 0x37524843
#define CHR8_ID 0x38524843
#define CHR9_ID 0x39524843
#define CHRA_ID 0x41524843
#define CHRB_ID 0x42524843
#define CHRC_ID 0x43524843
#define CHRD_ID 0x44524843
#define CHRE_ID 0x45524843
#define CHRF_ID 0x46524843
#if UNIF_REVISION > 7
// UNIF revision 8 (if it ever comes out) will probably include this chunk type
#define WRTR_ID 0x52545257
#define WRTR_MARKER ';'
#define WRTR_MARKER_S ";"
#endif
#define BOARDNAME_MAXLEN 32 // chunk length, NOT string length
// string lentgh = chunk length - 1
#define UNIF_HEADER_START 0
#define UNIF_HEADER_LEN (sizeof (st_unif_header_t))
typedef struct
{
char signature[4]; // 0x55,0x4e,0x49,0x46 ("UNIF")
unsigned int revision; // revision number
unsigned char expansion[24]; // reserved
} st_unif_header_t;
typedef struct
{
unsigned int id; // chunk identification string
unsigned int length; // data length, in little endian format
void *data;
} st_unif_chunk_t;
// DINF chunk data
typedef struct
{
char dumper_name[100]; // name of the person who dumped the cart
unsigned char day; // day of the month when cartridge was dumped
unsigned char month; // month of the year when cartridge was dumped
unsigned short year; // year during which the cartridge was dumped
char dumper_agent[100]; // name of the ROM-dumping means used (ASCII-Z string)
} st_dumper_info_t;
#define FDS_SIG_S "FDS\x1A"
#define FDS_HEADER_START 0
#define FDS_HEADER_LEN 16
// the FAM define is a guess based on FAM2FDS, more info is needed about the
// FAM format
#define FAM_HEADER_LEN 192
extern int nes_fds (void);
extern int nes_fdsl (st_rominfo_t *rominfo, char *output_str);
extern int nes_n (const char *name);
extern int nes_s (void);
extern int nes_pasofami (void);
extern int nes_ineshd (st_rominfo_t *rominfo);
extern int nes_ffe (st_rominfo_t *rominfo);
extern int nes_ines (void);
extern int nes_init (st_rominfo_t *rominfo);
extern int nes_unif (void);
extern int nes_j (unsigned char **mem_image);
extern int nes_dint (void);
extern nes_file_t nes_get_file_type (void);
#endif // NES_H

View File

@@ -0,0 +1,112 @@
/*
ngp.c - NeoGeo Pocket support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2001 Gulliver
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "misc/misc.h"
#include "misc/file.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "ngp.h"
#include "backup/pl.h"
const st_getopt2_t ngp_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Neo Geo Pocket/Neo Geo Pocket Color"/*"1998/1999 SNK http://www.neogeo.co.jp"*/,
NULL
},
{
"ngp", 0, 0, UCON64_NGP,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_NGP_SWITCH]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
typedef struct st_ngp_header
{
char pad[48];
} st_ngp_header_t;
#define NGP_HEADER_START 0
#define NGP_HEADER_LEN (sizeof (st_ngp_header_t))
st_ngp_header_t ngp_header;
int
ngp_init (st_rominfo_t *rominfo)
{
int result = -1;
char *snk_code = "COPYRIGHT BY SNK CORPORATION",
*third_code = " LICENSED BY SNK CORPORATION", buf[MAXBUFSIZE];
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ? ucon64.buheader_len : 0;
ucon64_fread (&ngp_header, NGP_HEADER_START + rominfo->buheader_len,
NGP_HEADER_LEN, ucon64.rom);
if (!strncmp ((const char *) &OFFSET (ngp_header, 0), snk_code, strlen (snk_code)) ||
!strncmp ((const char *) &OFFSET (ngp_header, 0), third_code, strlen (third_code)))
result = 0;
else
result = -1;
if (ucon64.console == UCON64_NGP)
result = 0;
rominfo->header_start = NGP_HEADER_START;
rominfo->header_len = NGP_HEADER_LEN;
rominfo->header = &ngp_header;
// internal ROM name
strncpy (rominfo->name, (const char *) &OFFSET (ngp_header, 0x24), 12);
rominfo->name[12] = 0;
// ROM maker
rominfo->maker =
!strncmp ((const char *) &OFFSET (ngp_header, 0), snk_code, strlen (snk_code)) ?
"SNK" : "Third party";
// misc stuff
sprintf (buf, "Mode: %s",
(OFFSET (ngp_header, 0x23) == 0x00) ? "Mono" :
(OFFSET (ngp_header, 0x23) == 0x10) ? "Color" :
"Unknown");
strcat (rominfo->misc, buf);
rominfo->console_usage = ngp_usage[0].help;
rominfo->copier_usage = !rominfo->buheader_len ? pl_usage[0].help : unknown_usage[0].help;
return result;
}

View File

@@ -0,0 +1,26 @@
/*
ngp.h - NeoGeo Pocket support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef NGP_H
#define NGP_H
extern const st_getopt2_t ngp_usage[];
extern int ngp_init (st_rominfo_t *rominfo);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
/*
pce.h - PC-Engine support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef PCE_H
#define PCE_H
extern const st_getopt2_t pcengine_usage[];
extern int pcengine_init (st_rominfo_t *rominfo);
extern int pcengine_mgd (st_rominfo_t *rominfo);
extern int pcengine_msg (st_rominfo_t *rominfo);
extern int pcengine_swap (st_rominfo_t *rominfo);
extern int pcengine_f (st_rominfo_t *rominfo);
extern int pcengine_multi (int truncate_size, char *fname);
#endif

View File

@@ -0,0 +1,66 @@
/*
psx.c - Playstation support for uCON64
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "misc/misc.h"
#include "misc/itypes.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "psx.h"
const st_getopt2_t psx_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Playstation (One)/Playstation 2 (CD only)"/*"1994/(2000) Sony http://www.playstation.com"*/,
NULL
},
{
"psx", 0, 0, UCON64_PSX,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_PSX_SWITCH]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
int
psx_init (st_rominfo_t *rominfo)
{
int result = -1;
rominfo->console_usage = psx_usage[0].help;
// rominfo->copier_usage = cdrw_usage[0].help;
return result;
}

View File

@@ -0,0 +1,25 @@
/*
psx.h - Playstation support for uCON64
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef PSX_H
#define PSX_H
extern int psx_init (st_rominfo_t *rominfo);
extern const st_getopt2_t psx_usage[];
#endif

View File

@@ -0,0 +1,699 @@
/*
sms.c - Sega Master System/Game Gear support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2003 - 2004 dbjh
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/stat.h>
#include "misc/chksum.h"
#include "misc/misc.h"
#include "misc/string.h"
#include "misc/file.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "sms.h"
#include "backup/mgd.h"
#include "backup/smd.h"
#define SMS_HEADER_START 0x7ff0
#define SMS_HEADER_LEN (sizeof (st_sms_header_t))
static int sms_chksum (unsigned char *rom_buffer, int rom_size);
const st_getopt2_t sms_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "Sega Master System(II/III)/Game Gear (Handheld)"/*"1986/19XX SEGA http://www.sega.com"*/,
NULL
},
{
"sms", 0, 0, UCON64_SMS,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_SMS_SWITCH]
},
{
"int", 0, 0, UCON64_INT,
NULL, "force ROM is in interleaved format (SMD)",
&ucon64_wf[WF_OBJ_ALL_SWITCH]
},
{
"nint", 0, 0, UCON64_NINT,
NULL, "force ROM is not in interleaved format (RAW)",
&ucon64_wf[WF_OBJ_ALL_SWITCH]
},
{
"mgd", 0, 0, UCON64_MGD,
NULL, "convert to Multi Game*/MGD2/MGH/RAW (gives SMS name)",
&ucon64_wf[WF_OBJ_ALL_DEFAULT_NO_SPLIT]
},
{
"mgdgg", 0, 0, UCON64_MGDGG,
NULL, "same as " OPTION_LONG_S "mgd, but gives GG name",
&ucon64_wf[WF_OBJ_SMS_DEFAULT_NO_SPLIT]
},
{
"smd", 0, 0, UCON64_SMD,
NULL, "convert to Super Magic Drive/SMD",
&ucon64_wf[WF_OBJ_ALL_DEFAULT_NO_SPLIT]
},
{
"smds", 0, 0, UCON64_SMDS,
NULL, "convert emulator (*.srm) SRAM to Super Magic Drive/SMD",
NULL
},
{
"chk", 0, 0, UCON64_CHK,
NULL, "fix ROM checksum (SMS only)",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{
"multi", 1, 0, UCON64_MULTI,
"SIZE", "make multi-game file for use with SMS-PRO/GG-PRO flash card,\n"
"truncated to SIZE Mbit; file with loader must be specified\n"
"first, then all the ROMs, multi-game file to create last",
&ucon64_wf[WF_OBJ_ALL_INIT_PROBE_STOP]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
typedef struct st_sms_header
{
char signature[8]; // "TMR "{"SEGA", "ALVS", "SMSC"}/"TMG SEGA"
unsigned char pad[2]; // 8
unsigned char checksum_low; // 10
unsigned char checksum_high; // 11
unsigned char partno_low; // 12
unsigned char partno_high; // 13
unsigned char version; // 14
unsigned char checksum_range; // 15, and country info
} st_sms_header_t;
static st_sms_header_t sms_header;
static int is_gamegear;
// see src/backup/mgd.h for the file naming scheme
int
sms_mgd (st_rominfo_t *rominfo, int console)
{
char src_name[FILENAME_MAX], dest_name[FILENAME_MAX];
unsigned char *buffer;
int size = ucon64.file_size - rominfo->buheader_len;
strcpy (src_name, ucon64.rom);
mgd_make_name (ucon64.rom, console, size, dest_name);
ucon64_file_handler (dest_name, src_name, OF_FORCE_BASENAME);
if (!(buffer = (unsigned char *) malloc (size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size);
exit (1);
}
ucon64_fread (buffer, rominfo->buheader_len, size, src_name);
if (rominfo->interleaved)
smd_deinterleave (buffer, size);
ucon64_fwrite (buffer, 0, size, dest_name, "wb");
free (buffer);
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
mgd_write_index_file ((char *) basename2 (dest_name), 1);
if (size <= 4 * MBIT)
printf ("NOTE: It may be necessary to change the suffix in order to make the game work\n"
" on an MGD2. You could try suffixes like .010, .024, .040, .048 or .078.\n");
return 0;
}
int
sms_smd (st_rominfo_t *rominfo)
{
st_smd_header_t header;
char src_name[FILENAME_MAX], dest_name[FILENAME_MAX];
unsigned char *buffer;
int size = ucon64.file_size - rominfo->buheader_len;
memset (&header, 0, SMD_HEADER_LEN);
header.size = size / 8192 >> 8;
header.id0 = 3; //size / 8192;
header.id1 = 0xaa;
header.id2 = 0xbb;
header.type = 6;
strcpy (src_name, ucon64.rom);
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".smd");
ucon64_file_handler (dest_name, src_name, 0);
if (!(buffer = (unsigned char *) malloc (size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size);
exit (1);
}
ucon64_fread (buffer, rominfo->buheader_len, size, src_name);
if (!rominfo->interleaved)
smd_interleave (buffer, size);
ucon64_fwrite (&header, 0, SMD_HEADER_LEN, dest_name, "wb");
ucon64_fwrite (buffer, rominfo->buheader_len, size, dest_name, "ab");
free (buffer);
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
return 0;
}
int
sms_smds (void)
{
st_smd_header_t header;
char src_name[FILENAME_MAX], dest_name[FILENAME_MAX];
memset (&header, 0, SMD_HEADER_LEN);
header.id1 = 0xaa;
header.id2 = 0xbb;
header.type = 7; // SRAM file
strcpy (src_name, ucon64.rom);
strcpy (dest_name, ucon64.rom);
set_suffix (dest_name, ".sav");
ucon64_file_handler (dest_name, src_name, 0);
ucon64_fwrite (&header, 0, SMD_HEADER_LEN, dest_name, "wb");
fcopy (src_name, 0, fsizeof (src_name), dest_name, "ab");
printf (ucon64_msg[WROTE], dest_name);
remove_temp_file ();
return 0;
}
int
sms_chk (st_rominfo_t *rominfo)
{
char buf[2], dest_name[FILENAME_MAX];
int offset = rominfo->header_start + 10;
if (is_gamegear)
{
fprintf (stderr, "ERROR: This option works only for SMS (not Game Gear) files\n");
return -1;
}
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
buf[0] = rominfo->current_internal_crc; // low byte
buf[1] = rominfo->current_internal_crc >> 8; // high byte
// change checksum
if (rominfo->interleaved)
{
ucon64_fputc (dest_name, rominfo->buheader_len +
(offset & ~0x3fff) + 0x2000 + (offset & 0x3fff) / 2, buf[0], "r+b");
ucon64_fputc (dest_name, rominfo->buheader_len +
(offset & ~0x3fff) + (offset & 0x3fff) / 2, buf[1], "r+b");
}
else
ucon64_fwrite (buf, rominfo->buheader_len + offset, 2, dest_name, "r+b");
dumper (stdout, buf, 2, rominfo->buheader_len + offset, DUMPER_HEX);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
static void
write_game_table_entry (FILE *destfile, int file_no, int totalsize)
{
static int sram_page = 0, sram_msg_printed = 0;
int n;
unsigned char name[0x0c], flags = 0; // x, D (reserved), x, x, x, x, S1, S0
const char *p;
fseek (destfile, 0x2000 + (file_no - 1) * 0x10, SEEK_SET);
fputc (0xff, destfile); // 0x0 = 0xff
memset (name, ' ', 0x0c);
p = basename2 (ucon64.rom);
n = strlen (p);
if (n > 0x0c)
n = 0x0c;
memcpy (name, p, n);
for (n = 0; n < 0x0c; n++)
{
if (!isprint ((int) name[n]))
name[n] = '.';
else
name[n] = toupper (name[n]); // loader only supports upper case characters
}
fwrite (name, 1, 0x0c, destfile); // 0x01 - 0x0c = name
fputc (0, destfile); // 0x0d = 0
fputc (totalsize / 16384, destfile); // 0x0e = bank code
if (sram_page > 3)
{
if (!sram_msg_printed)
{
puts ("NOTE: This ROM (and all following) will share SRAM with ROM 4");
sram_msg_printed = 1;
}
sram_page = 3;
}
flags = sram_page++;
fputc (flags, destfile); // 0x1f = flags
}
int
sms_multi (int truncate_size, char *fname)
{
#define BUFSIZE 0x20000
// BUFSIZE must be a multiple of 16 kB (for deinterleaving) and larger than or
// equal to 1 Mbit (for check sum calculation)
int n, n_files, file_no, bytestowrite, byteswritten, totalsize = 0, done,
truncated = 0, paddedsize, org_do_not_calc_crc = ucon64.do_not_calc_crc;
struct stat fstate;
FILE *srcfile, *destfile;
char destname[FILENAME_MAX];
unsigned char *buffer;
if (truncate_size == 0)
{
fprintf (stderr, "ERROR: Can't make multi-game file of 0 bytes\n");
return -1;
}
if (!(buffer = (unsigned char *) malloc (BUFSIZE)))
{
fprintf (stderr, ucon64_msg[FILE_BUFFER_ERROR], BUFSIZE);
return -1;
}
if (fname != NULL)
{
strcpy (destname, fname);
n_files = ucon64.argc;
}
else
{
strcpy (destname, ucon64.argv[ucon64.argc - 1]);
n_files = ucon64.argc - 1;
}
ucon64_file_handler (destname, NULL, OF_FORCE_BASENAME);
if ((destfile = fopen (destname, "w+b")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_WRITE_ERROR], destname);
return -1;
}
printf ("Creating multi-game file for SMS-PRO/GG-PRO: %s\n", destname);
file_no = 0;
for (n = 1; n < n_files; n++)
{
if (access (ucon64.argv[n], F_OK))
continue; // "file" does not exist (option)
stat (ucon64.argv[n], &fstate);
if (!S_ISREG (fstate.st_mode))
continue;
if (file_no == 32) // loader + 31 games
{
printf ("WARNING: A multi-game file can contain a maximum of 31 games. The other files\n"
" are ignored.\n");
break;
}
ucon64.console = UCON64_UNKNOWN;
ucon64.rom = ucon64.argv[n];
ucon64.file_size = fsizeof (ucon64.rom);
// DON'T use fstate.st_size, because file could be compressed
ucon64.rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ?
ucon64.buheader_len : 0;
ucon64.rominfo->interleaved = UCON64_ISSET (ucon64.interleaved) ?
ucon64.interleaved : 0;
ucon64.do_not_calc_crc = 1;
if (sms_init (ucon64.rominfo) != 0)
printf ("WARNING: %s does not appear to be an SMS/GG ROM\n", ucon64.rom);
if ((srcfile = fopen (ucon64.rom, "rb")) == NULL)
{
fprintf (stderr, ucon64_msg[OPEN_READ_ERROR], ucon64.rom);
continue;
}
if (ucon64.rominfo->buheader_len)
fseek (srcfile, ucon64.rominfo->buheader_len, SEEK_SET);
if (file_no == 0)
{
printf ("Loader: %s\n", ucon64.rom);
if (ucon64.file_size - ucon64.rominfo->buheader_len != 3 * 16384)
printf ("WARNING: Are you sure %s is a loader binary?\n", ucon64.rom);
}
else
{
printf ("ROM%d: %s\n", file_no, ucon64.rom);
write_game_table_entry (destfile, file_no, totalsize);
fseek (destfile, totalsize, SEEK_SET); // restore file pointer
}
file_no++;
done = 0;
byteswritten = 0; // # of bytes written per file
while (!done)
{
bytestowrite = fread (buffer, 1, BUFSIZE, srcfile);
if (ucon64.rominfo->interleaved)
smd_deinterleave (buffer, BUFSIZE);
// yes, BUFSIZE. bytestowrite might not be n * 16 kB
if (totalsize + bytestowrite > truncate_size)
{
bytestowrite = truncate_size - totalsize;
done = 1;
truncated = 1;
printf ("Output file is %d Mbit, truncating %s, skipping %d bytes\n",
truncate_size / MBIT, ucon64.rom, ucon64.file_size -
ucon64.rominfo->buheader_len - (byteswritten + bytestowrite));
}
totalsize += bytestowrite;
if (bytestowrite == 0)
done = 1;
fwrite (buffer, 1, bytestowrite, destfile);
byteswritten += bytestowrite;
}
fclose (srcfile);
if (truncated)
break;
// games have to be aligned to (start at) a 16 kB boundary
paddedsize = (totalsize + 16384 - 1) & ~(16384 - 1);
// printf ("paddedsize: %d (%f); totalsize: %d (%f)\n",
// paddedsize, paddedsize / (1.0 * MBIT), totalsize, totalsize / (1.0 * MBIT));
if (paddedsize > totalsize)
{
if (paddedsize > truncate_size)
{
truncated = 1; // not *really* truncated
paddedsize = truncate_size;
}
memset (buffer, 0, BUFSIZE);
while (totalsize < paddedsize)
{
bytestowrite = paddedsize - totalsize > BUFSIZE ?
BUFSIZE : paddedsize - totalsize;
fwrite (buffer, 1, bytestowrite, destfile);
totalsize += bytestowrite;
}
}
if (truncated)
break;
}
// fill the next game table entry
fseek (destfile, 0x2000 + (file_no - 1) * 0x10, SEEK_SET);
fputc (0, destfile); // indicate no next game
/*
The SMS requires the check sum to match the data. The ToToTEK loaders have
the lower nibble of the "check sum range byte" set to 0x0f. Maybe ToToTEK
will change this or maybe somebody else will write a loader. To avoid extra
code to handle those cases we just overwite the value.
We don't handle a GG multi-game file differently, because we cannot detect
that the user intended to make such a file (other than by adding a new GG
multi-game option). ToToTEK's GG loader has an SMS header.
*/
fseek (destfile, 0, SEEK_SET);
n = fread (buffer, 1, 0x20000, destfile); // 0x0f => check sum range = 0x20000
buffer[SMS_HEADER_START + 15] |= 0x0f; // overwrite check sum range byte
sms_header.checksum_range = 0x0f; // sms_chksum() uses this variable
n = sms_chksum (buffer, n);
buffer[SMS_HEADER_START + 10] = n; // low byte
buffer[SMS_HEADER_START + 11] = n >> 8; // high byte
fseek (destfile, SMS_HEADER_START + 10, SEEK_SET);
fwrite (buffer + SMS_HEADER_START + 10, 1, 6, destfile);
fclose (destfile);
ucon64.console = UCON64_SMS;
ucon64.do_not_calc_crc = org_do_not_calc_crc;
return 0;
}
static int
sms_testinterleaved (st_rominfo_t *rominfo)
{
unsigned char buf[0x4000] = { 0 };
ucon64_fread (buf, rominfo->buheader_len + 0x4000, // header in 2nd 16 kB block
0x2000 + (SMS_HEADER_START - 0x4000 + 8) / 2, ucon64.rom);
if (!(memcmp (buf + SMS_HEADER_START - 0x4000, "TMR SEGA", 8) &&
memcmp (buf + SMS_HEADER_START - 0x4000, "TMR ALVS", 8) && // SMS
memcmp (buf + SMS_HEADER_START - 0x4000, "TMR SMSC", 8) && // SMS (unofficial)
memcmp (buf + SMS_HEADER_START - 0x4000, "TMG SEGA", 8))) // GG
return 0;
smd_deinterleave (buf, 0x4000);
if (!(memcmp (buf + SMS_HEADER_START - 0x4000, "TMR SEGA", 8) &&
memcmp (buf + SMS_HEADER_START - 0x4000, "TMR ALVS", 8) &&
memcmp (buf + SMS_HEADER_START - 0x4000, "TMR SMSC", 8) &&
memcmp (buf + SMS_HEADER_START - 0x4000, "TMG SEGA", 8)))
return 1;
return 0; // unknown, act as if it's not interleaved
}
#define SEARCHBUFSIZE (SMS_HEADER_START + 8 + 16 * 1024)
#define N_SEARCH_STR 4
static int
sms_header_len (void)
/*
At first sight it seems reasonable to also determine whether the file is
interleaved in this function. However, we run into a chicken-and-egg problem:
in order to deinterleave the data we have to know the header length. And in
order to determine the header length we have to know whether the file is
interleaved :-) Of course we could assume the header has an even size, but it
turns out that that is not always the case. For example, there is a copy of
GG Shinobi (E) [b1] floating around with a "header" of 5 bytes.
In short: this function works only for files that are not interleaved.
*/
{
// first two hacks for Majesco Game Gear BIOS (U) [!]
if (ucon64.file_size == 1024)
return 0;
else if (ucon64.file_size == 1024 + SMD_HEADER_LEN)
return SMD_HEADER_LEN;
else
{
char buffer[SEARCHBUFSIZE], *ptr, search_str[N_SEARCH_STR][9] =
{ "TMR SEGA", "TMR ALVS", "TMR SMSC", "TMG SEGA" };
int n;
ucon64_fread (buffer, 0, SEARCHBUFSIZE, ucon64.rom);
for (n = 0; n < N_SEARCH_STR; n++)
if ((ptr = (char *)
memmem2 (buffer, SEARCHBUFSIZE, search_str[n], 8, 0)) != NULL)
return ptr - buffer - SMS_HEADER_START;
n = ucon64.file_size % (16 * 1024); // SMD_HEADER_LEN
if (ucon64.file_size > n)
return n;
else
return 0;
}
}
#undef SEARCHBUFSIZE
#undef N_SEARCH_STR
int
sms_init (st_rominfo_t *rominfo)
{
int result = -1, x;
unsigned char buf[16384] = { 0 }, *rom_buffer;
is_gamegear = 0;
memset (&sms_header, 0, SMS_HEADER_LEN);
if (UCON64_ISSET (ucon64.buheader_len)) // -hd, -nhd or -hdn option was specified
rominfo->buheader_len = ucon64.buheader_len;
else
rominfo->buheader_len = sms_header_len ();
rominfo->interleaved = UCON64_ISSET (ucon64.interleaved) ?
ucon64.interleaved : sms_testinterleaved (rominfo);
if (rominfo->interleaved)
{
ucon64_fread (buf, rominfo->buheader_len + 0x4000, // header in 2nd 16 kB block
0x2000 + (SMS_HEADER_START - 0x4000 + SMS_HEADER_LEN) / 2, ucon64.rom);
smd_deinterleave (buf, 0x4000);
memcpy (&sms_header, buf + SMS_HEADER_START - 0x4000, SMS_HEADER_LEN);
}
else
ucon64_fread (&sms_header, rominfo->buheader_len + SMS_HEADER_START,
SMS_HEADER_LEN, ucon64.rom);
rominfo->header_start = SMS_HEADER_START;
rominfo->header_len = SMS_HEADER_LEN;
rominfo->header = &sms_header;
ucon64_fread (buf, 0, 11, ucon64.rom);
// Note that the identification bytes are the same as for Genesis SMD files
// The init function for Genesis files is called before this function so it
// is alright to set result to 0
if ((buf[8] == 0xaa && buf[9] == 0xbb && buf[10] == 6) ||
!(memcmp (sms_header.signature, "TMR SEGA", 8) &&
memcmp (sms_header.signature, "TMR ALVS", 8) && // SMS
memcmp (sms_header.signature, "TMR SMSC", 8) && // SMS (unofficial)
memcmp (sms_header.signature, "TMG SEGA", 8)) || // GG
ucon64.console == UCON64_SMS)
result = 0;
else
result = -1;
x = sms_header.checksum_range & 0xf0;
if (x == 0x50 || x == 0x60 || x == 0x70)
is_gamegear = 1;
switch (x)
{
case 0x30: // SMS, falling through
case 0x50: // GG
rominfo->country = "Japan";
break;
case 0x40: // SMS, falling through
case 0x70: // GG
rominfo->country = "U.S.A. & Europe";
break;
case 0x60: // GG
rominfo->country = "Japan, U.S.A. & Europe";
break;
default:
rominfo->country = "Unknown";
break;
}
if (!UCON64_ISSET (ucon64.do_not_calc_crc) && result == 0)
{
int size = ucon64.file_size - rominfo->buheader_len;
if (!(rom_buffer = (unsigned char *) malloc (size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], size);
return -1;
}
ucon64_fread (rom_buffer, rominfo->buheader_len, size, ucon64.rom);
if (rominfo->interleaved)
{
ucon64.fcrc32 = crc32 (0, rom_buffer, size);
smd_deinterleave (rom_buffer, size);
}
ucon64.crc32 = crc32 (0, rom_buffer, size);
if (!is_gamegear)
{
rominfo->has_internal_crc = 1;
rominfo->internal_crc_len = 2;
rominfo->current_internal_crc = sms_chksum (rom_buffer, size);
rominfo->internal_crc = sms_header.checksum_low;
rominfo->internal_crc += sms_header.checksum_high << 8;
}
free (rom_buffer);
}
sprintf ((char *) buf, "Part number: 0x%04x\n",
sms_header.partno_low + (sms_header.partno_high << 8) +
((sms_header.version & 0xf0) << 12));
strcat (rominfo->misc, (char *) buf);
sprintf ((char *) buf, "Version: %d", sms_header.version & 0xf);
strcat (rominfo->misc, (char *) buf);
rominfo->console_usage = sms_usage[0].help;
rominfo->copier_usage = rominfo->buheader_len ? smd_usage[0].help : mgd_usage[0].help;
return result;
}
int
sms_chksum (unsigned char *rom_buffer, int rom_size)
{
unsigned short int sum;
int i, i_end;
switch (sms_header.checksum_range & 0xf)
{
case 0xc:
i_end = 0x7ff0;
break;
case 0xe: // falling through
case 0xf:
i_end = 0x20000;
break;
case 0:
i_end = 0x40000;
break;
case 1:
i_end = 0x80000;
break;
default:
i_end = rom_size;
break;
}
if (i_end > rom_size)
i_end = rom_size;
sum = 0;
for (i = 0; i < i_end; i++)
sum += rom_buffer[i];
if (i_end >= (int) (SMS_HEADER_START + SMS_HEADER_LEN))
for (i = SMS_HEADER_START; i < (int) (SMS_HEADER_START + SMS_HEADER_LEN); i++)
sum -= rom_buffer[i];
return sum;
}

View File

@@ -0,0 +1,36 @@
/*
sms.h - Sega Master System/Game Gear support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2003 - 2004 dbjh
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.
*/
#ifndef SMS_H
#define SMS_H
extern const st_getopt2_t sms_usage[];
extern int sms_gg (st_rominfo_t *rominfo);
extern int sms_ggd (st_rominfo_t *rominfo);
extern int sms_gge (st_rominfo_t *rominfo);
extern int sms_init (st_rominfo_t *rominfo);
extern int sms_mgd (st_rominfo_t *rominfo, int console);
extern int sms_smd (st_rominfo_t *rominfo);
extern int sms_smds (void);
extern int sms_chk (st_rominfo_t *rominfo);
extern int sms_multi (int truncate_size, char *fname);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/*
snes.h - Super NES support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
Copyright (c) 2001 - 2004 dbjh
Copyright (c) 2002 - 2003 John Weidman
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.
*/
#ifndef SNES_H
#define SNES_H
#include "backup/fig.h" // for st_fig_header_t
#define SNES_HEADER_START 0x7fb0
#define SNES_HIROM 0x8000
#define SNES_EROM 0x400000 // "Extended" ROM, Hi or Lo
typedef enum { SWC = 1, GD3, UFO, FIG, MGD_SNES, SMC } snes_file_t;
extern const st_getopt2_t snes_usage[];
extern snes_file_t snes_get_file_type (void);
extern int snes_buheader_info (st_rominfo_t *rominfo);
extern int snes_chk (st_rominfo_t *rominfo);
extern int snes_col (const char *color);
extern int snes_demirror (st_rominfo_t *rominfo);
extern int snes_densrt (st_rominfo_t *rominfo);
extern int snes_dint (st_rominfo_t *rominfo);
extern int snes_f (st_rominfo_t *rominfo);
extern int snes_fig (st_rominfo_t *rominfo);
extern int snes_figs (st_rominfo_t *rominfo);
extern int snes_gd3 (st_rominfo_t *rominfo);
extern int snes_gd3s (st_rominfo_t *rominfo);
extern int snes_get_snes_hirom (void);
extern int snes_init (st_rominfo_t *rominfo);
extern int snes_j (st_rominfo_t *rominfo);
extern int snes_k (st_rominfo_t *rominfo);
extern int snes_l (st_rominfo_t *rominfo);
extern int snes_make_gd_names (const char *filename, st_rominfo_t *rominfo, char **names);
extern int snes_mgd (st_rominfo_t *rominfo);
extern int snes_mgh (st_rominfo_t *rominfo);
extern int snes_multi (int truncate_size, char *fname);
extern int snes_n (st_rominfo_t *rominfo, const char *name);
extern int snes_s (st_rominfo_t *rominfo);
extern void snes_set_fig_header (st_rominfo_t *rominfo, st_fig_header_t *header);
extern int snes_smc (st_rominfo_t *rominfo);
extern int snes_swc (st_rominfo_t *rominfo);
extern int snes_swcs (st_rominfo_t *rominfo);
extern int snes_ufo (st_rominfo_t *rominfo);
extern int snes_ufos (st_rominfo_t *rominfo);
#endif // SNES_H

View File

@@ -0,0 +1,206 @@
/*
swan.c - WonderSwan support for uCON64
Copyright (c) 1999 - 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "misc/misc.h"
#include "misc/file.h"
#ifdef USE_ZLIB
#include "misc/archive.h"
#endif
#include "misc/getopt2.h" // st_getopt2_t
#include "ucon64.h"
#include "ucon64_misc.h"
#include "swan.h"
static int swan_chksum (unsigned char *rom_buffer);
const st_getopt2_t swan_usage[] =
{
{
NULL, 0, 0, 0,
NULL, "WonderSwan/WonderSwan Color/SwanCrystal"/*"19XX/19XX/2002 Bandai"*/,
NULL
},
{
"swan", 0, 0, UCON64_SWAN,
NULL, "force recognition",
&ucon64_wf[WF_OBJ_SWAN_SWITCH]
},
{
"chk", 0, 0, UCON64_CHK,
NULL, "fix ROM checksum",
&ucon64_wf[WF_OBJ_ALL_DEFAULT]
},
{NULL, 0, 0, 0, NULL, NULL, NULL}
};
typedef struct st_swan_header
{
char pad[10];
} st_swan_header_t;
#define SWAN_HEADER_START (ucon64.file_size - 10)
#define SWAN_HEADER_LEN (sizeof (st_swan_header_t))
st_swan_header_t swan_header;
int
swan_chk (st_rominfo_t *rominfo)
{
char buf[3], dest_name[FILENAME_MAX];
strcpy (dest_name, ucon64.rom);
ucon64_file_handler (dest_name, NULL, 0);
fcopy (ucon64.rom, 0, ucon64.file_size, dest_name, "wb");
ucon64_fputc (dest_name, SWAN_HEADER_START + 8, rominfo->current_internal_crc, "r+b"); // low byte
ucon64_fputc (dest_name, SWAN_HEADER_START + 9, rominfo->current_internal_crc >> 8, "r+b"); // high byte
ucon64_fread (buf, SWAN_HEADER_START + 8, 2, dest_name);
dumper (stdout, buf, 2, SWAN_HEADER_START + 8, DUMPER_HEX);
printf (ucon64_msg[WROTE], dest_name);
return 0;
}
/*
Byte2 - Cartridge ID number for this developer
Byte3 - ?Unknown?
00 - most roms
01 - Dig2/BAN032 & soro/KGT007
02 - Chocobo/BAN002
03 - sdej/BAN006
04 - srv2/BPR006
Byte4 - ROM Size:
01 - ?
02 - 4Mbit
03 - 8Mbit
04 - 16Mbit
05 - ?
06 - 32Mbit
07 - ?
08 - ?
09 - 128Mbit
Byte5 - SRAM/EEPROM Size:
00 - 0k
01 - 64k SRAM
02 - 256k SRAM
10 - 1k EEPROM (MGH001/NAP001)
20 - 16k EEPROM
Byte6 - Additional capabilities(?)
04 - ?? game played in "horizontal" position (most roms)
05 - ?? game played in "vertical" position
10 - ?? (SUN003)
*/
int
swan_init (st_rominfo_t *rominfo)
{
int result = -1;
unsigned char *rom_buffer, buf[MAXBUFSIZE];
#define SWAN_MAKER_MAX 0x30
const char *swan_maker[SWAN_MAKER_MAX] =
{
"BAN", "BAN", NULL, NULL, NULL,
"DTE", NULL, NULL, NULL, NULL,
NULL, "SUM", "SUM", NULL, "BPR",
NULL, NULL, NULL, "KNM", NULL,
NULL, NULL, "KGT", NULL, NULL,
NULL, NULL, "MGH", NULL, "BEC",
"NAP", "BVL", NULL, NULL, NULL,
NULL, NULL, NULL, "KDK", NULL,
"SQR", NULL, NULL, NULL, NULL,
"NMC", NULL, NULL
};
rominfo->buheader_len = UCON64_ISSET (ucon64.buheader_len) ? ucon64.buheader_len : 0;
ucon64_fread (&swan_header, SWAN_HEADER_START + rominfo->buheader_len,
SWAN_HEADER_LEN, ucon64.rom);
rominfo->header = &swan_header;
rominfo->header_start = SWAN_HEADER_START;
rominfo->header_len = SWAN_HEADER_LEN;
// ROM maker
rominfo->maker = NULL_TO_UNKNOWN_S (swan_maker[MIN (OFFSET (swan_header, 0),
SWAN_MAKER_MAX - 1)]);
// misc stuff
sprintf ((char *) buf, "Minimum supported system: %s",
(!OFFSET (swan_header, 1) ? "WS Monochrome" : "WS Color"));
strcat (rominfo->misc, (const char *) buf);
if (!(rom_buffer = (unsigned char *) malloc (ucon64.file_size)))
{
fprintf (stderr, ucon64_msg[ROM_BUFFER_ERROR], ucon64.file_size);
return -1;
}
ucon64_fread (rom_buffer, 0, ucon64.file_size, ucon64.rom);
rominfo->has_internal_crc = 1;
rominfo->internal_crc_len = 2;
if (ucon64.file_size > 10) // header itself is already 10 bytes
{
rominfo->current_internal_crc = swan_chksum (rom_buffer);
rominfo->internal_crc = OFFSET (swan_header, 8); // low byte of checksum
rominfo->internal_crc += OFFSET (swan_header, 9) << 8; // high byte of checksum
if (rominfo->current_internal_crc == rominfo->internal_crc)
result = 0;
else
result = -1;
}
if (ucon64.console == UCON64_SWAN)
result = 0;
rominfo->console_usage = swan_usage[0].help;
rominfo->copier_usage = unknown_usage[0].help;
free (rom_buffer);
return result;
}
int
swan_chksum (unsigned char *ptr)
{
unsigned int csum = 0, t;
if (ucon64.file_size % 4)
return -1;
t = ucon64.file_size - 2;
while (t-- > 0)
csum += *ptr++;
return csum & 0xffff;
}

View File

@@ -0,0 +1,27 @@
/*
swan.h - WonderSwan support for uCON64
Copyright (c) 2001 NoisyB <noisyb@gmx.net>
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.
*/
#ifndef WSWAN_H
#define WSWAN_H
extern int swan_init (st_rominfo_t *rominfo);
extern const st_getopt2_t swan_usage[];
extern int swan_chk (st_rominfo_t *rominfo);
#endif