Reverted to r598
725
HISTORY.txt
Normal file
@ -0,0 +1,725 @@
|
|||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX 1.5.0 (31/03/2011) (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core/VDP]
|
||||||
|
---------------
|
||||||
|
* added support for Master System compatibility mode (Z80 ports access mode), incl. Mode 5 rendering.
|
||||||
|
* added Mode 4 rendering for both Genesis & Master System modes.
|
||||||
|
* added alternate BG planes rendering functions (should be faster on PPC architectures).
|
||||||
|
|
||||||
|
[Core/IO]
|
||||||
|
---------------
|
||||||
|
* added support for Master System compatibility mode (Z80 ports access mode).
|
||||||
|
* added Master System peripherals emulation (Control Pad, Paddle, Sports Pad & Light Phaser).
|
||||||
|
* added XE-1AP (analog controller) emulation.
|
||||||
|
* added Activator emulation.
|
||||||
|
|
||||||
|
[Core/Extra]
|
||||||
|
---------------
|
||||||
|
* added support for all known Master System cartridge mappers.
|
||||||
|
* added copy-protection hardware emulation for a few MD unlicensed games: fixes 777 Casino (crash when talking to bunny girls).
|
||||||
|
(NB: most of those unlicensed games seem to have been already patched by ROM dumpers, main purpose is documenting them)
|
||||||
|
* added support for Top Shooter arcade board controller. (A=Shoot, B=Bet, C/RIGHT=Coins, START=Start, hold UP on startup to enter service mode)
|
||||||
|
* improved King of Fighters 98 mapper emulation (registers address decoding is now 100% accurate)
|
||||||
|
* fixed Game Genie when several codes affect same ROM address.
|
||||||
|
* fixed EEPROM types for Brian Lara Cricket & NBA Jam TE (verified on real cartridges)
|
||||||
|
|
||||||
|
[Core/General]
|
||||||
|
---------------
|
||||||
|
* added Master System compatibility mode emulation (automatically enabled when loading ROM file with .sms extension).
|
||||||
|
* improved savestate stability & compatibility (support for old 1.4.x savestates is preserved)
|
||||||
|
* various code cleanup & comments.
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
---------------
|
||||||
|
* fixed cheat codes handling when several codes affect same ROM address.
|
||||||
|
* improved input controller detection on menu exit.
|
||||||
|
* improved key remapping dialog box to match emulated device
|
||||||
|
* changed Menu key for Gamecube controller to allow MODE button mapping
|
||||||
|
* fixed DVD not being unmounted on swap (memory leak)
|
||||||
|
|
||||||
|
[Wii only]
|
||||||
|
---------------
|
||||||
|
* added USB mouse support for Sega Mouse emulation
|
||||||
|
* compiled with latest libogc: improves USB compatibility & fixes stability issues with Wiimotes.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX 1.4.1 (04/12/2010) (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core/VDP]
|
||||||
|
---------------
|
||||||
|
* improved VBLANK flag accuracy, as observed on real hardware.
|
||||||
|
* improved DMA operations accuracy, writes are now performed on a scanline basis: fixes Gaiares (flickering title screen).
|
||||||
|
* improved DMA Fill timing accuracy.
|
||||||
|
* fixed DMA with bad code values: fixes Williams Arcade Classics (corrupted gfx after soft reset).
|
||||||
|
* fixed horizontal resolution changes during HBLANK: fixes Bugs Bunny in Double Trouble (2nd stage).
|
||||||
|
* fixed Vertical Counter in interlace mode 1, as observed on real hardware.
|
||||||
|
* fixed horizontal border width, as observed on real hardware.
|
||||||
|
* various code improvments & optimizations.
|
||||||
|
|
||||||
|
[Core/Extra]
|
||||||
|
---------------
|
||||||
|
* improved savestate format: added DMA, SVP, cartridge mapping & internal registers state informations
|
||||||
|
* improved unlicensed ROM mappers emulation
|
||||||
|
* added Chinese Fighters III mapper support
|
||||||
|
* added Top Fighter mapper support
|
||||||
|
* fixed Barver Battle Saga mapper support
|
||||||
|
* fixed cartridge hardware soft-reset (Game Genie, SVP, ...)
|
||||||
|
* fixed Game Genie registers byte reads
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
---------------
|
||||||
|
* added message box when inputs config uses disconnected controllers.
|
||||||
|
* added message box when settings are reseted to default on startup.
|
||||||
|
* fixed default inputs configuration.
|
||||||
|
* fixed memory leak in Cheat Menu causing spurious resets.
|
||||||
|
* added an option to enable/disable automatic cheat activation
|
||||||
|
* increased max number of cheat codes
|
||||||
|
* optimized cheat codes requiring RAM patching.
|
||||||
|
* improved default horizontal scaling to better match output from a real Mega Drive
|
||||||
|
|
||||||
|
[Gamecube specific]
|
||||||
|
---------------
|
||||||
|
* fixed inverted keys in cheat menu.
|
||||||
|
* fixed audio input frequency, now use exact audio hardware samplerate, as measured on my Game Cube (~48044 Hz),
|
||||||
|
(NB: Wii samplerate has been verified to be closer to 48000 Hz)
|
||||||
|
|
||||||
|
[Wii specific]
|
||||||
|
---------------
|
||||||
|
* added the possibility for any wiimotes to be used as input device, regardless of the connected expansion controller.
|
||||||
|
* fixed USB drive not being detected when application is loaded from USB (HBC), thanks to Tantric for the tips.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX 1.4.0 (01/11/2010) (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core/Sound]
|
||||||
|
---------------
|
||||||
|
* completely rewrote sound processing/mixing: sound chips are now clocked with exact output framerate
|
||||||
|
to ensure 100% smooth video & audio playback, with no lag or skipping, while rendering an accurate number
|
||||||
|
of samples per frame and keeping PSG & FM chips in sync.
|
||||||
|
* improved PSG & FM chips synchronization with CPU execution (fixed point precision).
|
||||||
|
* improved YM2612 core general accuracy (SSG-EG, CSM mode,...) (based upon Nemesis recent tests on real hardware)
|
||||||
|
* improved YM2612 LFO emulation accuracy: fixes "Spider-Man & Venom : Separation Anxiety" (intro)
|
||||||
|
* fixed YM2612 bug with Timer B: fixes "Langrisser Hikari II"/"Der Langrisser II" (Sega logo)
|
||||||
|
* fixed YM2612 context saving/loading.
|
||||||
|
* fixed YM2612 state on reset.
|
||||||
|
* removed outdated & less accurate Gens YM2612 core
|
||||||
|
* added configurable YM2612 DAC resolution emulation.
|
||||||
|
* added configurable & faster FIR resampler (thanks to Blargg & AamirM), removed libsamplerate support.
|
||||||
|
* added configurable Low-Pass filtering
|
||||||
|
* added configurable 3-Band Equalizer (thanks to Neil C).
|
||||||
|
* added an option to boost SN76489 Noise Channel.
|
||||||
|
* adjusted SN76489 cut-off frequency.
|
||||||
|
* implemented Blargg's blip buffer in SN76489 core (all channels are now lineary interpolated)
|
||||||
|
|
||||||
|
[Core/VDP]
|
||||||
|
---------------
|
||||||
|
* added support for CRAM writes during horizontal blanking (Striker, Zero the Kamikaze Squirrel,...)
|
||||||
|
* added support for 2-Cell vertical scrolling in Interlaced 2 mode
|
||||||
|
* added support for some undocumented mode register bits
|
||||||
|
* added proper emulation of HV Counter latch: fixes Sunset Riders intro
|
||||||
|
* added pixel-accurate emulation of mid-line display on/off (Nigel Mansell World Championship PAL, Ren & Stimpy's Invention PAL,...)
|
||||||
|
* improved 2-cell vscroll emulation accuracy, as verified on real hardware (Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge)
|
||||||
|
* improved FIFO timings accuracy: fixes Sol Deace intro
|
||||||
|
* improved sprite masking accuracy (thanks to Nemesis for his test program)
|
||||||
|
* improved sprites processing accuracy: fixes (un)masked sprites in Mickey Mania (3D level), Sonic 2 (VS mode).
|
||||||
|
* improved HBLANK flag timing accuracy: fixes Mega Turrican (Sky level)
|
||||||
|
* improved horizontal blanking & HINT/VINT occurence timing accuracy, as measured on real hardware.
|
||||||
|
* improved HCounter accuracy in 40-cell mode, as measured on real hardware.
|
||||||
|
* improved color accuracy in VDP highlight mode to match results observed on real hardware
|
||||||
|
|
||||||
|
[Core/CPU]
|
||||||
|
---------------
|
||||||
|
* updated Z80 core to last version (fixes interrupt Mode 0 timing and some BIT instructions).
|
||||||
|
* fixed some Z80 instructions timing.
|
||||||
|
* fixed state of Z80 registers on reset (sound issues with Defender & Defender 2 in Williams Arcade Classics)
|
||||||
|
* improved Z80 interrupt accuracy
|
||||||
|
* improved 68k accuracy (initial Reset timing + auto-vectored interrupts handling).
|
||||||
|
* improved 68k timing accuracy for DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS instructions.
|
||||||
|
* implemented 68k undocumented flags behavior for DIVU/DIVS instructions (Bloodshot / Battle Frenzy)
|
||||||
|
* improved Z80 & 68k cpu execution/synchronization accuracy by using Master Clock as common reference (now run exactly 3420 M-Cycles per line).
|
||||||
|
* modified Z80 & 68k cores to directly use external cycle count instead of intermediate counters.
|
||||||
|
|
||||||
|
[Core/Extra]
|
||||||
|
---------------
|
||||||
|
* added Game Genie hardware emulation.
|
||||||
|
* added Action Replay & Pro Action Replay hardware emulation (only preliminary Pro Action Replay 2 support).
|
||||||
|
* added Sonic & Knuckles "Lock-On" support.
|
||||||
|
* added Cartridge "Hot Swap" feature.
|
||||||
|
* added missing EEPROM support in more games.
|
||||||
|
* added VDP lock-out emulation (TMSS).
|
||||||
|
* improved emulation of copy-protection hardware found in some unlicensed cartridges (Mulan, Pocket Monsters II).
|
||||||
|
* fixed Realtec mapper emulation: fixes missing sound in Balloon Boy / Funny World.
|
||||||
|
* fixed lightgun auto-detection: fixes default cursor position in Lethal Enforcers II.
|
||||||
|
* enabled simultaneous use of multitap & J-CART (Super Skidmarks 6-player mode)
|
||||||
|
* lots of code cleanup, bugfixes & optimization.
|
||||||
|
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
---------------
|
||||||
|
* implemented custom FONT engine (uses internal IPL font & GX hardware rendering).
|
||||||
|
* implemented custom GUI engine (uses GX hardware rendering & multithreading)
|
||||||
|
* implemented advanced menu interface (IR pointing, game snapshots, cheats & saves manager, visual & sound effects, BGM support, etc).
|
||||||
|
* improved audio/video synchronization to ensure 100% smooth video & audio playback.
|
||||||
|
* improved soft-reset button support, now works more like real Mega Drive / Genesis (model 1) reset button.
|
||||||
|
* improved lightgun cursors layout.
|
||||||
|
* added automatic ROM loading feature (last played game launches immediately when starting the emulator)
|
||||||
|
* added PAR codes and .pat files support
|
||||||
|
* fixed lot of stability issues and potential memory leaks.
|
||||||
|
|
||||||
|
[Wii specific]
|
||||||
|
---------------
|
||||||
|
* added Video Hardware "Gamma" control
|
||||||
|
* added Video Hardware "Trap Filter" control
|
||||||
|
* improved Mouse emulation through Wii remote
|
||||||
|
* compiled with devkitPPC r22 & libOGC 1.8.5 (includes SDHC & USB2 support through IOS58, removes DVDX support)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX 1.3.1 (20/12/2008) (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* improved sound engine
|
||||||
|
* modified frame synchronization (now use audio DMA interrupt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX 1.3.0 (14/12/2008) (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* YM2612 bugfixes (MAME core):
|
||||||
|
.fixed EG Decay->Substain transition when SL & DR are minimals: fix tracks #3 and #9 in "Mega Turrican"
|
||||||
|
.fixed a bug in SSG-EG emulation code: fix Level 1 music in "Alisia Dragoon"
|
||||||
|
.modified SSG-EG Decay End Level: fix some sound effects (ChainSaw, Zap...) in "Beavis & Butthead"
|
||||||
|
.improved Detune overflow accuracy: fix very high frequency sounds in many games
|
||||||
|
.fixed registers 0x20-0x26 Reset state: fix intro music in "B.O.B"
|
||||||
|
.reverted incorrect fix with KEY ON: fix "Flamethrower" sound effect in "Alien 3" and many others
|
||||||
|
* adjusted HCounter values: fixes line flickering in "Sonic 3D" bonus stage
|
||||||
|
* adjusted VINT timing: fixes hang-up in "V.R Troopers"
|
||||||
|
* improved HBLANK flag accuracy: fixes line flickering in "Gouketsuji Ichizoku"
|
||||||
|
* fixed broken Z80 access to WRAM: fixes hang-up in "Mamono Hunter Youko"
|
||||||
|
* modified JCART emulation: fixes corrupted tracks logo in "Micro Machines 2"
|
||||||
|
* added Blargg's NTSC Filters support (NTSC video artifacts emulation)
|
||||||
|
* optimized VDP rendering core, rewrote 68k interface (memory handlers, cycle execution, interrupts): greatly improved emulation speed
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* remove slowest libsamplerate settings under "HQ YM2612" option, only keeps SRC_LINEAR (faster) and SRC_SINC_FAST (better)
|
||||||
|
* added an option to enable/disable bilinear filtering
|
||||||
|
* rewrote video engine: improved horizontal scaling (VI+GX), improved rendering speed (direct texture mapping)
|
||||||
|
* removed embedded font, (re)enabled IPL font support: now should works for Qoob users too (thanks to emukiddid)
|
||||||
|
* fixed "Reset" button behavior, now acts more like Genesis Reset button ;-)
|
||||||
|
* patched libfat for faster SDCARD accesses (thanks to svpe)
|
||||||
|
* SRAM and SaveState filenames are now based on the ROM filename (for FAT devices only)
|
||||||
|
* various bugfixes, menu tweaks and code cleanup
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* added 480p support in menu
|
||||||
|
|
||||||
|
[Wii]
|
||||||
|
|
||||||
|
* implemented fast scrolling in menu using Wiimote D-PAD
|
||||||
|
* added "Power" button support
|
||||||
|
* added USB Storage support
|
||||||
|
* Widescreen menu fix
|
||||||
|
* *new* libogc 1.7.0 features: SDHC support, Wiimote shutdown button support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080826 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* YM2612(MAME): fixed LFO phase update for CH3 special mode: fix sound effects in Warlock & Aladdin (thanks to AamirM)
|
||||||
|
* YM2612(MAME): fixed EG attenuation level on "KEY ON": fix Ecco 2's splash sound
|
||||||
|
* YM2612(MAME): fixed SSG-EG emulation: fix Bubba'n Stix (Track 5) and many others
|
||||||
|
* YM2612(MAME): replaced sample interpolation with libsamplerate support, High Quality mode is now more accurate
|
||||||
|
* implemented cycle-accurate HINT timings: every timing sensitive games/demos are now *finally* working fine
|
||||||
|
* fixed a bug affecting CRAM/VSRAM DMA timings
|
||||||
|
* fixed Sprite Attribute Table address mask for VRAM writes
|
||||||
|
* improved accuracy of 68k access to Z80: fix music in Pacman 2 when entering PAUSE menu
|
||||||
|
* disabled "Address Error" emulation when UMK3 hack is loaded: fix game crashing after a round ends up
|
||||||
|
* added support for some more unlicensed games: Pocket Monster, King of Fighter 98, Soul Blade (credits to Haze)
|
||||||
|
* improved Menacer emulation: fix lightgun support in Body Count & T2: The Arcade Game
|
||||||
|
* added Konami Justifier emulation: fix lightgun support in Lethal Enforcers 1 & 2
|
||||||
|
* added Sega Mouse emulation (Populous 2, Body Count, Shangai 2, Fun'n Games, ...)
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* added Wiimote support for Menacer/Justifier/Mouse
|
||||||
|
* added DVD support in Wii mode (no modchip required)
|
||||||
|
* added "Gun cursor" option to enable/disable gun position display
|
||||||
|
* added "Invert Mouse" option to invert Sega Mouse vertical axe (required by some games)
|
||||||
|
* improved Controller options: Wiimote/Nunchuk and Classical Controllers can now be affected separately to ANY player
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080716 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* adjusted (again) HINT timings: fix Double Dragon 2 (game freezed), hopefully does not break anything else
|
||||||
|
* fixed broken EEPROM support for Codemaster games
|
||||||
|
* modified input update timings: fix Dungeons & Dragons * Warriors of the Eternal Sun (thanks to Notaz)
|
||||||
|
* added support for "Ultimate Mortal Kombat Trilogy" hack (max. size supported is 10MBytes)
|
||||||
|
* added (VERY) preliminar support for PICO roms (credits to Notaz for his documentation)
|
||||||
|
* improved YM2612 emulation (credits to Nemesis for his tests on real hardware):
|
||||||
|
.implemented phase overflow emulation: improved fix for special music instrument used in Comix Zone, Flashback, Ariel, Shaq Fu...
|
||||||
|
.improved SSG-EG emulation in MAME core (also based on additional code from Alone Coder)
|
||||||
|
.improved Timers emulation accuracy
|
||||||
|
.improved Enveloppe Generator accuracy
|
||||||
|
.fixed Channel 3 CSM mode emulation
|
||||||
|
.implemented sample interpolation in MAME core to emulate the chip at original frequency (HQ YM2612 mode, from gens)
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* added automatic alphabetical filesorting (Marty Disibio)
|
||||||
|
* added ROM History for faster ROM access (Marty Disibio)
|
||||||
|
* fixed a silly input bug in "ROM Infos" & "Game Genie" menus
|
||||||
|
* modified "Hard Reset" option
|
||||||
|
* improved display sharpness in original rendering mode (H40 cell mode only), filtering is now completely disabled
|
||||||
|
* enabled overscan emulation in "STRETCH" aspect mode also
|
||||||
|
* added support for horizontal wiimote handling in Menu (automatically used when the wiimote is not pointed towards the screen)
|
||||||
|
* improved Controller options
|
||||||
|
.prevented keys reconfiguration if device is not detected
|
||||||
|
.added support for up to 8 players (ISS Pro Deluxe, ...)
|
||||||
|
.each player can be affected to a custom device (GAMECUBE Pad, WIIMOTE/NUNCHUK or CLASSIC)
|
||||||
|
.added the ability to use classic controller & wiimote pad from the same port separately
|
||||||
|
.modified "soft-reset" key on the Wiimote to avoid "accidental" resets (now press Buttons + & * simultaneously)
|
||||||
|
.added MODE button mapping: use "START+Z" on gamepad or "Button Minus" on wiimote/classic (not reconfigurable)
|
||||||
|
.added automatic configuration save for controller options
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080601 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* improved HCounter accuracy: fix graphic glitches in "Striker (Europe)"
|
||||||
|
* improved HINT timing accuracy: fix flickering in "Zero The Kamikaze Squirrel (USA)"
|
||||||
|
* improved rendering accuracy when backdrop color is modified during HBLANK (Road Rash I/II/III)
|
||||||
|
* fixed broken Game Genie support
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* added full horizontal scaling (up to 720 pixels) when using "stretch" aspect mode (use Xscale to increase width)
|
||||||
|
* added progressive mode support (480p) in menu also
|
||||||
|
* added automatic SRAM/FreezeState support (OFF by default, check "system options")
|
||||||
|
* added automatic configuration file support
|
||||||
|
* /genplus/saves is now automatically created if it does not exist
|
||||||
|
* use libfat automatic SDCARD detection: default slot is now always used when accessing SDCARD
|
||||||
|
* assigned Reset Button to Genesis Soft-Reset
|
||||||
|
|
||||||
|
[Wii]
|
||||||
|
|
||||||
|
* added automatic TV mode detection (from SYSCONF), no more PAL60 version needed
|
||||||
|
* added option to return to Wii System Menu
|
||||||
|
* fixed "TP reload" option: now compatible with HB channel
|
||||||
|
* removed SD-Gekko support (Wii slot becomes default slot)
|
||||||
|
* added Wii SD slot support for SRAM & FreezeState files
|
||||||
|
* added Wiimote, Nunchuk & Classic controllers support through libwiiuse (see User Manual for default keys)
|
||||||
|
* added customizable key mapping (for each configurations: wiimote only, wiimote+nunchuk or classic)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080419 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* modified VINT timings a little bit: fix lockup during Desert Strike's intro
|
||||||
|
* corrected 68k interrupts handling: fix graphic glitches in Darius II/Sagaia
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* fixed 60Hz "Bilinear" rendering mode (was broken in last release)
|
||||||
|
* fixed issue with the 1st file when browsing SDCARD through SD-Gekko
|
||||||
|
* fixed GX initialization: fix "freeze" issue that occured sometime when starting a game
|
||||||
|
* added "Wii Reboot" option
|
||||||
|
* added PAL 50hz support in menu (black borders)
|
||||||
|
* added progressive rendering mode support (480p) in Wii mode (not supported by the PAL60 version, use the other one !)
|
||||||
|
* compiled with a modified libogc: should definitely fix the PAL "red screen" issue for RGB-cable users (still use the PAL60 version !)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080406 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* updated SVP core: fix some perspective issues in Virtua Racing (thanks to Notaz)
|
||||||
|
* added internal SAT update during VRAM Fill: fix unmasked sprites during Battletech's intro
|
||||||
|
* fixed m68k core issues with gcc 4.2.3: fix Xperts, Lemmings 2, M1 Abrams Battle Tank
|
||||||
|
* forced YM2612 Enveloppe update: fix intro music in Batman&Robin (thanks to Aamir)
|
||||||
|
|
||||||
|
[Gamecube/Wii]
|
||||||
|
|
||||||
|
* removed not working DVD features (Wii mode only)
|
||||||
|
* fixed Timers with PAL roms
|
||||||
|
* added EURGB60 TV mode support: fix "red screen" issue with PAL Wii when using RGB cable
|
||||||
|
* added PAL50 TV mode support (PAL and NTSC roms), see video options
|
||||||
|
* added "TP reload" option, use "System Reboot" (Wii mode only)
|
||||||
|
* added Front SD rom loading support with LFN & subdirectory browsing (Wii mode only)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080301 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* added SVP emulation: Virtua Racing is now emulated (big thanks to Notaz and TascoDeluxe)
|
||||||
|
* fixed VDP registers behaviour when VDP Mode 4 is enabled: fix Bass Masters Classic Pro, Captain Planet & The Planeeters
|
||||||
|
* corrected a bug in DMA Fill operation: fix James Pond 3, Rockman World/Megaman Willy Wars (corrupted VRAM)
|
||||||
|
* corrected typo errors in CPU cycle counters update: fix optiom screen music in "College Slam" and probably others games.
|
||||||
|
* added preliminary support of undocumented YM2612 bug: fixes soundtracks of Shaq Fu, Spiderman, Comix Zone, Ariel and some others
|
||||||
|
* added support for mappers & copy protection devices used in many unlicensed/pirate cartridges (see cart_hw.c for details)
|
||||||
|
* rewrote memory handlers for better modularity and some (little) speedup
|
||||||
|
* reduced Savestate size
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* compiled with last LibOGC (20080228): fix issues when unplugging controller, support for Wii mode (see release.txt)
|
||||||
|
* added "hard-coded" IPL font (no more direct access to BOOTROM): fix font problem for Qoob users
|
||||||
|
* added SDCARD Slot B support for loading Roms
|
||||||
|
* removed unused MAME PSG Core
|
||||||
|
* added 'Force DTACK' option for prototype games usually hanging on real hardware (example: Sonic Crackers)
|
||||||
|
* added an option to underclock SVP core (with default cycle count, Virtua Racing actually does not run fullspeed in GC mode)
|
||||||
|
* fixed frame timing in PAL mode
|
||||||
|
* fixed analog stick sensitivity
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 080107 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* fixed interleaved rom detection: roms with .smd extension should now work fine
|
||||||
|
* fixed a recently introduced bug in VDP registers writes: fixes bad colors in Toy Story (intro)
|
||||||
|
* updated list of games using EEPROM: added Sports Talk Baseball (internal memory check fixed) and Brian Lara Cricket
|
||||||
|
* fixed VINT flag update when VINT is disabled: fixes NCAA College Football
|
||||||
|
* adjusted DMA timings in H32 mode: fixes flickering in Out of this World, Kawasaki Superbike Challenge & Formula One
|
||||||
|
* adjusted line rendering and HBLANK timings: fixes flickering in Nigel Mansell's World Championship Racing, Deadly Moves/Power Athlete
|
||||||
|
* fixed unmapped ROM reads through Z80 Bank: fixes Zombie High (Proto)
|
||||||
|
* added support for custom ROM/RAM mapping used by Game no Kanzume Otokuyou
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* fixed broken SDCARD support for SRAM and Savestate files
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 071230 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* fixed ROM injector base address (DATA section 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 071228 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* many sourcecode cleanup and optimization
|
||||||
|
* completely rewrote EEPROM emulation: now support all known EEPROM types (24C01-24C65) and mappers (Sega, Acclaim, EA, Codemasters)
|
||||||
|
used in a few games (now use internal game database) as external RAM. This should at least fix save support in the following games:
|
||||||
|
. NBA Jam (alternate Acclaim mapper)
|
||||||
|
. College Slam, Frank Thomas Big Hurt Baseball (24C65 type)
|
||||||
|
. NHLPA Hockey 93, Rings of Power (EA mapper)
|
||||||
|
. Micro Machines serie, Brian Lara Cricket 96/Shane Warne Cricket (Codemasters mapper)
|
||||||
|
* external RAM is now initialized to 0xFF by default: fix Micromachines 2, Dino Dini Soccer
|
||||||
|
* fixed SRAM 16-bits memory handlers: fix some Sega Sports and EA Sports games (NFL95, NBA Action 95, NHL97, NHL98,...)
|
||||||
|
* modified WRITE_xxx & READ_xxx macros for better portability and faster memory access on BIG ENDIAN platform
|
||||||
|
* completely rewrote BIG ENDIAN support in render.c and vdp.c: rendering should be a little faster
|
||||||
|
* rewrote ROM bankswitch emulation (Super Street Fighter II): ROM access are faster, using memory pointers instead of reading ROM copy from ARAM
|
||||||
|
* fixed leftmost Window/PlaneA column render and implemented Window bug (as described by Charles Mc Donald)
|
||||||
|
* improved "Sprite Limit" and "Sprite Collision" detection accuracy
|
||||||
|
* modified RGB565 Color Palette to use the full available color range (0-31;0-63)
|
||||||
|
* implemented "cycle accurate" HV Interrupt timings: fix Sesame's Street Counting Cafe, Legend of Galahad (intro)
|
||||||
|
* improved VDP access timings accuracy (added FIFO emulation): fix Double Clutch
|
||||||
|
* improved DMA timings accuracy: fix Winter Olympics (E), Arch Rivals and probably more
|
||||||
|
* fixed HCounter again: Road Rash serie (I,II,III) don't need timing hacks anymore
|
||||||
|
* fixed VCounter in Interlaced 2 mode: fix Combat Cars "VS-Mode"
|
||||||
|
* improved Interlaced 2 mode (double resolution) rendering: Sonic 2, Combat Cars ("VS-Modes") look far better
|
||||||
|
* added TMSS BIOS support (optional)
|
||||||
|
* rewrote part of the YM2162 MAME's core: fixed internal FM timers handling, removed non-YM2612 emulation code and unused multiple cpu support
|
||||||
|
* implemented "cycle accurate" FM timers & sound samples rendering
|
||||||
|
* improved Z80 Interrupt timing accuracy: fix Sonic 3 music slowdowns
|
||||||
|
* updated Z80 & 68000 cores to last MAME versions
|
||||||
|
* improved Soft Reset emulation: X-Men 2 and Eternal Champions (random character selection) now work more like on real hardware.
|
||||||
|
* added full overscan emulation (vertical & horizontal borders) for "pixel perfect" aspect ratio (tested against a real genesis)
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* fixed rom checksum calculation (only used for rom information)
|
||||||
|
* some modifications in GX rendering code.
|
||||||
|
* added support for original Genesis/Megadrive NTSC & PAL video modes: this makes games looking exactly as on original hardware (progressive rendering with reduced resolution)
|
||||||
|
* added "Aspect" option to switch between ORIGINAL (aspect ratio is fixed and borders are emulated) and MANUAL SET (horizontal and vertical scaling can be manually configured, borders are not emulated)
|
||||||
|
* added "Overscan" option to disable the original borders color and always use black borders (only used when ORIGINAL Aspect mode is enabled)
|
||||||
|
* added support for up to 720 pixels horizontal resolution (needed for proper aspect ratio emulation)
|
||||||
|
* added "TV Mode" option to enable automatic switching to PAL(50Hz) TV mode when the Genesis runs in PAL mode
|
||||||
|
* added "Xshift" & "Yshift" settings to let you adjust display area position while keeping the original aspect ratio
|
||||||
|
* added option to disable/enable SSG-EG support in FM cores: this special mode is indeed not properly emulated and some games might sound wrong when enabled
|
||||||
|
* removed "CPU Type" option, you can also now force Region (JAP/EUR/USA) without reseting the game, choose USA or JAP for 60hz, EUR for 50hz, this can be useful to bypass game region protection at startup.
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070720 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* corrected TeamPlayer support: fix multiplayer in Gauntlet 4 (Sept. version), Pengo and a lot of others
|
||||||
|
* added J-Cart support: enable multiplayer in Codemasters games (Pete Sampras, Micromachines games, Super Skidmarks)
|
||||||
|
* added serial EEPROM autodetection: fix games with bad SRAM informations in header (NBA Jam TE)
|
||||||
|
* added SVP faking: display 2D graphics in Virtua Racing (the game is however still unplayable)
|
||||||
|
* added support for more internal IO registers: fixe some unlicensed games (Wisdom Tree games...)
|
||||||
|
* added preliminary support for unmapped protection device: fix some unlicensed games with special built-in hardware (Squirell King, Lion King 2...)
|
||||||
|
* added "Soft Reset" combo (in game, use L+Z triggers): this should be like pressing the RESET button on a real Genesis and this is required
|
||||||
|
in some games to enable special features or even complete the game (ex: X-Men).
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* added separate configuration for PortA/PortB inputs (GAMEPAD, MULTITAP or NONE, see Joypad Config): this let you setting
|
||||||
|
PORTB as unplugged, which is needed in some games to access special modes or enable cheat codes (Alien Storm, X-Men...)
|
||||||
|
* Freezestate & SRAM files are now compressed (using zlib)
|
||||||
|
* FreezeState & SRAM files can now be saved/loaded to/from SDCARD: located in /genplus/saves/ from the root of your SDCARD
|
||||||
|
* changed initial ROMS directory for SDCARD user: now looking for /genplus/roms/ from the root of your SDCARD
|
||||||
|
* added user-transparent SRAM autoload (detection order is MCARD then SDCARD, SLOTA then SLOTB)
|
||||||
|
* "System reboot" is now used for console reboot and SD/PSO reload (if detected)
|
||||||
|
* added new font: now use original IPL font, extracted from Bootrom
|
||||||
|
* modified controls when going into the rom selection menu (DVD or SDCARD):
|
||||||
|
. use B button to go up one directory
|
||||||
|
. use Z button to quit the file selection menu
|
||||||
|
. use L/R triggers to go down/up one full page
|
||||||
|
. use Left/Right buttons or Analog stick to scroll the selected entry's filename when it can't be full displayed
|
||||||
|
* various menu rearrangment, minor bugfixes & sourcecode cleanup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070621 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* added Multitap support (EA 4-Way Play and Sega Teamplayer): allowed up to four players in games supporting those peripherals
|
||||||
|
* added partial Sega Menacer lightgun support: automatically set when detecting the 6-in-1 Menacer game
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* added 4.7GB DVD support for WII drives (the maximal allowed size for Gamecube DVD is still 1.35GB)
|
||||||
|
* removed MPAL video timings, always use 60Hz NTSC: fix display problems for PAL wii users (no more PAL50 version needed)
|
||||||
|
* added Console Reboot option in main menu (IPL Reboot)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070518 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* you can now switch between FM cores without reseting the game. FM registers value are automatically restored when switching.
|
||||||
|
* removed the previous VINT timings modification because it brokes some games (Rocket Knight, Thunderforce III,...)
|
||||||
|
* added automatic Timing configuration (VDP latency, VINT timing & alternate Line Timing) at game loading, based upon specific romname detection.
|
||||||
|
This means you can still modify some of these options afterwards but they are now automatically set/unset when loading a game which need
|
||||||
|
special timing fixes. These fixes are also automatically desactivated when the current game doesn't need them.
|
||||||
|
For information, games that are actually detected and need special timings to run properly are:
|
||||||
|
.Legend of Galahad & Road Rash series (single line not rendered properly)
|
||||||
|
.Sesame Street Counting Cafe (don't boot)
|
||||||
|
.Chaos Engine/Soldiers of Fortune (graphic glitches on scrolling)
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* modified PAL framesync a little bit: the 20ms period is now applied between the start of 2 consecutive frames,
|
||||||
|
no more between the end of the previous and the start of the next one, which seems more correct to me
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070508 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* VINT timings are now a little more accurate: fixes Sesame's Street Counting Cafe
|
||||||
|
* SN76496 MAX_OUTPUT back to normal
|
||||||
|
* modified FB_WNOISE value in SN76496 core according to John Kortink's last informations
|
||||||
|
* added support for Maxim's PSG core, same as used in SMSPLUS (it becomes the default PSG core)
|
||||||
|
* updated FM core to the latest MAME version
|
||||||
|
* corrected DAC output level (fixes voices and some special FX being too low)
|
||||||
|
* added support for Gens YM2612 (FM) core (MAME's one still remains default FM core)
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* corrected L & R buttons assignment: fixes Genesis X & Z buttons being inverted
|
||||||
|
* added configurable preamplification for each sound cores (see Emulator Options)
|
||||||
|
* added some other configurable sound options (boost overall volume, FM improvment for Gens YM2612)
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070411 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* corrected MAX_OUTPUT value in SN76496 core: fix PSG sound (SFX) volume
|
||||||
|
* removed unused sound buffer allocation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070326 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* added DVD automount: automatically call libogc DVD_Mount function if ISO PVD reading failed (idea taken from softdev's last neocdredux release). This may be useful for loading roms from a DVD after booting from SDLOAD or after stopping DVD motor.
|
||||||
|
* added "DVD motor off" feature, like in others emulators
|
||||||
|
* corrected Memory Card mounting function: EXI_ProbeReset() function was never called if the first mounting attempt failed. Should fix some of the "Unable to mount memory card" errors.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070322 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* added SDCARD subdirectory browsing and LFN (255 char. max) support
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070317 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* Color RAM update now always reset color 0 to border color (fix color glitches in Mortal Kombat,...) (thanks to Noop's for the idea)
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* remove some rendering unused code (only used by DOS version of genesis plus) for little speedup
|
||||||
|
* added an option to enable alternate line rendering timing (fix single line error in Road Rash series and Legend of Galahad's Intro)
|
||||||
|
* added last Softdev's modifications (normalised memory access and ASM GU functions used intead of 'C' ones) for some speedup
|
||||||
|
* updated gcaram.c to be compatible with last libogc version
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070309 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* little rendering code speedups
|
||||||
|
* modified HV counter tables (fix graphic glitches in Skitchin's sky, Lotus 2 Recs, Panorama Cotton, Dashin Desperados & maybe more)
|
||||||
|
* completely rewrote DMA timings emulation so that it works for all games (no more cpu freezing)
|
||||||
|
* added all DMA tranfer rates handling for each three DMA modes and added dma busy flag emulation
|
||||||
|
* modified interrupts handling on VDP register #0 and #1 writes (fix Lemmings status bar)
|
||||||
|
* added VDP RAM write latency (fix Chaos Engine/Soldier of Fortune gfx glitches)
|
||||||
|
* modified FM timers handling a bit (fix Vectorman2 music)
|
||||||
|
* corrected Sprite Limit rendering (fix Sonic 1 & Micromachines 2 title screens)
|
||||||
|
* corrected IO Registers writes (fix Decap' Attack controls, no more need for alternate input)
|
||||||
|
* corrected 6 Buttons Pad emulation (fix 6buttons detection in Mortal Kombat 3, Comix Zone and other 6-buttons compatible games)
|
||||||
|
* modified sound mixing a bit according to Generator sourcecode (FM and PSG ratios seems more correct)
|
||||||
|
* added separate CPU Region (USA, Europe, Japan,...) & Speed (PAL or NTSC) choice in menu options
|
||||||
|
* modified main frame synchro in PAL mode (fix sound glitch in this mode), thanks to Softdev for the solution
|
||||||
|
* added savestates support (go to SRAM menu, memory card supports only)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX release 070207 (Eke-Eke)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* fm timers fixed (fix missing music in Castle of Illusion, Quackshot, Undead Line, Wonderboy in Monster Lair, Cal 50, Turbo Outrun, Thundeforce 4 and maybe more)
|
||||||
|
* added complete EEPROM emulation (save support now works fine in Wonderboy5, Megaman Willy Wars, NBA Jam...) (credits to Notaz, adapted from Picodrive code)
|
||||||
|
* added preliminar dma timing emulation (fix bottom screen in Legend of Galahad) (credits to Notaz, adapted from Picodrive code)
|
||||||
|
* hack: clear Vint pending after Hint (INT level 4) acknowledge (fix Fatal Rewind)
|
||||||
|
* hack: modify read_bus16 to return a random value (fake fetch) (fix Time Killers)
|
||||||
|
* modified cpu execution timings, with more correct hblank and interrupts timing (fix ISS Deluxe, Double Dragon 2 and certainly more) (Based on Gens code)
|
||||||
|
* modified busreq mechanism: better synchro between z80 & 68k (no need to dejitter anymore) (Based on Gens code)
|
||||||
|
* added sprite collision detection (fix Strider 2)
|
||||||
|
* modified dma fill operation for big endian platform (fix Contra Hardcorps gfx garbage)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX WIP 1.2 (Softdev)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* Added partial zip support (unzip.c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX WIP 1.1 (Softdev)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* sio.c added
|
||||||
|
* Added six button pad support from x86 Gens
|
||||||
|
* Additional changes based on Charles MacDonald's gen-hw.txt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX WIP 1 - 7 March 2006 (Softdev)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Core]
|
||||||
|
|
||||||
|
* Updated SN76496 driver
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* Added GX Hardware Scaling
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
Genesis Plus GX WIP 0 (Softdev)
|
||||||
|
---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[Gamecube]
|
||||||
|
|
||||||
|
* initial port based on Genesis Plus 1.2a from Charles McDonald (http://cgfm2.emuviews.com/)
|
440
LICENSE.txt
Normal file
@ -0,0 +1,440 @@
|
|||||||
|
MAME License:
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Redistribution and use of this code or any derivative works are permitted
|
||||||
|
provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions may not be sold, nor may they be used in a commercial
|
||||||
|
product or activity.
|
||||||
|
|
||||||
|
* Redistributions that are modified from the original source must include the
|
||||||
|
complete source code, including the source code for all components used by a
|
||||||
|
binary built from the modified sources. However, as a special exception, the
|
||||||
|
source code distributed need not include anything that is normally distributed
|
||||||
|
(in either source or binary form) with the major components (compiler, kernel,
|
||||||
|
and so on) of the operating system on which the executable runs, unless that
|
||||||
|
component itself accompanies the executable.
|
||||||
|
|
||||||
|
* Redistributions must reproduce the above copyright notice, this list of
|
||||||
|
conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LIBTREMOR license:
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Copyright (c) 2002, Xiph.org Foundation
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ASNDLIB License:
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
conditions and the following disclaimer.
|
||||||
|
- Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
- The names of the contributors may not be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GNU License:
|
||||||
|
------------
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
148
Makefile.gc
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/gamecube_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := genplus_cube
|
||||||
|
BUILD := build_cube
|
||||||
|
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
|
||||||
|
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds
|
||||||
|
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
|
||||||
|
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds \
|
||||||
|
$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DALT_RENDERER -DNGC -DHW_DOL
|
||||||
|
CXXFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
|
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -lpng -lfat -liso9660 -lvorbisidec -lasnd -logc -lm -lz
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
|
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
||||||
|
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
export LD := $(CC)
|
||||||
|
else
|
||||||
|
export LD := $(CXX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(PNGFILES:.png=.png.o) $(PCMFILES:.pcm=.pcm.o) $(OGGFILES:.ogg=.ogg.o) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
|
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of include paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD) \
|
||||||
|
-I$(LIBOGC_INC) -I$(PORTLIBS)/include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||||
|
-L$(LIBOGC_LIB)
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.gc
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT).dol: $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# This rule links in binary data with the various extension
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.jpg.o : %.jpg
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.png.o : %.png
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.pcm.o : %.pcm
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.ogg.o : %.ogg
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
148
Makefile.wii
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# Clear the implicit built in rules
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITPPC)),)
|
||||||
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := genplus_wii
|
||||||
|
BUILD := build_wii
|
||||||
|
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
|
||||||
|
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds
|
||||||
|
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
|
||||||
|
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds \
|
||||||
|
$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DALT_RENDERER -DNGC -DHW_RVL
|
||||||
|
CXXFLAGS = $(CFLAGS)
|
||||||
|
|
||||||
|
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -lpng -ldi -lfat -liso9660 -lvorbisidec -lasnd -lwiiuse -lbte -logc -lm -lz
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# automatically build a list of object files for our project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
|
PCMFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pcm)))
|
||||||
|
OGGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.ogg)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
export LD := $(CC)
|
||||||
|
else
|
||||||
|
export LD := $(CXX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(PNGFILES:.png=.png.o) $(PCMFILES:.pcm=.pcm.o) $(OGGFILES:.ogg=.ogg.o) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
||||||
|
$(sFILES:.s=.o) $(SFILES:.S=.o)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of include paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD) \
|
||||||
|
-I$(LIBOGC_INC) -I$(PORTLIBS)/include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# build a list of library paths
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
||||||
|
-L$(LIBOGC_LIB)
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.wii
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT).dol: $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf: $(OFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# This rule links in binary data with the various extension
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.jpg.o : %.jpg
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.png.o : %.png
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.pcm.o : %.pcm
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
%.ogg.o : %.ogg
|
||||||
|
@echo $(notdir $<)
|
||||||
|
$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
5
compile_all.bat
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
make -f Makefile.wii
|
||||||
|
make -f Makefile.gc
|
||||||
|
rm *.elf
|
||||||
|
cp genplus_wii.dol boot.dol
|
||||||
|
pause
|
3
pcutil/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
inject: inject.c
|
||||||
|
@gcc -O2 -Wall inject.c -o inject
|
||||||
|
@strip inject
|
154
pcutil/inject.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus 1.04
|
||||||
|
*
|
||||||
|
* Developer ROM injector.
|
||||||
|
*
|
||||||
|
* You should set ROMOFFSET to match ngc.c, as this will change as the
|
||||||
|
* binary expands and/or contracts.
|
||||||
|
****************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define DOLHEADERLENGTH 256 // GC DOL Header Length
|
||||||
|
#define MAXTEXT 7 // Maximum 7 Text Sections
|
||||||
|
#define MAXDATA 11 // Maximum 11 Data Sections
|
||||||
|
|
||||||
|
struct DOLHEADER{
|
||||||
|
unsigned int textOffsets[MAXTEXT];
|
||||||
|
unsigned int dataOffsets[MAXDATA];
|
||||||
|
|
||||||
|
unsigned int textAddress[MAXTEXT];
|
||||||
|
unsigned int dataAddress[MAXDATA];
|
||||||
|
|
||||||
|
unsigned int textLength[MAXTEXT];
|
||||||
|
unsigned int dataLength[MAXDATA];
|
||||||
|
|
||||||
|
unsigned int bssAddress;
|
||||||
|
unsigned int bssLength;
|
||||||
|
|
||||||
|
unsigned int entryPoint;
|
||||||
|
unsigned int unused[MAXTEXT];
|
||||||
|
} dolheader;
|
||||||
|
|
||||||
|
unsigned int FLIP32(unsigned int b)
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
|
||||||
|
c = ( b & 0xff000000 ) >> 24;
|
||||||
|
c |= ( b & 0xff0000 ) >> 8;
|
||||||
|
c |= ( b & 0xff00 ) << 8;
|
||||||
|
c |= ( b & 0xff ) << 24;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ROMOFFSET 0x80700000
|
||||||
|
|
||||||
|
int main( int argc, char *argv[] )
|
||||||
|
{
|
||||||
|
FILE *infile, *outfile;
|
||||||
|
char *dol;
|
||||||
|
char *rom;
|
||||||
|
int dollen, romlen, outlen;
|
||||||
|
char *sig = "GENPLUSR";
|
||||||
|
|
||||||
|
if ( argc != 4 )
|
||||||
|
{
|
||||||
|
printf("Usage : %s genplus.dol filename_of_your_rom.bin (or .smd) output.dol\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Try to open all three handles ***/
|
||||||
|
infile = fopen(argv[1], "rb");
|
||||||
|
if ( infile == NULL )
|
||||||
|
{
|
||||||
|
printf("Unable to open %s for reading\n", argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Allocate and load ***/
|
||||||
|
fseek(infile, 0, SEEK_END);
|
||||||
|
dollen=ftell(infile);
|
||||||
|
fseek(infile, 0, SEEK_SET);
|
||||||
|
|
||||||
|
dol = calloc(sizeof(char), dollen + 32);
|
||||||
|
|
||||||
|
if ( fread(dol, 1, dollen, infile ) != dollen )
|
||||||
|
{
|
||||||
|
free(dol);
|
||||||
|
printf("Error reading %s\n", argv[1]);
|
||||||
|
fclose(infile);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
infile = fopen(argv[2], "rb");
|
||||||
|
if ( infile == NULL )
|
||||||
|
{
|
||||||
|
printf("Unable to open %s for reading\n", argv[2]);
|
||||||
|
free(dol);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Allocate and load ***/
|
||||||
|
fseek( infile, 0, SEEK_END);
|
||||||
|
romlen = ftell(infile);
|
||||||
|
fseek( infile, 0, SEEK_SET);
|
||||||
|
rom = calloc( sizeof(char), romlen + 48 );
|
||||||
|
|
||||||
|
if ( fread(rom, 1, romlen, infile) != romlen )
|
||||||
|
{
|
||||||
|
printf("Error reading %s\n", argv[2]);
|
||||||
|
fclose(infile);
|
||||||
|
free(rom);
|
||||||
|
free(dol);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
/*** Ok, now have both in memory - so update the dol header and get this file done -;) ***/
|
||||||
|
memcpy(&dolheader, dol, DOLHEADERLENGTH);
|
||||||
|
|
||||||
|
/*** Align to 32 bytes - no real reason, I just like it -;) ***/
|
||||||
|
if ( dollen & 0x1f )
|
||||||
|
dollen = ( dollen & ~0x1f ) + 0x20;
|
||||||
|
|
||||||
|
dolheader.dataOffsets[1] = FLIP32(dollen);
|
||||||
|
dolheader.dataAddress[1] = FLIP32(ROMOFFSET);
|
||||||
|
dolheader.dataLength[1] = FLIP32(romlen + 32);
|
||||||
|
|
||||||
|
/*** Move the updated header back ***/
|
||||||
|
memcpy(dol, &dolheader, DOLHEADERLENGTH);
|
||||||
|
|
||||||
|
outfile = fopen(argv[3], "wb");
|
||||||
|
if ( outfile == NULL )
|
||||||
|
{
|
||||||
|
printf("Unable to open %s for writing!\n", argv[3]);
|
||||||
|
free(rom);
|
||||||
|
free(dol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Now simply update the files ***/
|
||||||
|
fwrite(dol, 1, dollen, outfile);
|
||||||
|
fwrite(sig, 1, 8, outfile);
|
||||||
|
|
||||||
|
outlen = FLIP32(romlen);
|
||||||
|
fwrite(&outlen, 1, 4, outfile);
|
||||||
|
|
||||||
|
char align[32];
|
||||||
|
memset(align, 0, 32);
|
||||||
|
fwrite(align, 1, 20, outfile);
|
||||||
|
fwrite(rom, 1, romlen, outfile);
|
||||||
|
fclose(outfile);
|
||||||
|
|
||||||
|
free(dol);
|
||||||
|
free(rom);
|
||||||
|
|
||||||
|
printf("Output file %s created successfully\n", argv[3]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
BIN
pcutil/injectlnx
Normal file
302
source/cart_hw/areplay.c
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Action Replay / Pro Action Replay emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
#define TYPE_PRO1 0x12
|
||||||
|
#define TYPE_PRO2 0x22
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint8 enabled;
|
||||||
|
uint8 status;
|
||||||
|
uint8 *rom;
|
||||||
|
uint8 *ram;
|
||||||
|
uint16 regs[13];
|
||||||
|
uint16 old[4];
|
||||||
|
uint16 data[4];
|
||||||
|
uint32 addr[4];
|
||||||
|
} action_replay;
|
||||||
|
|
||||||
|
static void ar_write_regs(uint32 address, uint32 data);
|
||||||
|
static void ar_write_regs_2(uint32 address, uint32 data);
|
||||||
|
static void ar_write_ram_8(uint32 address, uint32 data);
|
||||||
|
|
||||||
|
void areplay_init(void)
|
||||||
|
{
|
||||||
|
memset(&action_replay,0,sizeof(action_replay));
|
||||||
|
if (cart.romsize > 0x800000) return;
|
||||||
|
|
||||||
|
/* Open Action Replay ROM */
|
||||||
|
FILE *f = fopen(AR_ROM,"rb");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
/* store Action replay ROM + RAM above cartridge ROM + SRAM */
|
||||||
|
action_replay.rom = cart.rom + 0x800000;
|
||||||
|
action_replay.ram = cart.rom + 0x810000;
|
||||||
|
|
||||||
|
/* ROM size */
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
int size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* detect Action Replay board type */
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 0x8000:
|
||||||
|
{
|
||||||
|
/* normal Action Replay (32K) */
|
||||||
|
action_replay.enabled = TYPE_AR;
|
||||||
|
|
||||||
|
/* internal registers mapped at $010000-$01ffff */
|
||||||
|
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x10000:
|
||||||
|
case 0x20000:
|
||||||
|
{
|
||||||
|
/* read Stack Pointer */
|
||||||
|
uint8 sp[4];
|
||||||
|
fread(&sp, 4, 1, f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* Detect board version */
|
||||||
|
if (sp[1] == 0x42)
|
||||||
|
{
|
||||||
|
/* PRO Action Replay 1 (64/128K) */
|
||||||
|
action_replay.enabled = TYPE_PRO1;
|
||||||
|
|
||||||
|
/* internal registers mapped at $010000-$01ffff */
|
||||||
|
m68k_memory_map[0x01].write16 = ar_write_regs;
|
||||||
|
}
|
||||||
|
else if (sp[1] == 0x60)
|
||||||
|
{
|
||||||
|
/* PRO Action Replay 2 (64K) */
|
||||||
|
action_replay.enabled = TYPE_PRO2;
|
||||||
|
|
||||||
|
/* internal registers mapped at $100000-$10ffff */
|
||||||
|
m68k_memory_map[0x10].write16 = ar_write_regs_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* internal RAM (64k), mapped at $420000-$42ffff or $600000-$60ffff */
|
||||||
|
if (action_replay.enabled)
|
||||||
|
{
|
||||||
|
m68k_memory_map[sp[1]].base = action_replay.ram;
|
||||||
|
m68k_memory_map[sp[1]].read8 = NULL;
|
||||||
|
m68k_memory_map[sp[1]].read16 = NULL;
|
||||||
|
m68k_memory_map[sp[1]].write8 = ar_write_ram_8;
|
||||||
|
m68k_memory_map[sp[1]].write16 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action_replay.enabled)
|
||||||
|
{
|
||||||
|
/* Load ROM */
|
||||||
|
int i = 0;
|
||||||
|
while (i < size)
|
||||||
|
{
|
||||||
|
fread(action_replay.rom+i,0x1000,1,f);
|
||||||
|
i += 0x1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LSB_FIRST
|
||||||
|
/* Byteswap ROM */
|
||||||
|
uint8 temp;
|
||||||
|
for(i = 0; i < size; i += 2)
|
||||||
|
{
|
||||||
|
temp = action_replay.rom[i];
|
||||||
|
action_replay.rom[i] = action_replay.rom[i+1];
|
||||||
|
action_replay.rom[i+1] = temp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void areplay_shutdown(void)
|
||||||
|
{
|
||||||
|
/* clear existing patches */
|
||||||
|
areplay_set_status(AR_SWITCH_OFF);
|
||||||
|
|
||||||
|
/* disable device by default */
|
||||||
|
action_replay.enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void areplay_reset(int hard)
|
||||||
|
{
|
||||||
|
if (action_replay.enabled)
|
||||||
|
{
|
||||||
|
if (hard || (action_replay.status == AR_SWITCH_TRAINER))
|
||||||
|
{
|
||||||
|
/* reset internal registers */
|
||||||
|
memset(action_replay.regs, 0, sizeof(action_replay.regs));
|
||||||
|
memset(action_replay.old, 0, sizeof(action_replay.old));
|
||||||
|
memset(action_replay.data, 0, sizeof(action_replay.data));
|
||||||
|
memset(action_replay.addr, 0, sizeof(action_replay.addr));
|
||||||
|
|
||||||
|
/* by default, internal ROM is mapped at $000000-$00FFFF */
|
||||||
|
m68k_memory_map[0].base = action_replay.rom;
|
||||||
|
|
||||||
|
/* reset internal RAM on power-on */
|
||||||
|
if (hard)
|
||||||
|
{
|
||||||
|
memset(action_replay.ram,0xff,0x10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int areplay_get_status(void)
|
||||||
|
{
|
||||||
|
if (action_replay.enabled)
|
||||||
|
{
|
||||||
|
return action_replay.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void areplay_set_status(int status)
|
||||||
|
{
|
||||||
|
if (action_replay.enabled)
|
||||||
|
{
|
||||||
|
/* no Trainer mode for normal Action Replay */
|
||||||
|
if ((action_replay.enabled == TYPE_AR) && (status == AR_SWITCH_TRAINER))
|
||||||
|
{
|
||||||
|
status = AR_SWITCH_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check status changes */
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case AR_SWITCH_OFF:
|
||||||
|
case AR_SWITCH_TRAINER:
|
||||||
|
{
|
||||||
|
/* check that patches were previously enabled */
|
||||||
|
if (action_replay.status == AR_SWITCH_ON)
|
||||||
|
{
|
||||||
|
/* restore original data */
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[0]) = action_replay.old[0];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[1]) = action_replay.old[1];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[2]) = action_replay.old[2];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[3]) = action_replay.old[3];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case AR_SWITCH_ON:
|
||||||
|
{
|
||||||
|
/* check that patches were previously disabled */
|
||||||
|
if (action_replay.status != AR_SWITCH_ON)
|
||||||
|
{
|
||||||
|
/* decode patch data */
|
||||||
|
action_replay.data[0] = action_replay.regs[0];
|
||||||
|
action_replay.data[1] = action_replay.regs[4];
|
||||||
|
action_replay.data[2] = action_replay.regs[7];
|
||||||
|
action_replay.data[3] = action_replay.regs[10];
|
||||||
|
|
||||||
|
/* decode patch address ($000000-$7fffff) */
|
||||||
|
action_replay.addr[0] = (action_replay.regs[1] | ((action_replay.regs[2] & 0x3f00) << 8)) << 1;
|
||||||
|
action_replay.addr[1] = (action_replay.regs[5] | ((action_replay.regs[6] & 0x3f00) << 8)) << 1;
|
||||||
|
action_replay.addr[2] = (action_replay.regs[8] | ((action_replay.regs[9] & 0x3f00) << 8)) << 1;
|
||||||
|
action_replay.addr[3] = (action_replay.regs[11] | ((action_replay.regs[12] & 0x3f00) << 8)) << 1;
|
||||||
|
|
||||||
|
/* save original data */
|
||||||
|
action_replay.old[0] = *(uint16 *)(cart.rom + action_replay.addr[0]);
|
||||||
|
action_replay.old[1] = *(uint16 *)(cart.rom + action_replay.addr[1]);
|
||||||
|
action_replay.old[2] = *(uint16 *)(cart.rom + action_replay.addr[2]);
|
||||||
|
action_replay.old[3] = *(uint16 *)(cart.rom + action_replay.addr[3]);
|
||||||
|
|
||||||
|
/* patch new data */
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[0]) = action_replay.data[0];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[1]) = action_replay.data[1];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[2]) = action_replay.data[2];
|
||||||
|
*(uint16 *)(cart.rom + action_replay.addr[3]) = action_replay.data[3];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update status */
|
||||||
|
action_replay.status = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ar_write_regs(uint32 address, uint32 data)
|
||||||
|
{
|
||||||
|
/* register offset */
|
||||||
|
int offset = (address & 0xffff) >> 1;
|
||||||
|
if (offset > 12)
|
||||||
|
{
|
||||||
|
m68k_unused_16_w(address,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update internal register */
|
||||||
|
action_replay.regs[offset] = data;
|
||||||
|
|
||||||
|
/* MODE register */
|
||||||
|
if (action_replay.regs[3] == 0xffff)
|
||||||
|
{
|
||||||
|
/* check switch status */
|
||||||
|
if (action_replay.status == AR_SWITCH_ON)
|
||||||
|
{
|
||||||
|
/* reset existing patches */
|
||||||
|
areplay_set_status(AR_SWITCH_OFF);
|
||||||
|
areplay_set_status(AR_SWITCH_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable Cartridge ROM */
|
||||||
|
m68k_memory_map[0].base = cart.rom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ar_write_regs_2(uint32 address, uint32 data)
|
||||||
|
{
|
||||||
|
/* enable Cartridge ROM */
|
||||||
|
if (((address & 0xff) == 0x78) && (data == 0xffff))
|
||||||
|
{
|
||||||
|
m68k_memory_map[0].base = cart.rom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ar_write_ram_8(uint32 address, uint32 data)
|
||||||
|
{
|
||||||
|
/* byte writes are handled as word writes, with LSB duplicated in MSB (/LWR is not used) */
|
||||||
|
*(uint16 *)(action_replay.ram + (address & 0xfffe)) = (data | (data << 8));
|
||||||
|
}
|
||||||
|
|
35
source/cart_hw/areplay.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* DATEL Action Replay / Pro Action Replay emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _AREPLAY_H_
|
||||||
|
#define _AREPLAY_H_
|
||||||
|
|
||||||
|
#define AR_SWITCH_OFF (0)
|
||||||
|
#define AR_SWITCH_ON (1)
|
||||||
|
#define AR_SWITCH_TRAINER (2)
|
||||||
|
|
||||||
|
extern void areplay_init(void);
|
||||||
|
extern void areplay_shutdown(void);
|
||||||
|
extern void areplay_reset(int hard);
|
||||||
|
extern void areplay_set_status(int status);
|
||||||
|
extern int areplay_get_status(void);
|
||||||
|
|
||||||
|
#endif
|
462
source/cart_hw/eeprom.c
Normal file
@ -0,0 +1,462 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* I2C EEPROM support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
#define GAME_CNT 30
|
||||||
|
|
||||||
|
T_EEPROM eeprom;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char game_id[16];
|
||||||
|
uint16 chk;
|
||||||
|
T_EEPROM_TYPE type;
|
||||||
|
} T_GAME_ENTRY;
|
||||||
|
|
||||||
|
static const T_GAME_ENTRY database[GAME_CNT] =
|
||||||
|
{
|
||||||
|
/* ACCLAIM mappers */
|
||||||
|
/* 24C02 (old mapper) */
|
||||||
|
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
|
||||||
|
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
|
||||||
|
/* 24C02 */
|
||||||
|
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
|
||||||
|
/* 24C04 */
|
||||||
|
{{"T-81406" }, 0, {8, 0x1FF, 0x1FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
|
||||||
|
/* 24C16 */
|
||||||
|
{{"T-081586" }, 0, {8, 0x7FF, 0x7FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club '96 */
|
||||||
|
/* 24C65 */
|
||||||
|
{{"T-81576" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* College Slam */
|
||||||
|
{{"T-81476" }, 0, {16, 0x1FFF, 0x1FFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* Frank Thomas Big Hurt Baseball */
|
||||||
|
|
||||||
|
/* EA mapper (24C01 only) */
|
||||||
|
{{"T-50176" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Rings of Power */
|
||||||
|
{{"T-50396" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* NHLPA Hockey 93 */
|
||||||
|
{{"T-50446" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* John Madden Football 93 */
|
||||||
|
{{"T-50516" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* John Madden Football 93 (Championship Ed.) */
|
||||||
|
{{"T-50606" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 7, 7, 6}}, /* Bill Walsh College Football */
|
||||||
|
|
||||||
|
/* SEGA mapper (24C01 only) */
|
||||||
|
{{"T-12046" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Megaman - The Wily Wars */
|
||||||
|
{{"T-12053" }, 0xEA80, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Rockman Mega World (J) [A] */
|
||||||
|
{{"MK-1215" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Evander 'Real Deal' Holyfield's Boxing */
|
||||||
|
{{"MK-1228" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (U) */
|
||||||
|
{{"G-5538" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (J) */
|
||||||
|
{{"PR-1993" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Greatest Heavyweights of the Ring (E) */
|
||||||
|
{{"G-4060" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Wonderboy in Monster World */
|
||||||
|
{{"00001211-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Sports Talk Baseball */
|
||||||
|
{{"00004076-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Honoo no Toukyuuji Dodge Danpei */
|
||||||
|
{{"G-4524" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Ninja Burai Densetsu */
|
||||||
|
{{"00054503-00"}, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Game Toshokan */
|
||||||
|
|
||||||
|
/* CODEMASTERS mapper */
|
||||||
|
/* 24C08 */
|
||||||
|
{{"T-120106" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
|
||||||
|
{{"00000000-00"}, 0x168B, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
|
||||||
|
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military (Bad)*/
|
||||||
|
/* 24C16 */
|
||||||
|
{{"T-120096" }, 0, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament (E) */
|
||||||
|
{{"00000000-00"}, 0x165E, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 */
|
||||||
|
{{"00000000-00"}, 0x2C41, {8, 0x7FF, 0x7FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Turbo Tournament 96 (Bad)*/
|
||||||
|
/* 24C65 */
|
||||||
|
{{"T-120146-50"}, 0, {16, 0x1FFF, 0x1FFF, 0x300000, 0x380001, 0x300000, 0, 7, 1}} /* Brian Lara Cricket 96, Shane Warne Cricket */
|
||||||
|
};
|
||||||
|
|
||||||
|
void eeprom_init()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* initialize eeprom */
|
||||||
|
memset(&eeprom, 0, sizeof(T_EEPROM));
|
||||||
|
eeprom.sda = eeprom.old_sda = 1;
|
||||||
|
eeprom.scl = eeprom.old_scl = 1;
|
||||||
|
eeprom.state = STAND_BY;
|
||||||
|
|
||||||
|
/* no eeprom by default */
|
||||||
|
sram.custom = 0;
|
||||||
|
|
||||||
|
/* look into game database */
|
||||||
|
while (i<GAME_CNT)
|
||||||
|
{
|
||||||
|
if (strstr(rominfo.product,database[i].game_id) != NULL)
|
||||||
|
{
|
||||||
|
/* additional check (Micro Machines, Rockman Mega World) */
|
||||||
|
if ((database[i].chk == 0) || (database[i].chk == rominfo.checksum))
|
||||||
|
{
|
||||||
|
sram.custom = 1;
|
||||||
|
sram.on = 1;
|
||||||
|
memcpy(&eeprom.type, &database[i].type, sizeof(T_EEPROM_TYPE));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Game not found in database but header seems to indicate it uses EEPROM */
|
||||||
|
if (sram.detected)
|
||||||
|
{
|
||||||
|
if ((sram.end - sram.start) < 2)
|
||||||
|
{
|
||||||
|
/* set SEGA mapper as default */
|
||||||
|
sram.custom = 1;
|
||||||
|
memcpy(&eeprom.type, &database[9].type, sizeof(T_EEPROM_TYPE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Detect_START()
|
||||||
|
{
|
||||||
|
if (eeprom.old_scl && eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.old_sda && !eeprom.sda)
|
||||||
|
{
|
||||||
|
eeprom.cycles = 0;
|
||||||
|
eeprom.slave_mask = 0;
|
||||||
|
if (eeprom.type.address_bits == 7)
|
||||||
|
{
|
||||||
|
eeprom.word_address = 0;
|
||||||
|
eeprom.state = GET_WORD_ADR_7BITS;
|
||||||
|
}
|
||||||
|
else eeprom.state = GET_SLAVE_ADR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Detect_STOP()
|
||||||
|
{
|
||||||
|
if (eeprom.old_scl && eeprom.scl)
|
||||||
|
{
|
||||||
|
if (!eeprom.old_sda && eeprom.sda)
|
||||||
|
{
|
||||||
|
eeprom.state = STAND_BY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeprom_write(unsigned int address, unsigned int data, int word_access)
|
||||||
|
{
|
||||||
|
/* decode SCL and SDA value */
|
||||||
|
if (word_access)
|
||||||
|
{
|
||||||
|
/* 16-bits access */
|
||||||
|
if (eeprom.type.sda_in_adr == address) eeprom.sda = (data >> (8 + eeprom.type.sda_in_bit)) & 1; /* MSB */
|
||||||
|
else if (eeprom.type.sda_in_adr == (address | 1)) eeprom.sda = (data >> eeprom.type.sda_in_bit) & 1; /* LSB */
|
||||||
|
else eeprom.sda = eeprom.old_sda;
|
||||||
|
|
||||||
|
if (eeprom.type.scl_adr == address) eeprom.scl = (data >> (8 + eeprom.type.scl_bit)) & 1; /* MSB */
|
||||||
|
else if (eeprom.type.scl_adr == (address | 1)) eeprom.scl = (data >> eeprom.type.scl_bit) & 1; /* LSB */
|
||||||
|
else eeprom.scl = eeprom.old_scl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (eeprom.type.sda_in_adr == address) eeprom.sda = (data >> eeprom.type.sda_in_bit) & 1;
|
||||||
|
else eeprom.sda = eeprom.old_sda;
|
||||||
|
|
||||||
|
if (eeprom.type.scl_adr == address) eeprom.scl = (data >> eeprom.type.scl_bit) & 1;
|
||||||
|
else eeprom.scl = eeprom.old_scl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EEPROM current state */
|
||||||
|
switch (eeprom.state)
|
||||||
|
{
|
||||||
|
/* Standby Mode */
|
||||||
|
case STAND_BY:
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Suspended Mode */
|
||||||
|
case WAIT_STOP:
|
||||||
|
Detect_STOP();
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Word Address 7 bits: MODE-1 only (24C01)
|
||||||
|
* and R/W bit
|
||||||
|
*/
|
||||||
|
case GET_WORD_ADR_7BITS:
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL LOW to HIGH transition */
|
||||||
|
if (!eeprom.old_scl && eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||||
|
{
|
||||||
|
if (eeprom.cycles < 8)
|
||||||
|
{
|
||||||
|
eeprom.word_address |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||||
|
}
|
||||||
|
else if (eeprom.cycles == 8)
|
||||||
|
{
|
||||||
|
eeprom.rw = eeprom.old_sda;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* ACK CYCLE */
|
||||||
|
eeprom.cycles = 0;
|
||||||
|
eeprom.word_address &= eeprom.type.size_mask;
|
||||||
|
eeprom.state = eeprom.rw ? READ_DATA : WRITE_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/* Get Slave Address (3bits) : MODE-2 & MODE-3 only (24C01 - 24C512) (0-3bits, depending on the array size)
|
||||||
|
* or/and Word Address MSB: MODE-2 only (24C04 - 24C16) (0-3bits, depending on the array size)
|
||||||
|
* and R/W bit
|
||||||
|
*/
|
||||||
|
case GET_SLAVE_ADR:
|
||||||
|
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL LOW to HIGH transition */
|
||||||
|
if (!eeprom.old_scl && eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles == 0) eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl && (eeprom.cycles > 0))
|
||||||
|
{
|
||||||
|
if ((eeprom.cycles > 4) && (eeprom.cycles <8))
|
||||||
|
{
|
||||||
|
if ((eeprom.type.address_bits == 16) ||
|
||||||
|
(eeprom.type.size_mask < (1 << (15 - eeprom.cycles))))
|
||||||
|
{
|
||||||
|
/* this is a SLAVE ADDRESS bit */
|
||||||
|
eeprom.slave_mask |= (eeprom.old_sda << (7 - eeprom.cycles));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is a WORD ADDRESS high bit */
|
||||||
|
if (eeprom.old_sda) eeprom.word_address |= (1 << (15 - eeprom.cycles));
|
||||||
|
else eeprom.word_address &= ~(1 << (15 - eeprom.cycles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eeprom.cycles == 8) eeprom.rw = eeprom.old_sda;
|
||||||
|
else if (eeprom.cycles > 8)
|
||||||
|
{
|
||||||
|
/* ACK CYCLE */
|
||||||
|
eeprom.cycles = 0;
|
||||||
|
if (eeprom.type.address_bits == 16)
|
||||||
|
{
|
||||||
|
/* two ADDRESS bytes */
|
||||||
|
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_HIGH;
|
||||||
|
eeprom.slave_mask <<= 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* one ADDRESS byte */
|
||||||
|
eeprom.state = eeprom.rw ? READ_DATA : GET_WORD_ADR_LOW;
|
||||||
|
eeprom.slave_mask <<= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get Word Address MSB (4-8bits depending on the array size)
|
||||||
|
* MODE-3 only (24C32 - 24C512)
|
||||||
|
*/
|
||||||
|
case GET_WORD_ADR_HIGH:
|
||||||
|
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles < 9)
|
||||||
|
{
|
||||||
|
if ((eeprom.type.size_mask + 1) < (1 << (17 - eeprom.cycles)))
|
||||||
|
{
|
||||||
|
/* ignored bit: slave mask should be right-shifted by one */
|
||||||
|
eeprom.slave_mask >>= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is a WORD ADDRESS high bit */
|
||||||
|
if (eeprom.old_sda) eeprom.word_address |= (1 << (16 - eeprom.cycles));
|
||||||
|
else eeprom.word_address &= ~(1 << (16 - eeprom.cycles));
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* ACK CYCLE */
|
||||||
|
eeprom.cycles = 1;
|
||||||
|
eeprom.state = GET_WORD_ADR_LOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/* Get Word Address LSB: 7bits (24C01) or 8bits (24C02-24C512)
|
||||||
|
* MODE-2 and MODE-3 only (24C01 - 24C512)
|
||||||
|
*/
|
||||||
|
case GET_WORD_ADR_LOW:
|
||||||
|
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles < 9)
|
||||||
|
{
|
||||||
|
if ((eeprom.type.size_mask + 1) < (1 << (9 - eeprom.cycles)))
|
||||||
|
{
|
||||||
|
/* ignored bit (X24C01): slave mask should be right-shifted by one */
|
||||||
|
eeprom.slave_mask >>= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is a WORD ADDRESS high bit */
|
||||||
|
if (eeprom.old_sda) eeprom.word_address |= (1 << (8 - eeprom.cycles));
|
||||||
|
else eeprom.word_address &= ~(1 << (8 - eeprom.cycles));
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* ACK CYCLE */
|
||||||
|
eeprom.cycles = 1;
|
||||||
|
eeprom.word_address &= eeprom.type.size_mask;
|
||||||
|
eeprom.state = WRITE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read Cycle
|
||||||
|
*/
|
||||||
|
case READ_DATA:
|
||||||
|
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles < 9) eeprom.cycles ++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eeprom.cycles = 1;
|
||||||
|
|
||||||
|
/* ACK not received */
|
||||||
|
if (eeprom.old_sda) eeprom.state = WAIT_STOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write Cycle
|
||||||
|
*/
|
||||||
|
case WRITE_DATA:
|
||||||
|
|
||||||
|
Detect_START();
|
||||||
|
Detect_STOP();
|
||||||
|
|
||||||
|
/* look for SCL HIGH to LOW transition */
|
||||||
|
if (eeprom.old_scl && !eeprom.scl)
|
||||||
|
{
|
||||||
|
if (eeprom.cycles < 9)
|
||||||
|
{
|
||||||
|
/* Write DATA bits (max 64kBytes) */
|
||||||
|
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xFFFF;
|
||||||
|
if (eeprom.old_sda) sram.sram[sram_address] |= (1 << (8 - eeprom.cycles));
|
||||||
|
else sram.sram[sram_address] &= ~(1 << (8 - eeprom.cycles));
|
||||||
|
|
||||||
|
if (eeprom.cycles == 8)
|
||||||
|
{
|
||||||
|
/* WORD ADDRESS is incremented (roll up at maximum pagesize) */
|
||||||
|
eeprom.word_address = (eeprom.word_address & (0xFFFF - eeprom.type.pagewrite_mask)) |
|
||||||
|
((eeprom.word_address + 1) & eeprom.type.pagewrite_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.cycles ++;
|
||||||
|
}
|
||||||
|
else eeprom.cycles = 1; /* ACK cycle */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
eeprom.old_scl = eeprom.scl;
|
||||||
|
eeprom.old_sda = eeprom.sda;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int eeprom_read(int word_access)
|
||||||
|
{
|
||||||
|
uint8 sda_out = eeprom.sda;
|
||||||
|
|
||||||
|
/* EEPROM state */
|
||||||
|
switch (eeprom.state)
|
||||||
|
{
|
||||||
|
case READ_DATA:
|
||||||
|
if (eeprom.cycles < 9)
|
||||||
|
{
|
||||||
|
/* Return DATA bits (max 64kBytes) */
|
||||||
|
uint16 sram_address = (eeprom.slave_mask | eeprom.word_address) & 0xffff;
|
||||||
|
sda_out = (sram.sram[sram_address] >> (8 - eeprom.cycles)) & 1;
|
||||||
|
|
||||||
|
if (eeprom.cycles == 8)
|
||||||
|
{
|
||||||
|
/* WORD ADDRESS is incremented (roll up at maximum array size) */
|
||||||
|
eeprom.word_address ++;
|
||||||
|
eeprom.word_address &= eeprom.type.size_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GET_WORD_ADR_7BITS:
|
||||||
|
case GET_SLAVE_ADR:
|
||||||
|
case GET_WORD_ADR_HIGH:
|
||||||
|
case GET_WORD_ADR_LOW:
|
||||||
|
case WRITE_DATA:
|
||||||
|
if (eeprom.cycles == 9) sda_out = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* memory access */
|
||||||
|
if (word_access)
|
||||||
|
{
|
||||||
|
/* 16-bits access */
|
||||||
|
if (eeprom.type.sda_out_adr & 1) return (sda_out << eeprom.type.sda_out_bit); /* LSB */
|
||||||
|
else return (sda_out << (eeprom.type.sda_out_bit + 8)); /* MSB */
|
||||||
|
}
|
||||||
|
else return (sda_out << eeprom.type.sda_out_bit);
|
||||||
|
}
|
92
source/cart_hw/eeprom.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* I2C EEPROM support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _EEPROM_H_
|
||||||
|
#define _EEPROM_H_
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STAND_BY = 0,
|
||||||
|
WAIT_STOP,
|
||||||
|
GET_SLAVE_ADR,
|
||||||
|
GET_WORD_ADR_7BITS,
|
||||||
|
GET_WORD_ADR_HIGH,
|
||||||
|
GET_WORD_ADR_LOW,
|
||||||
|
WRITE_DATA,
|
||||||
|
READ_DATA,
|
||||||
|
|
||||||
|
} T_EEPROM_STATE;
|
||||||
|
|
||||||
|
/* this defines the type of EEPROM inside the game cartridge as Backup RAM
|
||||||
|
*
|
||||||
|
* Here are some notes from 8BitWizard (http://www.spritesmind.net/_GenDev/forum):
|
||||||
|
*
|
||||||
|
* Mode 1 (7-bit) - the chip takes a single byte with a 7-bit memory address and a R/W bit (24C01)
|
||||||
|
* Mode 2 (8-bit) - the chip takes a 7-bit device address and R/W bit followed by an 8-bit memory address;
|
||||||
|
* the device address may contain up to three more memory address bits (24C01 - 24C16).
|
||||||
|
* You can also string eight 24C01, four 24C02, two 24C08, or various combinations, set their address config lines correctly,
|
||||||
|
* and the result appears exactly the same as a 24C16
|
||||||
|
* Mode 3 (16-bit) - the chip takes a 7-bit device address and R/W bit followed by a 16-bit memory address (24C32 and larger)
|
||||||
|
*
|
||||||
|
* Also, while most 24Cxx are addressed at 200000-2FFFFF, I have found two different ways of mapping the control lines.
|
||||||
|
* EA uses SDA on D7 (read/write) and SCL on D6 (write only), and I have found boards using different mapping (I think Accolade)
|
||||||
|
* which uses D1-read=SDA, D0-write=SDA, D1-write=SCL. Accolade also has a custom-chip mapper which may even use a third method.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 address_bits; /* number of bits needed to address memory: 7, 8 or 16 */
|
||||||
|
uint16 size_mask; /* depends on the max size of the memory (in bytes) */
|
||||||
|
uint16 pagewrite_mask; /* depends on the maximal number of bytes that can be written in a single write cycle */
|
||||||
|
uint32 sda_in_adr; /* 68000 memory address mapped to SDA_IN */
|
||||||
|
uint32 sda_out_adr; /* 68000 memory address mapped to SDA_OUT */
|
||||||
|
uint32 scl_adr; /* 68000 memory address mapped to SCL */
|
||||||
|
uint8 sda_in_bit; /* bit offset for SDA_IN */
|
||||||
|
uint8 sda_out_bit; /* bit offset for SDA_OUT */
|
||||||
|
uint8 scl_bit; /* bit offset for SCL */
|
||||||
|
|
||||||
|
} T_EEPROM_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 sda; /* current /SDA line state */
|
||||||
|
uint8 scl; /* current /SCL line state */
|
||||||
|
uint8 old_sda; /* previous /SDA line state */
|
||||||
|
uint8 old_scl; /* previous /SCL line state */
|
||||||
|
uint8 cycles; /* current operation cycle number (0-9) */
|
||||||
|
uint8 rw; /* operation type (1:READ, 0:WRITE) */
|
||||||
|
uint16 slave_mask; /* device address (shifted by the memory address width)*/
|
||||||
|
uint16 word_address; /* memory address */
|
||||||
|
T_EEPROM_STATE state; /* current operation state */
|
||||||
|
T_EEPROM_TYPE type; /* EEPROM characteristics for this game */
|
||||||
|
|
||||||
|
} T_EEPROM;
|
||||||
|
|
||||||
|
/* global variables */
|
||||||
|
extern T_EEPROM eeprom;
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void eeprom_init();
|
||||||
|
extern void eeprom_write(unsigned int address, unsigned int data, int word_access);
|
||||||
|
extern unsigned int eeprom_read(int word_access);
|
||||||
|
|
||||||
|
#endif
|
264
source/cart_hw/ggenie.c
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Game Genie Hardware emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* Based on documentation from Charles McDonald
|
||||||
|
* (http://cgfm2.emuviews.com/txt/genie.txt)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint8 enabled;
|
||||||
|
uint8 *rom;
|
||||||
|
uint16 regs[0x20];
|
||||||
|
uint16 old[6];
|
||||||
|
uint16 data[6];
|
||||||
|
uint32 addr[6];
|
||||||
|
} ggenie;
|
||||||
|
|
||||||
|
static unsigned int ggenie_read_byte(unsigned int address);
|
||||||
|
static unsigned int ggenie_read_word(unsigned int address);
|
||||||
|
static void ggenie_write_byte(unsigned int address, unsigned int data);
|
||||||
|
static void ggenie_write_word(unsigned int address, unsigned int data);
|
||||||
|
static void ggenie_write_regs(unsigned int offset, unsigned int data);
|
||||||
|
|
||||||
|
void ggenie_init(void)
|
||||||
|
{
|
||||||
|
memset(&ggenie,0,sizeof(ggenie));
|
||||||
|
|
||||||
|
/* Open Game Genie ROM */
|
||||||
|
FILE *f = fopen(GG_ROM,"rb");
|
||||||
|
if (!f) return;
|
||||||
|
|
||||||
|
/* store Game Genie ROM above cartridge ROM + SRAM */
|
||||||
|
if (cart.romsize > 0x600000) return;
|
||||||
|
ggenie.rom = cart.rom + 0x600000;
|
||||||
|
|
||||||
|
/* Load ROM */
|
||||||
|
int i = 0;
|
||||||
|
while (i < 0x8000)
|
||||||
|
{
|
||||||
|
fread(ggenie.rom+i,0x1000,1,f);
|
||||||
|
i += 0x1000;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
#ifdef LSB_FIRST
|
||||||
|
/* Byteswap ROM */
|
||||||
|
uint8 temp;
|
||||||
|
for(i = 0; i < 0x8000; i += 2)
|
||||||
|
{
|
||||||
|
temp = ggenie.rom[i];
|
||||||
|
ggenie.rom[i] = ggenie.rom[i+1];
|
||||||
|
ggenie.rom[i+1] = temp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* $0000-$7fff mirrored into $8000-$ffff */
|
||||||
|
memcpy(ggenie.rom+0x8000,ggenie.rom,0x8000);
|
||||||
|
|
||||||
|
/* set flag */
|
||||||
|
ggenie.enabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ggenie_shutdown(void)
|
||||||
|
{
|
||||||
|
if (ggenie.enabled)
|
||||||
|
{
|
||||||
|
ggenie_switch(0);
|
||||||
|
ggenie.enabled = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ggenie_reset(int hard)
|
||||||
|
{
|
||||||
|
if (ggenie.enabled)
|
||||||
|
{
|
||||||
|
if (hard)
|
||||||
|
{
|
||||||
|
/* clear codes */
|
||||||
|
ggenie_switch(0);
|
||||||
|
|
||||||
|
/* reset internal state */
|
||||||
|
memset(ggenie.regs,0,sizeof(ggenie.regs));
|
||||||
|
memset(ggenie.old,0,sizeof(ggenie.old));
|
||||||
|
memset(ggenie.data,0,sizeof(ggenie.data));
|
||||||
|
memset(ggenie.addr,0,sizeof(ggenie.addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Game Genie ROM is mapped at $000000-$007fff */
|
||||||
|
m68k_memory_map[0].base = ggenie.rom;
|
||||||
|
|
||||||
|
/* Internal registers are mapped at $000000-$00001f */
|
||||||
|
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||||
|
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||||
|
|
||||||
|
/* Disable registers reads */
|
||||||
|
m68k_memory_map[0].read16 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ggenie_switch(int enable)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
/* enable cheats */
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
/* patch is enabled ? */
|
||||||
|
if (ggenie.regs[0] & (1 << i))
|
||||||
|
{
|
||||||
|
/* save old value and patch ROM if enabled */
|
||||||
|
ggenie.old[i] = *(uint16 *)(cart.rom + ggenie.addr[i]);
|
||||||
|
*(uint16 *)(cart.rom + ggenie.addr[i]) = ggenie.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* disable cheats in reversed order in case the same address is used by multiple patches */
|
||||||
|
for (i=5; i>=0; i--)
|
||||||
|
{
|
||||||
|
/* patch is enabled ? */
|
||||||
|
if (ggenie.regs[0] & (1 << i))
|
||||||
|
{
|
||||||
|
/* restore original ROM value */
|
||||||
|
*(uint16 *)(cart.rom + ggenie.addr[i]) = ggenie.old[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int ggenie_read_byte(unsigned int address)
|
||||||
|
{
|
||||||
|
unsigned int data = ggenie.regs[(address >> 1) & 0x1f];
|
||||||
|
return ((address & 1) ? (data & 0xff) : ((data >> 8) & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int ggenie_read_word(unsigned int address)
|
||||||
|
{
|
||||||
|
return ggenie.regs[(address >> 1) & 0x1f];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ggenie_write_byte(unsigned int address, unsigned int data)
|
||||||
|
{
|
||||||
|
/* Register offset */
|
||||||
|
uint8 offset = (address >> 1) & 0x1f;
|
||||||
|
|
||||||
|
/* /LWR and /UWR are used to decode writes */
|
||||||
|
if (address & 1)
|
||||||
|
{
|
||||||
|
data = (ggenie.regs[offset] & 0xff00) | (data & 0xff);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = (ggenie.regs[offset] & 0x00ff) | ((data & 0xff) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update internal register */
|
||||||
|
ggenie_write_regs(offset,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ggenie_write_word(unsigned int address, unsigned int data)
|
||||||
|
{
|
||||||
|
/* Register offset */
|
||||||
|
uint8 offset = (address >> 1) & 0x1f;
|
||||||
|
|
||||||
|
/* Write internal register (full WORD) */
|
||||||
|
ggenie_write_regs(offset,data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ggenie_write_regs(unsigned int offset, unsigned int data)
|
||||||
|
{
|
||||||
|
/* update internal register */
|
||||||
|
ggenie.regs[offset] = data;
|
||||||
|
|
||||||
|
/* Mode Register */
|
||||||
|
if (offset == 0)
|
||||||
|
{
|
||||||
|
/* MODE bit */
|
||||||
|
if (data & 0x400)
|
||||||
|
{
|
||||||
|
/* $0000-$7ffff reads mapped to Cartridge ROM */
|
||||||
|
m68k_memory_map[0].base = cart.rom;
|
||||||
|
m68k_memory_map[0].read8 = NULL;
|
||||||
|
m68k_memory_map[0].read16 = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* $0000-$7ffff reads mapped to Game Genie ROM */
|
||||||
|
m68k_memory_map[0].base = ggenie.rom;
|
||||||
|
m68k_memory_map[0].read8 = NULL;
|
||||||
|
m68k_memory_map[0].read16 = NULL;
|
||||||
|
|
||||||
|
/* READ_ENABLE bit */
|
||||||
|
if (data & 0x200)
|
||||||
|
{
|
||||||
|
/* $0000-$7ffff reads mapped to Game Genie Registers */
|
||||||
|
/* code doing this should execute in RAM so we don't need to modify base address */
|
||||||
|
m68k_memory_map[0].read8 = ggenie_read_byte;
|
||||||
|
m68k_memory_map[0].read16 = ggenie_read_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LOCK bit */
|
||||||
|
if (data & 0x100)
|
||||||
|
{
|
||||||
|
/* decode patch address (ROM area only)*/
|
||||||
|
/* note: Charles's doc is wrong, first register holds bits 23-16 of patch address */
|
||||||
|
ggenie.addr[0] = ((ggenie.regs[2] & 0x3f) << 16) | ggenie.regs[3];
|
||||||
|
ggenie.addr[1] = ((ggenie.regs[5] & 0x3f) << 16) | ggenie.regs[6];
|
||||||
|
ggenie.addr[2] = ((ggenie.regs[8] & 0x3f) << 16) | ggenie.regs[9];
|
||||||
|
ggenie.addr[3] = ((ggenie.regs[11] & 0x3f) << 16) | ggenie.regs[12];
|
||||||
|
ggenie.addr[4] = ((ggenie.regs[14] & 0x3f) << 16) | ggenie.regs[15];
|
||||||
|
ggenie.addr[5] = ((ggenie.regs[17] & 0x3f) << 16) | ggenie.regs[18];
|
||||||
|
|
||||||
|
/* decode patch data */
|
||||||
|
ggenie.data[0] = ggenie.regs[4];
|
||||||
|
ggenie.data[1] = ggenie.regs[7];
|
||||||
|
ggenie.data[2] = ggenie.regs[10];
|
||||||
|
ggenie.data[3] = ggenie.regs[13];
|
||||||
|
ggenie.data[4] = ggenie.regs[16];
|
||||||
|
ggenie.data[5] = ggenie.regs[19];
|
||||||
|
|
||||||
|
/* disable internal registers */
|
||||||
|
m68k_memory_map[0].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0].write16 = m68k_unused_16_w;
|
||||||
|
|
||||||
|
/* patch ROM when GG program exits (LOCK bit set) */
|
||||||
|
/* this is done here to handle patched program reads faster & more easily */
|
||||||
|
/* on real HW, address decoding would be done on each reads */
|
||||||
|
ggenie_switch(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m68k_memory_map[0].write8 = ggenie_write_byte;
|
||||||
|
m68k_memory_map[0].write16 = ggenie_write_word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RESET register */
|
||||||
|
else if (offset == 1)
|
||||||
|
{
|
||||||
|
ggenie.regs[1] |= 1;
|
||||||
|
}
|
||||||
|
}
|
34
source/cart_hw/ggenie.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Game Genie Hardware emulation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* Based on documentation from Charles McDonald
|
||||||
|
* (http://cgfm2.emuviews.com/txt/genie.txt)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GGENIE_H_
|
||||||
|
#define _GGENIE_H_
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void ggenie_init(void);
|
||||||
|
extern void ggenie_shutdown(void);
|
||||||
|
extern void ggenie_reset(int hard);
|
||||||
|
extern void ggenie_switch(int enable);
|
||||||
|
|
||||||
|
#endif
|
1185
source/cart_hw/md_cart.c
Normal file
75
source/cart_hw/md_cart.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Mega Drive cartridge hardware support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007-2011 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* Lots of protection mechanism have been discovered by Haze
|
||||||
|
* (http://haze.mameworld.info/)
|
||||||
|
*
|
||||||
|
* Realtec mapper has been figured out by TascoDeluxe
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _MD_CART_H_
|
||||||
|
#define _MD_CART_H_
|
||||||
|
|
||||||
|
/* Lock-On cartridge type */
|
||||||
|
#define TYPE_GG 0x01 /* Game Genie */
|
||||||
|
#define TYPE_AR 0x02 /* (Pro) Action Replay */
|
||||||
|
#define TYPE_SK 0x03 /* Sonic & Knuckles */
|
||||||
|
|
||||||
|
/* Special hardware (0x01 reserved for SMS 3-D glasses) */
|
||||||
|
#define HW_J_CART 0x02
|
||||||
|
#define HW_LOCK_ON 0x04
|
||||||
|
|
||||||
|
/* Cartridge extra hardware */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 regs[4]; /* internal registers (R/W) */
|
||||||
|
uint32 mask[4]; /* registers address mask */
|
||||||
|
uint32 addr[4]; /* registers address */
|
||||||
|
uint16 realtec; /* realtec mapper */
|
||||||
|
uint16 bankshift; /* cartridge with bankshift mecanism reseted on software reset */
|
||||||
|
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
|
||||||
|
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
|
||||||
|
unsigned int (*regs_r)(unsigned int address); /* cart hardware registers read handler */
|
||||||
|
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware registers write handler */
|
||||||
|
} T_CART_HW;
|
||||||
|
|
||||||
|
/* Cartridge type */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 *rom; /* ROM area */
|
||||||
|
uint8 *base; /* ROM base (saved for OS/Cartridge ROM swap) */
|
||||||
|
uint32 romsize; /* ROM size */
|
||||||
|
uint32 mask; /* ROM mask */
|
||||||
|
uint8 special; /* Lock-On, J-Cart or SMS 3-D glasses hardware */
|
||||||
|
T_CART_HW hw; /* Extra mapping hardware */
|
||||||
|
} T_CART;
|
||||||
|
|
||||||
|
/* global variables */
|
||||||
|
extern T_CART cart;
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void md_cart_init(void);
|
||||||
|
extern void md_cart_reset(int hard_reset);
|
||||||
|
extern int md_cart_context_save(uint8 *state);
|
||||||
|
extern int md_cart_context_load(uint8 *state);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
631
source/cart_hw/sms_cart.c
Normal file
@ -0,0 +1,631 @@
|
|||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Master System cartridge hardware support
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998-2007 Charles MacDonald (SMS Plus original code)
|
||||||
|
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
|
||||||
|
*
|
||||||
|
* Most cartridge protections documented by Haze
|
||||||
|
* (http://haze.mameworld.info/)
|
||||||
|
*
|
||||||
|
* Realtec mapper documented by TascoDeluxe
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
#define MAPPER_NONE (0)
|
||||||
|
#define MAPPER_SEGA (1)
|
||||||
|
#define MAPPER_CODIES (2)
|
||||||
|
#define MAPPER_KOREA (3)
|
||||||
|
#define MAPPER_MSX (4)
|
||||||
|
|
||||||
|
#define GAME_DATABASE_CNT (75)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32 crc;
|
||||||
|
uint8 glasses_3d;
|
||||||
|
uint8 peripheral;
|
||||||
|
uint8 mapper;
|
||||||
|
uint8 region;
|
||||||
|
} rominfo_t;
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
uint8 fcr[4];
|
||||||
|
uint8 mapper;
|
||||||
|
} slot;
|
||||||
|
|
||||||
|
/* SMS game database */
|
||||||
|
static const rominfo_t game_list[GAME_DATABASE_CNT] =
|
||||||
|
{
|
||||||
|
/* games requiring CODEMASTER mapper (NOTE: extended video modes don't work on Genesis VDP !) */
|
||||||
|
{0x29822980, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Cosmic Spacehead */
|
||||||
|
{0xA577CE46, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines */
|
||||||
|
{0xF7C524F6, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines [BAD DUMP] */
|
||||||
|
{0xDBE8895C, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines 2 - Turbo Tournament */
|
||||||
|
{0xC1756BEE, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Pete Sampras Tennis */
|
||||||
|
{0x8813514B, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Excellent Dizzy Collection, The [Proto] */
|
||||||
|
{0xEA5C3A6F, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Dinobasher - Starring Bignose the Caveman [Proto] */
|
||||||
|
{0x152F0DCC, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Drop Zone" */
|
||||||
|
{0xAA140C9C, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Excellent Dizzy Collection, The [SMS-GG] */
|
||||||
|
{0xB9664AE1, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Fantastic Dizzy */
|
||||||
|
{0xC888222B, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Fantastic Dizzy [SMS-GG] */
|
||||||
|
{0x76C5BDFB, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Jang Pung 2 [SMS-GG] */
|
||||||
|
{0xD9A7F170, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Man Overboard! */
|
||||||
|
|
||||||
|
/* games requiring KOREA mappers (NOTE: TMS9918 video modes don't work on Genesis VDP !) */
|
||||||
|
{0x17AB6883, 0, SYSTEM_MS_GAMEPAD, MAPPER_NONE, REGION_JAPAN_NTSC}, /* FA Tetris (KR) */
|
||||||
|
{0x61E8806F, 0, SYSTEM_MS_GAMEPAD, MAPPER_NONE, REGION_JAPAN_NTSC}, /* Flash Point (KR) */
|
||||||
|
{0x445525E2, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */
|
||||||
|
{0x83F0EEDE, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Street Master (KR) */
|
||||||
|
{0xA05258F5, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Won-Si-In (KR) */
|
||||||
|
{0x06965ED9, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */
|
||||||
|
{0x89B79E77, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */
|
||||||
|
{0x18FB98A3, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */
|
||||||
|
{0x97D03541, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR)"} */
|
||||||
|
{0x67C2F0FF, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Super Boy 2 (KR) */
|
||||||
|
|
||||||
|
/* games requiring PAL timings */
|
||||||
|
{0x72420F38, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Addams Familly */
|
||||||
|
{0x2D48C1D3, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Back to the Future Part III */
|
||||||
|
{0x1CBB7BF1, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Battlemaniacs (BR) */
|
||||||
|
{0x1B10A951, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Bram Stoker's Dracula */
|
||||||
|
{0xC0E25D62, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* California Games II */
|
||||||
|
{0x45C50294, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Jogos de Verao II (BR) */
|
||||||
|
{0xC9DBF936, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Home Alone */
|
||||||
|
{0x0047B615, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Predator2 */
|
||||||
|
{0xF42E145C, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Quest for the Shaven Yak Starring Ren Hoek & Stimpy (BR) */
|
||||||
|
{0x9F951756, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* RoboCop 3 */
|
||||||
|
{0xF8176918, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sensible Soccer */
|
||||||
|
{0x1575581D, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Shadow of the Beast */
|
||||||
|
{0x96B3F29E, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic Blast (BR) */
|
||||||
|
{0x5B3B922C, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic the Hedgehog 2 [V0] */
|
||||||
|
{0xD6F2BFCA, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic the Hedgehog 2 [V1] */
|
||||||
|
{0xCA1D3752, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Space Harrier [50 Hz] */
|
||||||
|
{0x85CFC9C9, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Taito Chase H.Q. */
|
||||||
|
|
||||||
|
/* games requiring 3-D Glasses */
|
||||||
|
{0x871562b0, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Maze Walker */
|
||||||
|
{0x156948f9, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Space Harrier 3-D (J) */
|
||||||
|
{0x6BD5C2BF, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Space Harrier 3-D */
|
||||||
|
{0x8ECD201C, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D */
|
||||||
|
{0xFBF96C81, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D (BR) */
|
||||||
|
{0x58D5FC48, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D [Proto] */
|
||||||
|
{0x31B8040B, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Maze Hunter 3-D */
|
||||||
|
{0xABD48AD2, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Poseidon Wars 3-D */
|
||||||
|
{0xA3EF13CB, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Zaxxon 3-D */
|
||||||
|
{0xBBA74147, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Zaxxon 3-D [Proto] */
|
||||||
|
{0xD6F43DDA, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Out Run 3-D */
|
||||||
|
|
||||||
|
/* games requiring 3-D Glasses & Sega Light Phaser */
|
||||||
|
{0xFBE5CFBB, 1, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Missile Defense 3D */
|
||||||
|
{0xE79BB689, 1, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Missile Defense 3D [BIOS] */
|
||||||
|
|
||||||
|
/* games requiring Sega Light Phaser */
|
||||||
|
{0x861B6E79, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Assault City [Light Phaser] */
|
||||||
|
{0x5FC74D2A, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Gangster Town */
|
||||||
|
{0xE167A561, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt */
|
||||||
|
{0xC5083000, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt [BAD DUMP] */
|
||||||
|
{0x91E93385, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt [BIOS] */
|
||||||
|
{0xE8EA842C, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Marksman Shooting / Trap Shooting */
|
||||||
|
{0xE8215C2E, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Marksman Shooting / Trap Shooting / Safari Hunt */
|
||||||
|
{0x205CAAE8, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Operation Wolf (can be played with gamepad in port B)*/
|
||||||
|
{0x23283F37, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Operation Wolf [A] (can be played with gamepad in port B) */
|
||||||
|
{0xDA5A7013, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Rambo 3 */
|
||||||
|
{0x79AC8E7F, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Rescue Mission */
|
||||||
|
{0x4B051022, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Shooting Gallery */
|
||||||
|
{0xA908CFF5, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Spacegun */
|
||||||
|
{0x5359762D, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Wanted */
|
||||||
|
{0x0CA95637, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Laser Ghost */
|
||||||
|
|
||||||
|
/* games requiring Sega Paddle */
|
||||||
|
{0xF9DBB533, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Alex Kidd BMX Trial */
|
||||||
|
{0xA6FA42D0, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Galactic Protector */
|
||||||
|
{0x29BC7FAD, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Megumi Rescue */
|
||||||
|
{0x315917D4, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Woody Pop */
|
||||||
|
|
||||||
|
/* games requiring Sega Sport Pad */
|
||||||
|
{0x0CB7E21F, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA}, /* Great Ice Hockey */
|
||||||
|
{0xE42E4998, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA}, /* Sports Pad Football */
|
||||||
|
{0x41C948BF, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA} /* Sports Pad Soccer */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 1K trash buffer */
|
||||||
|
static uint8 dummy[0x400];
|
||||||
|
|
||||||
|
/* Function prorotypes */
|
||||||
|
static void mapper_8k_w(int offset, unsigned int data);
|
||||||
|
static void mapper_16k_w(int offset, unsigned int data);
|
||||||
|
static void write_mapper_none(unsigned int address, unsigned char data);
|
||||||
|
static void write_mapper_sega(unsigned int address, unsigned char data);
|
||||||
|
static void write_mapper_codies(unsigned int address, unsigned char data);
|
||||||
|
static void write_mapper_korea(unsigned int address, unsigned char data);
|
||||||
|
static void write_mapper_msx(unsigned int address, unsigned char data);
|
||||||
|
|
||||||
|
|
||||||
|
void sms_cart_init(void)
|
||||||
|
{
|
||||||
|
/* default mapper */
|
||||||
|
slot.mapper = MAPPER_SEGA;
|
||||||
|
|
||||||
|
/* default supported peripheral */
|
||||||
|
uint8 device = SYSTEM_MS_GAMEPAD;
|
||||||
|
cart.special = 0;
|
||||||
|
|
||||||
|
/* compute CRC */
|
||||||
|
uint32 crc = crc32(0, cart.rom, cart.romsize);
|
||||||
|
|
||||||
|
/* detect cartridge mapper */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<GAME_DATABASE_CNT; i++)
|
||||||
|
{
|
||||||
|
if (crc == game_list[i].crc)
|
||||||
|
{
|
||||||
|
cart.special = game_list[i].glasses_3d;
|
||||||
|
slot.mapper = game_list[i].mapper;
|
||||||
|
device = game_list[i].peripheral;
|
||||||
|
i = GAME_DATABASE_CNT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize Z80 write handler */
|
||||||
|
switch(slot.mapper)
|
||||||
|
{
|
||||||
|
case MAPPER_NONE:
|
||||||
|
z80_writemem = write_mapper_none;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAPPER_CODIES:
|
||||||
|
z80_writemem = write_mapper_codies;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAPPER_KOREA:
|
||||||
|
z80_writemem = write_mapper_korea;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MAPPER_MSX:
|
||||||
|
z80_writemem = write_mapper_msx;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
z80_writemem = write_mapper_sega;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize default SRAM (32K max.) */
|
||||||
|
sram_init();
|
||||||
|
|
||||||
|
/* restore previous input settings */
|
||||||
|
if (old_system[0] != -1)
|
||||||
|
{
|
||||||
|
input.system[0] = old_system[0];
|
||||||
|
}
|
||||||
|
if (old_system[1] != -1)
|
||||||
|
{
|
||||||
|
input.system[1] = old_system[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default gun offset */
|
||||||
|
input.x_offset = 20;
|
||||||
|
input.y_offset = 0;
|
||||||
|
|
||||||
|
/* detect if game requires specific peripheral */
|
||||||
|
if (device != SYSTEM_MS_GAMEPAD)
|
||||||
|
{
|
||||||
|
/* save port A setting */
|
||||||
|
if (old_system[0] == -1)
|
||||||
|
{
|
||||||
|
old_system[0] = input.system[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force port A configuration */
|
||||||
|
input.system[0] = device;
|
||||||
|
|
||||||
|
/* SpaceGun & Gangster Town use different gun offset */
|
||||||
|
if ((crc == 0x5359762D) || (crc == 0x5FC74D2A))
|
||||||
|
{
|
||||||
|
input.x_offset = 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sms_cart_reset(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Unmapped memory return $FF */
|
||||||
|
memset(dummy, 0xFF, 0x400);
|
||||||
|
|
||||||
|
/* Reset Z80 memory mapping at $0000-$BFFF (first 32k of ROM mirrored) */
|
||||||
|
for(i = 0x00; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(i & 0x1F) << 10];
|
||||||
|
z80_writemap[i] = dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset Z80 memory mapping at $C000-$FFFF (first 8K of 68k RAM mirrored) */
|
||||||
|
for(i = 0x30; i < 0x40; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x07) << 10];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset cartridge paging registers */
|
||||||
|
switch(slot.mapper)
|
||||||
|
{
|
||||||
|
case MAPPER_NONE:
|
||||||
|
case MAPPER_SEGA:
|
||||||
|
{
|
||||||
|
slot.fcr[0] = 0;
|
||||||
|
slot.fcr[1] = 0;
|
||||||
|
slot.fcr[2] = 1;
|
||||||
|
slot.fcr[3] = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
slot.fcr[0] = 0;
|
||||||
|
slot.fcr[1] = 0;
|
||||||
|
slot.fcr[2] = 1;
|
||||||
|
slot.fcr[3] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set default memory map */
|
||||||
|
if (slot.mapper != MAPPER_MSX)
|
||||||
|
{
|
||||||
|
mapper_16k_w(0,slot.fcr[0]);
|
||||||
|
mapper_16k_w(1,slot.fcr[1]);
|
||||||
|
mapper_16k_w(2,slot.fcr[2]);
|
||||||
|
mapper_16k_w(3,slot.fcr[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapper_8k_w(0,slot.fcr[0]);
|
||||||
|
mapper_8k_w(1,slot.fcr[1]);
|
||||||
|
mapper_8k_w(2,slot.fcr[2]);
|
||||||
|
mapper_8k_w(3,slot.fcr[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sms_cart_switch(int enabled)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
/* Enable cartdige ROM at $0000-$BFFF */
|
||||||
|
for(i = 0x00; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(i & 0x1F) << 10];
|
||||||
|
z80_writemap[i] = dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Disable cartridge ROM at $0000-$BFFF */
|
||||||
|
for(i = 0x00; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sms_cart_region_detect(void)
|
||||||
|
{
|
||||||
|
/* compute CRC */
|
||||||
|
uint32 crc = crc32(0, cart.rom, cart.romsize);
|
||||||
|
|
||||||
|
/* detect game region */
|
||||||
|
int i;
|
||||||
|
for (i=0; i<GAME_DATABASE_CNT; i++)
|
||||||
|
{
|
||||||
|
if (crc == game_list[i].crc)
|
||||||
|
{
|
||||||
|
return game_list[i].region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default region */
|
||||||
|
return REGION_USA;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sms_cart_context_save(uint8 *state)
|
||||||
|
{
|
||||||
|
int bufferptr = 0;
|
||||||
|
save_param(slot.fcr, sizeof(slot.fcr));
|
||||||
|
return bufferptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sms_cart_context_load(uint8 *state)
|
||||||
|
{
|
||||||
|
int bufferptr = 0;
|
||||||
|
load_param(slot.fcr, sizeof(slot.fcr));
|
||||||
|
|
||||||
|
/* Set default memory map */
|
||||||
|
if (slot.mapper != MAPPER_MSX)
|
||||||
|
{
|
||||||
|
mapper_16k_w(0,slot.fcr[0]);
|
||||||
|
mapper_16k_w(1,slot.fcr[1]);
|
||||||
|
mapper_16k_w(2,slot.fcr[2]);
|
||||||
|
mapper_16k_w(3,slot.fcr[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapper_8k_w(0,slot.fcr[0]);
|
||||||
|
mapper_8k_w(1,slot.fcr[1]);
|
||||||
|
mapper_8k_w(2,slot.fcr[2]);
|
||||||
|
mapper_8k_w(3,slot.fcr[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bufferptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mapper_8k_w(int offset, unsigned int data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* cartridge ROM page (8k) */
|
||||||
|
uint8 page = data % (cart.romsize >> 13);
|
||||||
|
|
||||||
|
/* Save frame control register data */
|
||||||
|
slot.fcr[offset] = data;
|
||||||
|
|
||||||
|
/* 4 x 8k banks */
|
||||||
|
switch (offset & 3)
|
||||||
|
{
|
||||||
|
case 0: /* cartridge ROM bank (8k) at $8000-$9FFF */
|
||||||
|
{
|
||||||
|
for(i = 0x20; i < 0x28; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: /* cartridge ROM bank (8k) at $A000-$BFFF */
|
||||||
|
{
|
||||||
|
for(i = 0x28; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2: /* cartridge ROM bank (8k) at $4000-$5FFF */
|
||||||
|
{
|
||||||
|
for(i = 0x10; i < 0x18; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: /* cartridge ROM bank (8k) at $6000-$7FFF */
|
||||||
|
{
|
||||||
|
for(i = 0x18; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapper_16k_w(int offset, unsigned int data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* cartridge ROM page (16k) */
|
||||||
|
uint8 page = data % (cart.romsize >> 14);
|
||||||
|
|
||||||
|
/* page index increment (SEGA mapper) */
|
||||||
|
if (slot.fcr[0] & 0x03)
|
||||||
|
{
|
||||||
|
page = (page + ((4 - (slot.fcr[0] & 0x03)) << 3)) % (cart.romsize >> 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save frame control register data */
|
||||||
|
slot.fcr[offset] = data;
|
||||||
|
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0: /* control register (SEGA mapper) */
|
||||||
|
{
|
||||||
|
if(data & 0x08)
|
||||||
|
{
|
||||||
|
/* external RAM (upper or lower 16K) mapped at $8000-$BFFF */
|
||||||
|
for(i = 0x20; i <= 0x2F; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = &sram.sram[((data & 0x04) << 12) + ((i & 0x0F) << 10)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* cartridge ROM page (16k) */
|
||||||
|
page = slot.fcr[3] % (cart.romsize >> 14);
|
||||||
|
|
||||||
|
/* page index increment (SEGA mapper) */
|
||||||
|
if (data & 0x03)
|
||||||
|
{
|
||||||
|
page = (page + ((4 - (data & 0x03)) << 3)) % (cart.romsize >> 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cartridge ROM mapped at $8000-$BFFF */
|
||||||
|
for(i = 0x20; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
z80_writemap[i] = dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data & 0x10)
|
||||||
|
{
|
||||||
|
/* external RAM (lower 16K) mapped at $C000-$FFFF */
|
||||||
|
for(i = 0x30; i < 0x40; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = &sram.sram[(i & 0x0F) << 10];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* internal RAM (8K mirrorred) mapped at $C000-$FFFF */
|
||||||
|
for(i = 0x30; i < 0x40; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x07) << 10];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: /* cartridge ROM bank (16k) at $0000-$3FFF */
|
||||||
|
{
|
||||||
|
/* first 1k is not fixed (CODEMASTER mapper) */
|
||||||
|
if (slot.mapper == MAPPER_CODIES)
|
||||||
|
{
|
||||||
|
z80_readmap[0] = &cart.rom[(page << 14)];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0x01; i < 0x10; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2: /* cartridge ROM bank (16k) at $4000-$7FFF */
|
||||||
|
{
|
||||||
|
for(i = 0x10; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ernie Elf's Golf external RAM switch */
|
||||||
|
if (slot.mapper == MAPPER_CODIES)
|
||||||
|
{
|
||||||
|
if (data & 0x80)
|
||||||
|
{
|
||||||
|
/* external RAM (8k) mapped at $A000-$BFFF */
|
||||||
|
for(i = 0x28; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = z80_writemap[i] = &sram.sram[(i & 0x0F) << 10];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* cartridge ROM page (16k) */
|
||||||
|
page = slot.fcr[3] % (cart.romsize >> 14);
|
||||||
|
|
||||||
|
/* cartridge ROM mapped at $A000-$BFFF */
|
||||||
|
for(i = 0x28; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
z80_writemap[i] = dummy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: /* cartridge ROM bank (16k) at $8000-$BFFF */
|
||||||
|
{
|
||||||
|
/* check that external RAM (16k) is not mapped at $8000-$BFFF (SEGA mapper) */
|
||||||
|
if ((slot.fcr[0] & 0x08)) break;
|
||||||
|
|
||||||
|
/* first 8k */
|
||||||
|
for(i = 0x20; i < 0x28; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that external RAM (8k) is not mapped at $A000-$BFFF (CODEMASTER mapper) */
|
||||||
|
if ((slot.mapper == MAPPER_CODIES) && (slot.fcr[2] & 0x80)) break;
|
||||||
|
|
||||||
|
/* last 8k */
|
||||||
|
for(i = 0x28; i < 0x30; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_mapper_none(unsigned int address, unsigned char data)
|
||||||
|
{
|
||||||
|
z80_writemap[address >> 10][address & 0x03FF] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_mapper_sega(unsigned int address, unsigned char data)
|
||||||
|
{
|
||||||
|
if(address >= 0xFFFC)
|
||||||
|
{
|
||||||
|
mapper_16k_w(address & 3, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
z80_writemap[address >> 10][address & 0x03FF] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_mapper_codies(unsigned int address, unsigned char data)
|
||||||
|
{
|
||||||
|
if (address == 0x0000)
|
||||||
|
{
|
||||||
|
mapper_16k_w(1,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address == 0x4000)
|
||||||
|
{
|
||||||
|
mapper_16k_w(2,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address == 0x8000)
|
||||||
|
{
|
||||||
|
mapper_16k_w(3,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
z80_writemap[address >> 10][address & 0x03FF] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_mapper_korea(unsigned int address, unsigned char data)
|
||||||
|
{
|
||||||
|
if (address == 0xA000)
|
||||||
|
{
|
||||||
|
mapper_16k_w(3,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
z80_writemap[address >> 10][address & 0x03FF] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_mapper_msx(unsigned int address, unsigned char data)
|
||||||
|
{
|
||||||
|
if (address <= 0x0003)
|
||||||
|
{
|
||||||
|
mapper_8k_w(address,data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
z80_writemap[address >> 10][address & 0x03FF] = data;
|
||||||
|
}
|
38
source/cart_hw/sms_cart.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Master System cartridge hardware support
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998-2007 Charles MacDonald (SMS Plus original code)
|
||||||
|
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
|
||||||
|
*
|
||||||
|
* Realtec mapper has been figured out by TascoDeluxe
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SMS_CART_H_
|
||||||
|
#define _SMS_CART_H_
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void sms_cart_init(void);
|
||||||
|
extern void sms_cart_reset(void);
|
||||||
|
extern void sms_cart_switch(int enabled);
|
||||||
|
extern int sms_cart_region_detect(void);
|
||||||
|
extern int sms_cart_context_save(uint8 *state);
|
||||||
|
extern int sms_cart_context_load(uint8 *state);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
140
source/cart_hw/sram.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/***************************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Backup RAM support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
T_SRAM sram;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* A quick guide to SRAM on the Genesis
|
||||||
|
*
|
||||||
|
* The SRAM definition is held at offset 0x1b0 of the ROM header.
|
||||||
|
*
|
||||||
|
* 1B0h: dc.b 'RA', %1x1yz000, %00100000
|
||||||
|
* 1B4h: dc.l RAM start address
|
||||||
|
* 1B8h: dc.l RAM end address
|
||||||
|
* x 1 for BACKUP and 0 If not BACKUP
|
||||||
|
* yz 10 if even address only
|
||||||
|
* 11 if odd address only
|
||||||
|
* 00 if both even and odd address
|
||||||
|
*
|
||||||
|
* Assuming max. 64k SRAM / Battery RAM throughout
|
||||||
|
****************************************************************************/
|
||||||
|
void sram_init()
|
||||||
|
{
|
||||||
|
memset (&sram, 0, sizeof (T_SRAM));
|
||||||
|
|
||||||
|
/* store SRAM into cartridge area */
|
||||||
|
if (cart.romsize > 0x500000) return;
|
||||||
|
sram.sram = cart.rom + 0x500000;
|
||||||
|
|
||||||
|
/* initialize SRAM */
|
||||||
|
memset(sram.sram, 0xff, 0x10000);
|
||||||
|
sram.crc = crc32(0, sram.sram, 0x10000);
|
||||||
|
|
||||||
|
/* retrieve informations from header */
|
||||||
|
if ((READ_BYTE(cart.rom,0x1b0) == 0x52) && (READ_BYTE(cart.rom,0x1b1) == 0x41))
|
||||||
|
{
|
||||||
|
sram.start = READ_WORD_LONG(cart.rom, 0x1b4);
|
||||||
|
sram.end = READ_WORD_LONG(cart.rom, 0x1b8);
|
||||||
|
|
||||||
|
/* fixe some bad header informations */
|
||||||
|
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
|
||||||
|
{
|
||||||
|
sram.end = sram.start + 0xffff;
|
||||||
|
}
|
||||||
|
sram.start &= 0xfffffffe;
|
||||||
|
sram.end |= 1;
|
||||||
|
|
||||||
|
/* enable SRAM */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.detected = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* default SRAM region */
|
||||||
|
sram.start = 0x200000;
|
||||||
|
sram.end = 0x20ffff;
|
||||||
|
|
||||||
|
/* enable SRAM only if ROM < 2MB */
|
||||||
|
if (cart.romsize <= sram.start)
|
||||||
|
sram.on = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* autodetect some games with bad header or specific configuration */
|
||||||
|
if (strstr(rominfo.product,"T-113016") != NULL)
|
||||||
|
{
|
||||||
|
/* Pugsy (try accessing unmapped area for copy protection) */
|
||||||
|
sram.on = 0;
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.international,"SONIC THE HEDGEHOG 2") != NULL)
|
||||||
|
{
|
||||||
|
/* Sonic the Hedgehog 2 does not use SRAM */
|
||||||
|
/* this prevents SRAM activation when using Sonic & Knuckles LOCK-ON feature */
|
||||||
|
sram.on = 0;
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.international,"SONIC & KNUCKLES") != NULL)
|
||||||
|
{
|
||||||
|
if (cart.romsize == 0x400000)
|
||||||
|
{
|
||||||
|
/* Sonic 3 & Knuckles */
|
||||||
|
/* the combined ROM has S&K header but should obviously use FRAM from Sonic the Hedgehog 3 */
|
||||||
|
sram.on = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.product,"T-26013") != NULL)
|
||||||
|
{
|
||||||
|
/* Psy-O-Blade (bad header) */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.start = 0x200001;
|
||||||
|
sram.end = 0x203fff;
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.product,"T-50086") != NULL)
|
||||||
|
{
|
||||||
|
/* PGA Tour Golf (no header) */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.start = 0x200001;
|
||||||
|
sram.end = 0x203fff;
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.product,"ACLD007") != NULL)
|
||||||
|
{
|
||||||
|
/* Winter Challenge (no header) */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.start = 0x200001;
|
||||||
|
sram.end = 0x200fff;
|
||||||
|
}
|
||||||
|
else if (strstr(rominfo.product,"T-50286") != NULL)
|
||||||
|
{
|
||||||
|
/* Buck Rogers - Countdown to Doomsday (no header) */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.start = 0x200001;
|
||||||
|
sram.end = 0x203fff;
|
||||||
|
}
|
||||||
|
else if (((rominfo.realchecksum == 0xaeaa) || (rominfo.realchecksum == 0x8dba)) &&
|
||||||
|
(rominfo.checksum == 0x8104))
|
||||||
|
{
|
||||||
|
/* Xin Qigai Wangzi, aka Beggar Prince (no header, use uncommon area) */
|
||||||
|
sram.on = 1;
|
||||||
|
sram.start = 0x400000;
|
||||||
|
sram.end = 0x40ffff;
|
||||||
|
}
|
||||||
|
}
|
43
source/cart_hw/sram.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/***************************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Backup RAM support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SRAM_H_
|
||||||
|
#define _SRAM_H_
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8 detected;
|
||||||
|
uint8 on;
|
||||||
|
uint8 custom;
|
||||||
|
uint32 start;
|
||||||
|
uint32 end;
|
||||||
|
uint32 crc;
|
||||||
|
uint8 *sram;
|
||||||
|
} T_SRAM;
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void sram_init ();
|
||||||
|
|
||||||
|
/* global variables */
|
||||||
|
extern T_SRAM sram;
|
||||||
|
|
||||||
|
#endif
|
68
source/cart_hw/svp/imageformat.txt
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
|
||||||
|
vscroll: 1 (0); 209 (26) - alternates every 4 frames
|
||||||
|
vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f; high 3980-999f)
|
||||||
|
name table address: c000
|
||||||
|
seen DMAs (in order):
|
||||||
|
[300002-3026c3]->[0020-26e1] len 4961
|
||||||
|
[3026c2-303943]->[26e0-3961] len 2369
|
||||||
|
[303942-306003]->[72e0-99a1] len 4961
|
||||||
|
---
|
||||||
|
[306002-3086c3]->[3980-6041] len 4961
|
||||||
|
[3086c2-309943]->[6040-72c1] len 2369
|
||||||
|
[309942-30c003]->[72e0-99a2] len 4961
|
||||||
|
tile arrangement:
|
||||||
|
|
||||||
|
000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||||
|
001: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||||
|
002: 001 003 005 007 009 00b 00d 00f 011 013 015 017 019 01b 01d 01f 021 023 025 027 029 02b 02d 02f 031 033 035 037 039 03b 03d 03f
|
||||||
|
003: 002 004 006 008 00a 00c 00e 010 012 014 016 018 01a 01c 01e 020 022 024 026 028 02a 02c 02e 030 032 034 036 038 03a 03c 03e 040
|
||||||
|
004: 041 043 045 047 049 04b 04d 04f 051 053 055 057 059 05b 05d 05f 061 063 065 067 069 06b 06d 06f 071 073 075 077 079 07b 07d 07f
|
||||||
|
005: 042 044 046 048 04a 04c 04e 050 052 054 056 058 05a 05c 05e 060 062 064 066 068 06a 06c 06e 070 072 074 076 078 07a 07c 07e 080
|
||||||
|
006: 081 083 085 087 089 08b 08d 08f 091 093 095 097 099 09b 09d 09f 0a1 0a3 0a5 0a7 0a9 0ab 0ad 0af 0b1 0b3 0b5 0b7 0b9 0bb 0bd 0bf
|
||||||
|
007: 082 084 086 088 08a 08c 08e 090 092 094 096 098 09a 09c 09e 0a0 0a2 0a4 0a6 0a8 0aa 0ac 0ae 0b0 0b2 0b4 0b6 0b8 0ba 0bc 0be 0c0
|
||||||
|
008: 0c1 0c3 0c5 0c7 0c9 0cb 0cd 0cf 0d1 0d3 0d5 0d7 0d9 0db 0dd 0df 0e1 0e3 0e5 0e7 0e9 0eb 0ed 0ef 0f1 0f3 0f5 0f7 0f9 0fb 0fd 0ff
|
||||||
|
009: 0c2 0c4 0c6 0c8 0ca 0cc 0ce 0d0 0d2 0d4 0d6 0d8 0da 0dc 0de 0e0 0e2 0e4 0e6 0e8 0ea 0ec 0ee 0f0 0f2 0f4 0f6 0f8 0fa 0fc 0fe 100
|
||||||
|
010: 101 103 105 107 109 10b 10d 10f 111 113 115 117 119 11b 11d 11f 121 123 125 127 129 12b 12d 12f 131 133 135 137 139 13b 13d 13f
|
||||||
|
011: 102 104 106 108 10a 10c 10e 110 112 114 116 118 11a 11c 11e 120 122 124 126 128 12a 12c 12e 130 132 134 136 138 13a 13c 13e 140
|
||||||
|
012: 141 143 145 147 149 14b 14d 14f 151 153 155 157 159 15b 15d 15f 161 163 165 167 169 16b 16d 16f 171 173 175 177 179 17b 17d 17f
|
||||||
|
013: 142 144 146 148 14a 14c 14e 150 152 154 156 158 15a 15c 15e 160 162 164 166 168 16a 16c 16e 170 172 174 176 178 17a 17c 17e 180
|
||||||
|
014: 181 183 185 187 189 18b 18d 18f 191 193 195 197 199 19b 19d 19f 1a1 1a3 1a5 1a7 1a9 1ab 1ad 1af 1b1 1b3 1b5 1b7 1b9 1bb 1bd 1bf
|
||||||
|
015: 182 184 186 188 18a 18c 18e 190 192 194 196 198 19a 19c 19e 1a0 1a2 1a4 1a6 1a8 1aa 1ac 1ae 1b0 1b2 1b4 1b6 1b8 1ba 1bc 1be 1c0
|
||||||
|
016: 1c1 1c3 1c5 1c7 1c9 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
|
||||||
|
017: 1c2 1c4 1c6 1c8 1ca 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
|
||||||
|
018: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
|
||||||
|
019: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
|
||||||
|
020: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
|
||||||
|
021: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
|
||||||
|
022: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
|
||||||
|
023: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
|
||||||
|
024: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
|
||||||
|
025: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
|
||||||
|
026: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||||
|
027: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||||
|
028: 1cc 1ce 1d0 1d2 1d4 1d6 1d8 1da 1dc 1de 1e0 1e2 1e4 1e6 1e8 1ea 1ec 1ee 1f0 1f2 1f4 1f6 1f8 1fa 1fc 1fe 200 202 204 206 208 20a
|
||||||
|
029: 1cd 1cf 1d1 1d3 1d5 1d7 1d9 1db 1dd 1df 1e1 1e3 1e5 1e7 1e9 1eb 1ed 1ef 1f1 1f3 1f5 1f7 1f9 1fb 1fd 1ff 201 203 205 207 209 20b
|
||||||
|
030: 20c 20e 210 212 214 216 218 21a 21c 21e 220 222 224 226 228 22a 22c 22e 230 232 234 236 238 23a 23c 23e 240 242 244 246 248 24a
|
||||||
|
031: 20d 20f 211 213 215 217 219 21b 21d 21f 221 223 225 227 229 22b 22d 22f 231 233 235 237 239 23b 23d 23f 241 243 245 247 249 24b
|
||||||
|
032: 24c 24e 250 252 254 256 258 25a 25c 25e 260 262 264 266 268 26a 26c 26e 270 272 274 276 278 27a 27c 27e 280 282 284 286 288 28a
|
||||||
|
033: 24d 24f 251 253 255 257 259 25b 25d 25f 261 263 265 267 269 26b 26d 26f 271 273 275 277 279 27b 27d 27f 281 283 285 287 289 28b
|
||||||
|
034: 28c 28e 290 292 294 296 298 29a 29c 29e 2a0 2a2 2a4 2a6 2a8 2aa 2ac 2ae 2b0 2b2 2b4 2b6 2b8 2ba 2bc 2be 2c0 2c2 2c4 2c6 2c8 2ca
|
||||||
|
035: 28d 28f 291 293 295 297 299 29b 29d 29f 2a1 2a3 2a5 2a7 2a9 2ab 2ad 2af 2b1 2b3 2b5 2b7 2b9 2bb 2bd 2bf 2c1 2c3 2c5 2c7 2c9 2cb
|
||||||
|
036: 2cc 2ce 2d0 2d2 2d4 2d6 2d8 2da 2dc 2de 2e0 2e2 2e4 2e6 2e8 2ea 2ec 2ee 2f0 2f2 2f4 2f6 2f8 2fa 2fc 2fe 300 302 304 306 308 30a
|
||||||
|
037: 2cd 2cf 2d1 2d3 2d5 2d7 2d9 2db 2dd 2df 2e1 2e3 2e5 2e7 2e9 2eb 2ed 2ef 2f1 2f3 2f5 2f7 2f9 2fb 2fd 2ff 301 303 305 307 309 30b
|
||||||
|
038: 30c 30e 310 312 314 316 318 31a 31c 31e 320 322 324 326 328 32a 32c 32e 330 332 334 336 338 33a 33c 33e 340 342 344 346 348 34a
|
||||||
|
039: 30d 30f 311 313 315 317 319 31b 31d 31f 321 323 325 327 329 32b 32d 32f 331 333 335 337 339 33b 33d 33f 341 343 345 347 349 34b
|
||||||
|
040: 34c 34e 350 352 354 356 358 35a 35c 35e 360 362 364 366 368 36a 36c 36e 370 372 374 376 378 37a 37c 37e 380 382 384 386 388 38a
|
||||||
|
041: 34d 34f 351 353 355 357 359 35b 35d 35f 361 363 365 367 369 36b 36d 36f 371 373 375 377 379 37b 37d 37f 381 383 385 387 389 38b
|
||||||
|
042: 38c 38e 390 392 394 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
|
||||||
|
043: 38d 38f 391 393 395 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
|
||||||
|
044: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
|
||||||
|
045: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
|
||||||
|
046: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
|
||||||
|
047: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
|
||||||
|
048: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
|
||||||
|
049: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
|
||||||
|
050: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
|
||||||
|
051: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
|
||||||
|
052: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
||||||
|
053: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
|
1331
source/cart_hw/svp/ssp16.c
Normal file
83
source/cart_hw/svp/ssp16.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
basic, incomplete SSP160x (SSP1601?) interpreter
|
||||||
|
with SVP memory controller emu
|
||||||
|
|
||||||
|
(c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||||
|
Free for non-commercial use.
|
||||||
|
|
||||||
|
For commercial use, separate licencing terms must be obtained.
|
||||||
|
|
||||||
|
Modified for Genesis Plus GX (Eke-Eke): added BIG ENDIAN support, fixed addr/code inversion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SSP16_H_
|
||||||
|
#define _SSP16_H_
|
||||||
|
|
||||||
|
/* emulation event logging (from Picodrive) */
|
||||||
|
#define EL_SVP 0x00004000 /* SVP stuff */
|
||||||
|
#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */
|
||||||
|
#ifdef LOG_SVP
|
||||||
|
#define elprintf(w,f,...) error("%d(%d): " f "\n",frame_count,v_counter,##__VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define elprintf(w,f,...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* register names */
|
||||||
|
enum {
|
||||||
|
SSP_GR0, SSP_X, SSP_Y, SSP_A,
|
||||||
|
SSP_ST, SSP_STACK, SSP_PC, SSP_P,
|
||||||
|
SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
|
||||||
|
SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
unsigned int v;
|
||||||
|
struct {
|
||||||
|
#ifdef LSB_FIRST
|
||||||
|
unsigned short l;
|
||||||
|
unsigned short h;
|
||||||
|
#else
|
||||||
|
unsigned short h;
|
||||||
|
unsigned short l;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
} ssp_reg_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
unsigned short RAM[256*2]; // 2 internal RAM banks
|
||||||
|
struct {
|
||||||
|
unsigned short RAM0[256];
|
||||||
|
unsigned short RAM1[256];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ssp_reg_t gr[16]; // general registers
|
||||||
|
union {
|
||||||
|
unsigned char r[8]; // BANK pointers
|
||||||
|
struct {
|
||||||
|
unsigned char r0[4];
|
||||||
|
unsigned char r1[4];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
unsigned short stack[6];
|
||||||
|
unsigned int pmac_read[6]; // read modes/addrs for PM0-PM5
|
||||||
|
unsigned int pmac_write[6]; // write ...
|
||||||
|
|
||||||
|
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode
|
||||||
|
#define SSP_PMC_SET 0x0002 // PMAC is set
|
||||||
|
#define SSP_HANG 0x1000 // 68000 hangs SVP
|
||||||
|
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0
|
||||||
|
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE08 to become non-zero
|
||||||
|
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
|
||||||
|
#define SSP_WAIT_MASK 0xf000
|
||||||
|
unsigned int emu_status;
|
||||||
|
unsigned int pad[30];
|
||||||
|
} ssp1601_t;
|
||||||
|
|
||||||
|
|
||||||
|
void ssp1601_reset(ssp1601_t *ssp);
|
||||||
|
void ssp1601_run(int cycles);
|
||||||
|
|
||||||
|
#endif
|
50
source/cart_hw/svp/svp.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
basic, incomplete SSP160x (SSP1601?) interpreter
|
||||||
|
with SVP memory controller emu
|
||||||
|
|
||||||
|
(c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||||
|
Free for non-commercial use.
|
||||||
|
|
||||||
|
For commercial use, separate licencing terms must be obtained.
|
||||||
|
|
||||||
|
Modified for Genesis Plus GX (Eke-Eke): added BIG ENDIAN support, fixed addr/code inversion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
svp_t *svp = NULL;
|
||||||
|
int16 SVP_cycles = 800;
|
||||||
|
|
||||||
|
void svp_init(void)
|
||||||
|
{
|
||||||
|
svp = (void *) ((char *)cart.rom + 0x200000);
|
||||||
|
memset(svp, 0, sizeof(*svp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void svp_reset(void)
|
||||||
|
{
|
||||||
|
memcpy(svp->iram_rom + 0x800, cart.rom + 0x800, 0x20000 - 0x800);
|
||||||
|
ssp1601_reset(&svp->ssp1601);
|
||||||
|
}
|
||||||
|
|
||||||
|
void svp_write_dram(uint32 address, uint32 data)
|
||||||
|
{
|
||||||
|
*(uint16 *)(svp->dram + (address & 0x1fffe)) = data;
|
||||||
|
if ((address == 0x30fe06) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
|
||||||
|
if ((address == 0x30fe08) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 svp_read_cell_1(uint32 address)
|
||||||
|
{
|
||||||
|
address >>= 1;
|
||||||
|
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
|
||||||
|
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 svp_read_cell_2(uint32 address)
|
||||||
|
{
|
||||||
|
address >>= 1;
|
||||||
|
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
|
||||||
|
return *(uint16 *)(svp->dram + (address & 0x1fffe));
|
||||||
|
}
|
||||||
|
|
34
source/cart_hw/svp/svp.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
basic, incomplete SSP160x (SSP1601?) interpreter
|
||||||
|
with SVP memory controller emu
|
||||||
|
|
||||||
|
(c) Copyright 2008, Grazvydas "notaz" Ignotas
|
||||||
|
Free for non-commercial use.
|
||||||
|
|
||||||
|
For commercial use, separate licencing terms must be obtained.
|
||||||
|
|
||||||
|
Modified for Genesis Plus GX (Eke-Eke): added BIG ENDIAN support, fixed addr/code inversion
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SVP_H_
|
||||||
|
#define _SVP_H_
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "ssp16.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
|
||||||
|
unsigned char dram[0x20000];
|
||||||
|
ssp1601_t ssp1601;
|
||||||
|
} svp_t;
|
||||||
|
|
||||||
|
extern svp_t *svp;
|
||||||
|
extern int16 SVP_cycles;
|
||||||
|
|
||||||
|
extern void svp_init(void);
|
||||||
|
extern void svp_reset(void);
|
||||||
|
extern void svp_write_dram(uint32 address, uint32 data);
|
||||||
|
extern uint32 svp_read_cell_1(uint32 address);
|
||||||
|
extern uint32 svp_read_cell_2(uint32 address);
|
||||||
|
|
||||||
|
#endif
|
524
source/cart_hw/svp/svpdoc.txt
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
notaz's SVP doc
|
||||||
|
$Id: svpdoc.txt 349 2008-02-04 23:13:59Z notaz $
|
||||||
|
Copyright 2008, Grazvydas Ignotas (notaz)
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
If you use this, please credit me in your work or it's documentation.
|
||||||
|
Tasco Deluxe should also be credited for his pioneering work on the subject.
|
||||||
|
Thanks.
|
||||||
|
|
||||||
|
Use monospace font and disable word wrap when reading this document.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Table of Contents
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
0. Introduction
|
||||||
|
1. Overview
|
||||||
|
2. The SSP160x DSP
|
||||||
|
2.1. General registers
|
||||||
|
2.2. External registers
|
||||||
|
2.3. Pointer registers
|
||||||
|
2.4. The instruction set
|
||||||
|
3. Memory map
|
||||||
|
4. Other notes
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
0. Introduction
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This document is an attempt to provide technical information needed to
|
||||||
|
emulate Sega's SVP chip. It is based on reverse engineering Virtua Racing
|
||||||
|
game and on various internet sources. None of information provided here
|
||||||
|
was verified on the real hardware, so some things are likely to be
|
||||||
|
inaccurate.
|
||||||
|
|
||||||
|
The following information sources were used while writing this document
|
||||||
|
and emulator implementation:
|
||||||
|
|
||||||
|
[1] SVP Reference Guide (annotated) and SVP Register Guide (annotated)
|
||||||
|
by Tasco Deluxe < tasco.deluxe @ gmail.com >
|
||||||
|
http://www.sharemation.com/TascoDLX/SVP%20Reference%20Guide%202007.02.11.txt
|
||||||
|
http://www.sharemation.com/TascoDLX/SVP%20Register%20Guide%202007.02.11.txt
|
||||||
|
[2] SSP1610 disassembler
|
||||||
|
written by Pierpaolo Prazzoli, MAME source code.
|
||||||
|
http://mamedev.org/
|
||||||
|
[3] SSP1601 DSP datasheet
|
||||||
|
http://notaz.gp2x.de/docs/SSP1601.pdf
|
||||||
|
[4] DSP page (with code samples) in Samsung Semiconductor website from 1997
|
||||||
|
retrieved from Internet Archive: The Wayback Machine
|
||||||
|
http://web.archive.org/web/19970607052826/www.sec.samsung.com/Products/dsp/dspcore.htm
|
||||||
|
[5] Sega's SVP Chip: The Road not Taken?
|
||||||
|
Ken Horowitz, Sega-16
|
||||||
|
http://sega-16.com/feature_page.php?id=37&title=Sega's%20SVP%20Chip:%20The%20Road%20not%20Taken?
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
1. Overview
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The only game released with SVP chip was Virtua Racing. There are at least 4
|
||||||
|
versions of the game: USA, Jap and 2 different Eur revisions. Three of them
|
||||||
|
share identical SSP160x code, one of the Eur revisions has some differences.
|
||||||
|
|
||||||
|
From the software developer's point of view, the game cartridge contains
|
||||||
|
at least:
|
||||||
|
|
||||||
|
* Samsung SSP160x 16-bit DSP core, which includes [3]:
|
||||||
|
* Two independent high-speed RAM banks, accessed in single clock cycle,
|
||||||
|
256 words each.
|
||||||
|
* 16 x 16 bit multiply unit.
|
||||||
|
* 32-bit ALU, status register.
|
||||||
|
* Hardware stack of 6 levels.
|
||||||
|
* 128KB of DRAM.
|
||||||
|
* 2KB of IRAM (instruction RAM).
|
||||||
|
* Memory controller with address mapping capability.
|
||||||
|
* 2MB of game ROM.
|
||||||
|
|
||||||
|
[5] claims there is also "2 Channels PWM" in the cartridge, but it's either
|
||||||
|
not used or not there at all.
|
||||||
|
Various sources claim that SSP160x is SSP1601 which is likely to be true,
|
||||||
|
because the code doesn't seem to use any SSP1605+ features.
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
2. The SSP160x DSP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SSP160x is 16-bit DSP, capable of performing multiplication + addition in
|
||||||
|
single clock cycle [3]. It has 8 general, 8 external and 8 pointer registers.
|
||||||
|
There is a status register which has operation control bits and condition
|
||||||
|
flags. Condition flags are set/cleared during ALU (arithmetic, logic)
|
||||||
|
operations. It also has 6-level hardware stack and 2 internal RAM banks
|
||||||
|
RAM0 and RAM1, 256 words each.
|
||||||
|
|
||||||
|
The device is only capable of addressing 16-bit words, so all addresses refer
|
||||||
|
to words (16bit value in ROM, accessed by 68k through address 0x84 would be
|
||||||
|
accessed by SSP160x using address 0x42).
|
||||||
|
|
||||||
|
[3] mentions interrupt pins, but interrupts don't seem to be used by SVP code
|
||||||
|
(actually there are functions which look like interrupt handler routines, but
|
||||||
|
they don't seem to do anything important).
|
||||||
|
|
||||||
|
2.1. General registers
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
There are 8 general registers: -, X, Y, A, ST, STACK, PC and P ([2] [4]).
|
||||||
|
Size is given in bits.
|
||||||
|
|
||||||
|
2.1.1. "-"
|
||||||
|
Constant register with all bits set (0xffff). Also used for programming
|
||||||
|
external registers (blind reads/writes, see 2.2).
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.2. "X"
|
||||||
|
Generic register. Also acts as a multiplier 1 for P register.
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.3. "Y"
|
||||||
|
Generic register. Also acts as a multiplier 2 for P register.
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.4. "A"
|
||||||
|
Accumulator. Stores the result of all ALU (but not multiply) operations,
|
||||||
|
status register is updated according to this. When directly accessed,
|
||||||
|
only upper word is read/written. Low word can be accessed by using AL
|
||||||
|
(see 2.2.8).
|
||||||
|
size: 32
|
||||||
|
|
||||||
|
2.1.5. "ST"
|
||||||
|
STatus register. Bits 0-9 are CONTROL, other are FLAG [2]. Only some of
|
||||||
|
them are actually used by SVP.
|
||||||
|
Bits: fedc ba98 7654 3210
|
||||||
|
210 - RPL "Loop size". If non-zero, makes (rX+) and (rX-) respectively
|
||||||
|
modulo-increment and modulo-decrement (see 2.3). The value
|
||||||
|
shows which power of 2 to use, i.e. 4 means modulo by 16.
|
||||||
|
43 - RB Unknown. Not used by SVP code.
|
||||||
|
5 - ST5 Affects behavior of external registers. See 2.2.
|
||||||
|
6 - ST6 Affects behavior of external registers. See 2.2.
|
||||||
|
According to [3] (5,6) bits correspond to hardware pins.
|
||||||
|
7 - IE Interrupt enable? Not used by SVP code.
|
||||||
|
8 - OP Saturated value? Not used by SVP code.
|
||||||
|
9 - MACS MAC shift? Not used by SVP code.
|
||||||
|
a - GPI_0 Interrupt 0 enable/status? Not used by SVP code.
|
||||||
|
b - GPI_1 Interrupt 1 enable/status? Not used by SVP code.
|
||||||
|
c - L L flag. Similar to carry? Not used by SVP code.
|
||||||
|
d - Z Zero flag. Set after ALU operations, when all 32 accumulator
|
||||||
|
bits become zero.
|
||||||
|
e - OV Overflow flag. Not used by SVP code.
|
||||||
|
f - N Negative flag. Set after ALU operations, when bit31 in
|
||||||
|
accumulator is 1.
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.6. "STACK"
|
||||||
|
Hardware stack of 6 levels [3]. Values are "pushed" by directly writing to
|
||||||
|
it, or by "call" instruction. "Pop" is performed by directly reading the
|
||||||
|
register or by "ret" instruction.
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.7. "PC"
|
||||||
|
Program Counter. Can be written directly to perform a jump. It is not clear
|
||||||
|
if it is possible to read it (SVP code never does).
|
||||||
|
size: 16
|
||||||
|
|
||||||
|
2.1.8. "P"
|
||||||
|
multiply Product - multiplication result register.
|
||||||
|
Always contains 32-bit multiplication result of X, Y and 2 (P = X * Y * 2).
|
||||||
|
X and Y are sign-extended before performing the multiplication.
|
||||||
|
size: 32
|
||||||
|
|
||||||
|
2.2. External registers
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The external registers, as the name says, are external to SSP160x, they are
|
||||||
|
hooked to memory controller in SVP, so by accessing them we actually program
|
||||||
|
the memory controller. They act as programmable memory access registers or
|
||||||
|
external status registers [1]. Some of them can act as both, depending on how
|
||||||
|
ST5 ans ST6 bits are set in status register. After a register is programmed,
|
||||||
|
accessing it causes reads/writes from/to external memory (see section 3 for
|
||||||
|
the memory map). The access may also cause some additional effects, like
|
||||||
|
incremental of address, associated with accessed register.
|
||||||
|
In this document and my emu, instead of using names EXT0-EXT7
|
||||||
|
from [4] I used different names for these registers. Those names are from
|
||||||
|
Tasco Deluxe's [1] doc.
|
||||||
|
|
||||||
|
All these registers can be blind-accessed (as said in [1]) by performing
|
||||||
|
(ld -, PMx) or (ld PMx, -). This programs them to access memory (except PMC,
|
||||||
|
where the effect is different).
|
||||||
|
All registers are 16-bit.
|
||||||
|
|
||||||
|
2.2.1. "PM0"
|
||||||
|
If ST5 or ST6 is set, acts as Programmable Memory access register
|
||||||
|
(see 2.2.7). Else it acts as status of XST (2.2.4). It is also mapped
|
||||||
|
to a15004 on 68k side:
|
||||||
|
???????? ??????10
|
||||||
|
0: set, when SSP160x has written something to XST
|
||||||
|
(cleared when 015004 is read by 68k)
|
||||||
|
1: set, when 68k has written something to a15000 or a15002
|
||||||
|
(cleared on PM0 read by SSP160x)
|
||||||
|
Note that this is likely to be incorrect, but such behavior is OK for
|
||||||
|
emulation to work.
|
||||||
|
|
||||||
|
2.2.2. "PM1"
|
||||||
|
Programmable Memory access register. Only accessed with ST bits set by
|
||||||
|
SVP code.
|
||||||
|
|
||||||
|
2.2.3. "PM2"
|
||||||
|
Same as PM1.
|
||||||
|
|
||||||
|
2.2.4. "XST"
|
||||||
|
If ST5 or ST6 is set, acts as Programmable Memory access register
|
||||||
|
(only used by memory test code). Else it acts as eXternal STatus
|
||||||
|
register, which is also mapped to a15000 and a15002 on 68k side.
|
||||||
|
Affects PM0 when written to.
|
||||||
|
|
||||||
|
2.2.5. "PM4"
|
||||||
|
Programmable Memory access register. Not affected by ST5 and ST6 bits,
|
||||||
|
always stays in PMAR mode.
|
||||||
|
|
||||||
|
2.2.6. "EXT5"
|
||||||
|
Not used by SVP, so not covered by this document.
|
||||||
|
|
||||||
|
2.2.7. "PMC"
|
||||||
|
Programmable Memory access Control. It is set using 2 16bit writes, first
|
||||||
|
address, then mode word. After setting PMAC, PMx should be blind accessed
|
||||||
|
using (ld -, PMx) or (ld PMx, -) to program it for reading or writing
|
||||||
|
external memory respectively. Every PMx register can be programmed to
|
||||||
|
access it's own memory location with it's own mode. Registers are programmed
|
||||||
|
separately for reading and writing.
|
||||||
|
|
||||||
|
Reading PMC register also shifts it's state (from "waiting for address" to
|
||||||
|
"waiting for mode" and back). Reads always return address word related to
|
||||||
|
last PMx register accessed, or last address word written to PMC (whichever
|
||||||
|
event happened last before PMC read).
|
||||||
|
|
||||||
|
The address word contains bits 0-15 of the memory word-address.
|
||||||
|
The mode word format is as follows:
|
||||||
|
dsnnnv?? ???aaaaa
|
||||||
|
a: bits 16-20 of memory word-address.
|
||||||
|
n: auto-increment value. If set, after every access of PMx, word-address
|
||||||
|
value related to it will be incremented by (words):
|
||||||
|
1 - 1 5 - 16
|
||||||
|
2 - 2 6 - 32
|
||||||
|
3 - 4 7 - 128
|
||||||
|
4 - 8
|
||||||
|
d: make auto-increment negative - decrement by count listed above.
|
||||||
|
s: special-increment mode. If current address is even (when accessing
|
||||||
|
programmed PMx), increment it by 1. Else, increment by 32. It is not
|
||||||
|
clear what happens if d and n bits are also set (never done by SVP).
|
||||||
|
v: over-write mode when writing, unknown when reading (not used).
|
||||||
|
Over-write mode splits the word being written into 4 half-bytes and
|
||||||
|
only writes those half-bytes, which are not zero.
|
||||||
|
When auto-increment is performed, it affects all 21 address bits.
|
||||||
|
|
||||||
|
2.2.8. "AL"
|
||||||
|
This register acts more like a general register.
|
||||||
|
If this register is blind-accessed, it is "dummy programmed", i.e. nothing
|
||||||
|
happens and PMC is reset to "waiting for address" state.
|
||||||
|
In all other cases, it is Accumulator Low, 16 least significant bits of
|
||||||
|
accumulator. Normally reading acc (ld X, A) you get 16 most significant
|
||||||
|
bits, so this allows you access the low word of 32bit accumulator.
|
||||||
|
|
||||||
|
2.3. Pointer registers
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
There are 8 8-bit pointer registers rX, which are internal to SSP160x and are
|
||||||
|
used to access internal RAM banks RAM0 and RAM1, or program memory indirectly.
|
||||||
|
r0-r3 (ri) point to RAM0, r4-r7 (rj) point to RAM1. Each bank has 256 words of
|
||||||
|
RAM, so 8bit registers can fully address them. The registers can be accessed
|
||||||
|
directly, or 2 indirection levels can be used [ (rX), ((rX)) ]. They work
|
||||||
|
similar to * and ** operators in C, only they use different types of memory
|
||||||
|
and ((rX)) also performs post-increment. First indirection level (rX) accesses
|
||||||
|
a word in RAMx, second accesses program memory at address read from (rX), and
|
||||||
|
increments value in (rX).
|
||||||
|
|
||||||
|
Only r0,r1,r2,r4,r5,r6 can be directly modified (ldi r0, 5), or by using
|
||||||
|
modifiers. 3 modifiers can be applied when using first indirection level
|
||||||
|
(optional):
|
||||||
|
+ : post-increment (ld a, (r0+) ). Increment register value after operation.
|
||||||
|
Can be made modulo-increment by setting RPL bits in status register
|
||||||
|
(see 2.1.5).
|
||||||
|
- : post-decrement. Also can be made modulo-decrement by using RPL bits in ST.
|
||||||
|
+!: post-increment, unaffected by RPL (probably).
|
||||||
|
These are only used on 1st indirection level, so things like ( ld a, ((r0+)) )
|
||||||
|
and (ld X, r6-) are probably invalid.
|
||||||
|
|
||||||
|
r3 and r7 are special and can not be changed (at least Samsung samples [4] and
|
||||||
|
SVP code never do). They are fixed to the start of their RAM banks. (They are
|
||||||
|
probably changeable for ssp1605+, Samsung's old DSP page claims that).
|
||||||
|
1 of these 4 modifiers must be used on these registers (short form direct
|
||||||
|
addressing? [2]):
|
||||||
|
|00: RAMx[0] The very first word in the RAM bank.
|
||||||
|
|01: RAMx[1] Second word
|
||||||
|
|10: RAMx[2] ...
|
||||||
|
|11: RAMx[3]
|
||||||
|
|
||||||
|
2.4. The instruction set
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The Samsung SSP16 series assembler uses right-to-left notation ([2] [4]):
|
||||||
|
ld X, Y
|
||||||
|
means value from Y should be copied to X.
|
||||||
|
|
||||||
|
Size of every instruction is word, some have extension words for immediate
|
||||||
|
values. When writing an interpreter, 7 most significant bits are usually
|
||||||
|
enough to determine which opcode it is.
|
||||||
|
|
||||||
|
encoding bits are marked as:
|
||||||
|
rrrr - general or external register, in order specified in 2.1 and 2.2
|
||||||
|
(0 is '-', 1 'X', ..., 8 is 'PM0', ..., 0xf is 'AL')
|
||||||
|
dddd - same as above, as destination operand
|
||||||
|
ssss - same as above, as source operand
|
||||||
|
jpp - pointer register index, 0-7
|
||||||
|
j - specifies RAM bank, i.e. RAM0 or RAM1
|
||||||
|
i* - immediate value bits
|
||||||
|
a* - offset in internal RAM bank
|
||||||
|
mm - modifier for pointer register, depending on register:
|
||||||
|
r0-r2,r4-r6 r3,r7 examples
|
||||||
|
0: (none) |00 ld a, (r0) cmp a, (r7|00)
|
||||||
|
1: +! |01 ld (r0+!), a ld (r7|01), a
|
||||||
|
2: - |10 add a, (r0-)
|
||||||
|
3: + |11
|
||||||
|
cccc - encodes condition, only 3 used by SVP, see check_cond() below
|
||||||
|
ooo - operation to perform
|
||||||
|
|
||||||
|
Operation is written in C-style pseudo-code, where:
|
||||||
|
program_memory[X] - access program memory at address X
|
||||||
|
RAMj[X] - access internal RAM bank j=0,1 (RAM0 or RAM1), word
|
||||||
|
offset X
|
||||||
|
RIJ[X] - pointer register rX, X=0-7
|
||||||
|
pr_modif_read(m,X) - read pointer register rX, applying modifier m:
|
||||||
|
if register is r3 or r7, return value m
|
||||||
|
else switch on value m:
|
||||||
|
0: return rX;
|
||||||
|
1: tmp = rX; rX++; return tmp; // rX+!
|
||||||
|
2: tmp = rX; modulo_decrement(rX); return tmp; // rX-
|
||||||
|
3: tmp = rX; modulo_increment(rX); return tmp; // rX+
|
||||||
|
the modulo value used (if used at all) depends on ST
|
||||||
|
RPL bits (see 2.1.5)
|
||||||
|
check_cond(c,f) - checks if a flag matches f bit:
|
||||||
|
switch (c) {
|
||||||
|
case 0: return true;
|
||||||
|
case 5: return (Z == f) ? true : false; // check Z flag
|
||||||
|
case 7: return (N == f) ? true : false; // check N flag
|
||||||
|
} // other conditions are possible, but they are not used
|
||||||
|
update_flags() - update ST flags according to last ALU operation.
|
||||||
|
sign_extend(X) - sign extend 16bit value X to 32bits.
|
||||||
|
next_op_address() - address of instruction after current instruction.
|
||||||
|
|
||||||
|
2.4.1. ALU instructions
|
||||||
|
|
||||||
|
All of these instructions update flags, which are set according to full 32bit
|
||||||
|
accumulator. The SVP code only checks N and Z flags, so it is not known when
|
||||||
|
exactly OV and L flags are set. Operations are performed on full A, so
|
||||||
|
(andi A, 0) would clear all 32 bits of A.
|
||||||
|
|
||||||
|
They share the same addressing modes. The exact arithmetic operation is
|
||||||
|
determined by 3 most significant (ooo) bits:
|
||||||
|
001 - sub - subtract (OP -=)
|
||||||
|
011 - cmp - compare (OP -, flags are updated according to result)
|
||||||
|
100 - add - add (OP +=)
|
||||||
|
101 - and - binary AND (OP &=)
|
||||||
|
110 - or - binary OR (OP |=)
|
||||||
|
111 - eor - exclusive OR (OP ^=)
|
||||||
|
|
||||||
|
syntax encoding operation
|
||||||
|
OP A, s ooo0 0000 0000 rrrr A OP r << 16;
|
||||||
|
OP A, (ri) ooo0 001j 0000 mmpp A OP RAMj[pr_modif_read(m,jpp)] << 16;
|
||||||
|
OP A, adr ooo0 011j aaaa aaaa A OP RAMj[a] << 16;
|
||||||
|
OPi A, imm ooo0 1000 0000 0000 A OP i << 16;
|
||||||
|
iiii iiii iiii iiii
|
||||||
|
op A, ((ri)) ooo0 101j 0000 mmpp tmp = pr_modif_read(m,jpp);
|
||||||
|
A OP program_memory[RAMj[tmp]] << 16;
|
||||||
|
RAMj[tmp]++;
|
||||||
|
op A, ri ooo1 001j 0000 00pp A OP RIJ[jpp] << 16;
|
||||||
|
OPi simm ooo1 1000 iiii iiii A OP i << 16;
|
||||||
|
|
||||||
|
There is also "perform operation on accumulator" instruction:
|
||||||
|
|
||||||
|
syntax encoding operation
|
||||||
|
mod cond, op 1001 000f cccc 0ooo if (check_cond(c,f)) switch(o) {
|
||||||
|
case 2: A >>= 1; break; // arithmetic shift
|
||||||
|
case 3: A <<= 1; break;
|
||||||
|
case 6: A = -A; break; // negate A
|
||||||
|
case 7: A = abs(A); break; // absolute val.
|
||||||
|
} // other operations are possible, but
|
||||||
|
// they are not used by SVP.
|
||||||
|
|
||||||
|
2.4.2. Load (move) instructions
|
||||||
|
|
||||||
|
These instructions never affect flags (even ld A).
|
||||||
|
If destination is A, and source is 16bit, only upper word is transfered (same
|
||||||
|
thing happens on opposite). If dest. is A, and source is P, whole 32bit value
|
||||||
|
is transfered. It is not clear if P can be destination operand (probably not,
|
||||||
|
no code ever does this).
|
||||||
|
Writing to STACK pushes a value there, reading pops. It is not known what
|
||||||
|
happens on overflow/underflow (never happens in SVP code).
|
||||||
|
ld -, - is used as a nop.
|
||||||
|
|
||||||
|
syntax encoding operation
|
||||||
|
ld d, s 0000 0000 dddd ssss d = s;
|
||||||
|
ld d, (ri) 0000 001j dddd mmpp d = RAMj[pr_modif_read(m,jpp)];
|
||||||
|
ld (ri), s 0000 010j ssss mmpp RAMj[pr_modif_read(m,jpp)] = s;
|
||||||
|
ldi d, imm 0000 1000 dddd 0000 d = i;
|
||||||
|
iiii iiii iiii iiii
|
||||||
|
ld d, ((ri)) 0000 101j dddd mmpp tmp = pr_modif_read(m,jpp);
|
||||||
|
d = program_memory[RAMj[tmp]];
|
||||||
|
RAMj[tmp]++;
|
||||||
|
ldi (ri), imm 0000 110l 0000 mmpp RAMj[pr_modif_read(m,jpp)] = i;
|
||||||
|
iiii iiii iiii iiii
|
||||||
|
ld adr, a 0000 111j aaaa aaaa RAMj[a] = A;
|
||||||
|
ld d, ri 0001 001j dddd 00pp d = RIJ[jpp];
|
||||||
|
ld ri, s 0001 010j ssss 00pp RIJ[jpp] = s;
|
||||||
|
ldi ri, simm 0001 1jpp iiii iiii RIJ[jpp] = i;
|
||||||
|
ld d, (a) 0100 1010 dddd 0000 d = program_memory[A[31:16]];
|
||||||
|
// read a word from program memory. Offset
|
||||||
|
// is the upper word in A.
|
||||||
|
|
||||||
|
2.4.3. Program control instructions
|
||||||
|
|
||||||
|
Only 3 instructions: call, ret (alias of ld PC, STACK) and branch. Indirect
|
||||||
|
jumps can be performed by simply writing to PC.
|
||||||
|
|
||||||
|
syntax encoding operation
|
||||||
|
call cond, addr 0100 100f cccc 0000 if (check_cond(c,f)) {
|
||||||
|
aaaa aaaa aaaa aaaa STACK = next_op_address(); PC = a;
|
||||||
|
}
|
||||||
|
bra cond, addr 0100 110f cccc 0000 if (check_cond(c,f)) PC = a;
|
||||||
|
aaaa aaaa aaaa aaaa
|
||||||
|
ret 0000 0000 0110 0101 PC = STACK; // same as ld PC, STACK
|
||||||
|
|
||||||
|
2.4.4. Multiply-accumulate instructions
|
||||||
|
|
||||||
|
Not sure if (ri) and (rj) really get loaded into X and Y, but multiplication
|
||||||
|
result surely is loaded into P. There is probably optional 3rd operand (1, 0;
|
||||||
|
encoded by bit16, default 1), but it's not used by SVP code.
|
||||||
|
|
||||||
|
syntax encoding operation
|
||||||
|
mld (rj), (ri) 1011 0111 nnjj mmii A = 0; update_flags();
|
||||||
|
X = RAM0[pr_modif_read(m,0ii)];
|
||||||
|
Y = RAM1[pr_modif_read(m,1jj)];
|
||||||
|
P = sign_extend(X) * sign_extend(Y) * 2
|
||||||
|
mpya (rj), (ri) 1001 0111 nnjj mmii A += P; update_flags();
|
||||||
|
X = RAM0[pr_modif_read(m,0ii)];
|
||||||
|
Y = RAM1[pr_modif_read(m,1jj)];
|
||||||
|
P = sign_extend(X) * sign_extend(Y) * 2
|
||||||
|
mpys (rj), (ri) 0011 0111 nnjj mmii A -= P; update_flags();
|
||||||
|
X = RAM0[pr_modif_read(m,0ii)];
|
||||||
|
Y = RAM1[pr_modif_read(m,1jj)];
|
||||||
|
P = sign_extend(X) * sign_extend(Y) * 2
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
3. Memory map
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The SSp160x can access it's own program memory, and external memory through EXT
|
||||||
|
registers (see 2.2). Program memory is read-execute-only, the size of this
|
||||||
|
space is 64K words (this is how much 16bit PC can address):
|
||||||
|
|
||||||
|
byte address word address name
|
||||||
|
0- 7ff 0- 3ff IRAM
|
||||||
|
800-1ffff 400-ffff ROM
|
||||||
|
|
||||||
|
There were reports that SVP has internal ROM, but fortunately they were wrong.
|
||||||
|
The location 800-1ffff is mapped from the same location in the 2MB game ROM.
|
||||||
|
The IRAM is read-only (as SSP160x doesn't have any means of writing to it's
|
||||||
|
program memory), but it can be changed through external memory space, as it's
|
||||||
|
also mapped there.
|
||||||
|
|
||||||
|
The external memory space seems to match the one visible by 68k, with some
|
||||||
|
differences:
|
||||||
|
|
||||||
|
68k space SVP space word address name
|
||||||
|
0-1fffff 0-1fffff 0- fffff game ROM
|
||||||
|
300000-31ffff 300000-31ffff 180000-18ffff DRAM
|
||||||
|
? 390000-3907ff 1c8000-1c83ff IRAM
|
||||||
|
390000-39ffff ? ? "cell arrange" 1
|
||||||
|
3a0000-3affff ? ? "cell arrange" 2
|
||||||
|
a15000-a15009 n/a n/a Status/control registers
|
||||||
|
|
||||||
|
The external memory can be read/written by SSP160x (except game ROM, which can
|
||||||
|
only be read).
|
||||||
|
|
||||||
|
"cell arrange" 1 and 2 are similar to the one used in SegaCD, they map
|
||||||
|
300000-30ffff location to 390000-39ffff and 3a0000-3affff, where linear image
|
||||||
|
written to 300000 can be read as VDP patterns at 390000. Virtua Racing doesn't
|
||||||
|
seem to use this feature, it is only used by memory test code.
|
||||||
|
|
||||||
|
Here is the list of status/control registers (16bit size):
|
||||||
|
a15000 - w/r command/result register. Visible as XST for SSP160x (2.2.4).
|
||||||
|
a15002 - mirror of the above.
|
||||||
|
a15004 - status of command/result register (see 2.2.1).
|
||||||
|
a15006 - possibly halts the SVP. Before doing DMA from DRAM, 68k code writes
|
||||||
|
0xa, and after it's finished, writes 0. This is probably done to
|
||||||
|
prevent SVP accessing DRAM and avoid bus clashes.
|
||||||
|
a15008 - possibly causes an interrupt. There is (unused?) code which writes
|
||||||
|
0, 1, and again 0 in sequence.
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
4. Other notes
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The game has arcade-style memory self-check mode, which can be accessed by
|
||||||
|
pressing _all_ buttons (including directions) on 3-button controller. There was
|
||||||
|
probably some loopback plug for this.
|
||||||
|
|
||||||
|
SVP seems to have DMA latency issue similar to one in Sega CD, as the code
|
||||||
|
always sets DMA source address value larger by 2, then intended for copy.
|
||||||
|
This is even true for DMAs from ROM, as it's probably hooked through SVP's
|
||||||
|
memory controller.
|
||||||
|
|
||||||
|
The entry point for the code seems to be at address 0x800 (word 0x400) in ROM,
|
||||||
|
but it is not clear where the address is fetched from when the system powers
|
||||||
|
up. The memory test code also sets up "ld PC, .." opcodes at 0x7f4, 0x7f8 and
|
||||||
|
0x7fc, which jump to some routines, possibly interrupt handlers. This means
|
||||||
|
that mentioned addresses might be built-in interrupt vectors.
|
||||||
|
|
||||||
|
The SVP code doesn't seem to be timing sensitive, so it can be emulated without
|
||||||
|
knowing timing of the instructions or even how fast the chip is clocked.
|
||||||
|
Overclocking doesn't have any effect, underclocking causes slowdowns. Running
|
||||||
|
10-12M instructions/sec (or possibly less) is sufficient.
|
||||||
|
|
428
source/genesis.c
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/***************************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Internal Hardware & Bus controllers
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||||
|
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
uint8 tmss[4]; /* TMSS security register */
|
||||||
|
uint8 bios_rom[0x800]; /* OS ROM */
|
||||||
|
uint8 work_ram[0x10000]; /* 68K RAM */
|
||||||
|
uint8 zram[0x2000]; /* Z80 RAM */
|
||||||
|
uint32 zbank; /* Z80 bank window address */
|
||||||
|
uint8 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
|
||||||
|
|
||||||
|
/* PICO data */
|
||||||
|
uint8 pico_current;
|
||||||
|
uint8 pico_page[7];
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* Init, reset, shutdown functions */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void gen_init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* initialize 68k */
|
||||||
|
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||||
|
m68k_init();
|
||||||
|
|
||||||
|
/* initialize Z80 */
|
||||||
|
z80_init(0,z80_irq_callback);
|
||||||
|
|
||||||
|
/* initialize 68k memory map */
|
||||||
|
/* $000000-$7FFFFF is affected to cartridge area (see md_cart.c) */
|
||||||
|
for (i=0x80; i<0x100; i++)
|
||||||
|
{
|
||||||
|
/* $800000-$FFFFFF is affected to WRAM (see VDP DMA) */
|
||||||
|
m68k_memory_map[i].base = work_ram;
|
||||||
|
m68k_memory_map[i].read8 = NULL;
|
||||||
|
m68k_memory_map[i].read16 = NULL;
|
||||||
|
m68k_memory_map[i].write8 = NULL;
|
||||||
|
m68k_memory_map[i].write16 = NULL;
|
||||||
|
zbank_memory_map[i].read = NULL;
|
||||||
|
zbank_memory_map[i].write = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize 68k memory handlers */
|
||||||
|
for (i=0x80; i<0xe0; i++)
|
||||||
|
{
|
||||||
|
/* $800000-$DFFFFF : illegal area by default */
|
||||||
|
m68k_memory_map[i].read8 = m68k_lockup_r_8;
|
||||||
|
m68k_memory_map[i].read16 = m68k_lockup_r_16;
|
||||||
|
m68k_memory_map[i].write8 = m68k_lockup_w_8;
|
||||||
|
m68k_memory_map[i].write16 = m68k_lockup_w_16;
|
||||||
|
zbank_memory_map[i].read = zbank_lockup_r;
|
||||||
|
zbank_memory_map[i].write = zbank_lockup_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* $A10000-$A1FFFF : I/O & Control registers */
|
||||||
|
m68k_memory_map[0xa1].read8 = ctrl_io_read_byte;
|
||||||
|
m68k_memory_map[0xa1].read16 = ctrl_io_read_word;
|
||||||
|
m68k_memory_map[0xa1].write8 = ctrl_io_write_byte;
|
||||||
|
m68k_memory_map[0xa1].write16 = ctrl_io_write_word;
|
||||||
|
zbank_memory_map[0xa1].read = zbank_read_ctrl_io;
|
||||||
|
zbank_memory_map[0xa1].write = zbank_write_ctrl_io;
|
||||||
|
|
||||||
|
/* $C0xxxx, $C8xxxx, $D0xxxx, $D8xxxx : VDP ports */
|
||||||
|
for (i=0xc0; i<0xe0; i+=8)
|
||||||
|
{
|
||||||
|
m68k_memory_map[i].read8 = vdp_read_byte;
|
||||||
|
m68k_memory_map[i].read16 = vdp_read_word;
|
||||||
|
m68k_memory_map[i].write8 = vdp_write_byte;
|
||||||
|
m68k_memory_map[i].write16 = vdp_write_word;
|
||||||
|
zbank_memory_map[i].read = zbank_read_vdp;
|
||||||
|
zbank_memory_map[i].write = zbank_write_vdp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MS COMPATIBILITY mode */
|
||||||
|
if (system_hw == SYSTEM_PBC)
|
||||||
|
{
|
||||||
|
/* initialize Z80 read handler */
|
||||||
|
/* NB: memory map & write handler are defined by cartridge hardware */
|
||||||
|
z80_readmem = z80_sms_memory_r;
|
||||||
|
|
||||||
|
/* initialize Z80 ports handlers */
|
||||||
|
z80_writeport = z80_sms_port_w;
|
||||||
|
z80_readport = z80_sms_port_r;
|
||||||
|
|
||||||
|
/* initialize MS cartridge hardware */
|
||||||
|
sms_cart_init();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* PICO hardware */
|
||||||
|
if (system_hw == SYSTEM_PICO)
|
||||||
|
{
|
||||||
|
/* additional registers mapped to $800000-$80FFFF */
|
||||||
|
m68k_memory_map[0x80].read8 = pico_read_byte;
|
||||||
|
m68k_memory_map[0x80].read16 = pico_read_word;
|
||||||
|
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
|
||||||
|
|
||||||
|
/* there is no I/O area (Notaz) */
|
||||||
|
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
|
||||||
|
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
|
||||||
|
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
|
||||||
|
|
||||||
|
/* page registers */
|
||||||
|
pico_current = 0x00;
|
||||||
|
pico_page[0] = 0x00;
|
||||||
|
pico_page[1] = 0x01;
|
||||||
|
pico_page[2] = 0x03;
|
||||||
|
pico_page[3] = 0x07;
|
||||||
|
pico_page[4] = 0x0F;
|
||||||
|
pico_page[5] = 0x1F;
|
||||||
|
pico_page[6] = 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize Z80 memory map */
|
||||||
|
/* $0000-$3FFF is mapped to Z80 RAM (8K mirrored) */
|
||||||
|
/* $4000-$FFFF is mapped to hardware but Z80.PC should never point there */
|
||||||
|
for (i=0; i<64; i++)
|
||||||
|
{
|
||||||
|
z80_readmap[i] = &zram[(i & 7) << 10];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize Z80 memory handlers */
|
||||||
|
z80_writemem = z80_md_memory_w;
|
||||||
|
z80_readmem = z80_md_memory_r;
|
||||||
|
|
||||||
|
/* initialize Z80 port handlers */
|
||||||
|
z80_writeport = z80_unused_port_w;
|
||||||
|
z80_readport = z80_unused_port_r;
|
||||||
|
|
||||||
|
/* initialize MD cartridge hardware */
|
||||||
|
md_cart_init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_reset(int hard_reset)
|
||||||
|
{
|
||||||
|
/* System Reset */
|
||||||
|
if (hard_reset)
|
||||||
|
{
|
||||||
|
/* clear RAM */
|
||||||
|
memset (work_ram, 0x00, sizeof (work_ram));
|
||||||
|
memset (zram, 0x00, sizeof (zram));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* reset YM2612 (on hard reset, this is done by sound_reset) */
|
||||||
|
fm_reset(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 68k & Z80 could restart anywhere in VDP frame (Bonkers, Eternal Champions, X-Men 2) */
|
||||||
|
mcycles_68k = mcycles_z80 = (uint32)((MCYCLES_PER_LINE * lines_per_frame) * ((double)rand() / (double)RAND_MAX));
|
||||||
|
|
||||||
|
if (system_hw == SYSTEM_PBC)
|
||||||
|
{
|
||||||
|
/* reset MS cartridge hardware */
|
||||||
|
sms_cart_reset();
|
||||||
|
|
||||||
|
/* Z80 is running */
|
||||||
|
zstate = 1;
|
||||||
|
|
||||||
|
/* 68k is halted */
|
||||||
|
m68k_pulse_halt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* reset MD cartridge hardware */
|
||||||
|
md_cart_reset(hard_reset);
|
||||||
|
|
||||||
|
/* Z80 bus is released & Z80 is reseted */
|
||||||
|
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
|
||||||
|
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
|
||||||
|
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
|
||||||
|
zstate = 0;
|
||||||
|
|
||||||
|
/* assume default bank is $000000-$007FFF */
|
||||||
|
zbank = 0;
|
||||||
|
|
||||||
|
/* TMSS & OS ROM support */
|
||||||
|
if (config.tmss & 1)
|
||||||
|
{
|
||||||
|
/* on HW reset only */
|
||||||
|
if (hard_reset)
|
||||||
|
{
|
||||||
|
/* clear TMSS register */
|
||||||
|
memset(tmss, 0x00, sizeof(tmss));
|
||||||
|
|
||||||
|
/* VDP access is locked by default */
|
||||||
|
int i;
|
||||||
|
for (i=0xc0; i<0xe0; i+=8)
|
||||||
|
{
|
||||||
|
m68k_memory_map[i].read8 = m68k_lockup_r_8;
|
||||||
|
m68k_memory_map[i].read16 = m68k_lockup_r_16;
|
||||||
|
m68k_memory_map[i].write8 = m68k_lockup_w_8;
|
||||||
|
m68k_memory_map[i].write16 = m68k_lockup_w_16;
|
||||||
|
zbank_memory_map[i].read = zbank_lockup_r;
|
||||||
|
zbank_memory_map[i].write = zbank_lockup_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OS ROM is mapped at $000000-$0007FF */
|
||||||
|
if (config.tmss & 2)
|
||||||
|
{
|
||||||
|
m68k_memory_map[0].base = bios_rom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset 68k */
|
||||||
|
m68k_pulse_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset Z80 */
|
||||||
|
z80_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_shutdown(void)
|
||||||
|
{
|
||||||
|
z80_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* OS ROM / TMSS register control functions (Genesis mode) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void gen_tmss_w(unsigned int offset, unsigned int data)
|
||||||
|
{
|
||||||
|
/* write TMSS regisiter */
|
||||||
|
WRITE_WORD(tmss, offset, data);
|
||||||
|
|
||||||
|
/* VDP requires "SEGA" value to be written in TMSS register */
|
||||||
|
int i;
|
||||||
|
if (strncmp((char *)tmss, "SEGA", 4) == 0)
|
||||||
|
{
|
||||||
|
for (i=0xc0; i<0xe0; i+=8)
|
||||||
|
{
|
||||||
|
m68k_memory_map[i].read8 = vdp_read_byte;
|
||||||
|
m68k_memory_map[i].read16 = vdp_read_word;
|
||||||
|
m68k_memory_map[i].write8 = vdp_write_byte;
|
||||||
|
m68k_memory_map[i].write16 = vdp_write_word;
|
||||||
|
zbank_memory_map[i].read = zbank_read_vdp;
|
||||||
|
zbank_memory_map[i].write = zbank_write_vdp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0xc0; i<0xe0; i+=8)
|
||||||
|
{
|
||||||
|
m68k_memory_map[i].read8 = m68k_lockup_r_8;
|
||||||
|
m68k_memory_map[i].read16 = m68k_lockup_r_16;
|
||||||
|
m68k_memory_map[i].write8 = m68k_lockup_w_8;
|
||||||
|
m68k_memory_map[i].write16 = m68k_lockup_w_16;
|
||||||
|
zbank_memory_map[i].read = zbank_lockup_r;
|
||||||
|
zbank_memory_map[i].write = zbank_lockup_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_bankswitch_w(unsigned int data)
|
||||||
|
{
|
||||||
|
/* OS ROM has not been loaded yet */
|
||||||
|
if (!(config.tmss & 2))
|
||||||
|
{
|
||||||
|
config.tmss |= 2;
|
||||||
|
memcpy(bios_rom, cart.rom, 0x800);
|
||||||
|
memset(cart.rom, 0xff, cart.romsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & 1)
|
||||||
|
{
|
||||||
|
/* enable CART */
|
||||||
|
m68k_memory_map[0].base = cart.base;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* enable internal BIOS ROM */
|
||||||
|
m68k_memory_map[0].base = bios_rom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int gen_bankswitch_r(void)
|
||||||
|
{
|
||||||
|
return (m68k_memory_map[0].base == cart.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Z80 Bus controller chip functions (Genesis mode) */
|
||||||
|
/* ----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void gen_zbusreq_w(unsigned int data, unsigned int cycles)
|
||||||
|
{
|
||||||
|
if (data) /* !ZBUSREQ asserted */
|
||||||
|
{
|
||||||
|
/* check if Z80 is going to be stopped */
|
||||||
|
if (zstate == 1)
|
||||||
|
{
|
||||||
|
/* resynchronize with 68k */
|
||||||
|
z80_run(cycles);
|
||||||
|
|
||||||
|
/* enable 68k access to Z80 bus */
|
||||||
|
m68k_memory_map[0xa0].read8 = z80_read_byte;
|
||||||
|
m68k_memory_map[0xa0].read16 = z80_read_word;
|
||||||
|
m68k_memory_map[0xa0].write8 = z80_write_byte;
|
||||||
|
m68k_memory_map[0xa0].write16 = z80_write_word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate |= 2;
|
||||||
|
}
|
||||||
|
else /* !ZBUSREQ released */
|
||||||
|
{
|
||||||
|
/* check if Z80 is going to be restarted */
|
||||||
|
if (zstate == 3)
|
||||||
|
{
|
||||||
|
/* resynchronize with 68k */
|
||||||
|
mcycles_z80 = cycles;
|
||||||
|
|
||||||
|
/* disable 68k access to Z80 bus */
|
||||||
|
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
|
||||||
|
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
|
||||||
|
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate &= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_zreset_w(unsigned int data, unsigned int cycles)
|
||||||
|
{
|
||||||
|
if (data) /* !ZRESET released */
|
||||||
|
{
|
||||||
|
/* check if Z80 is going to be restarted */
|
||||||
|
if (zstate == 0)
|
||||||
|
{
|
||||||
|
/* resynchronize with 68k */
|
||||||
|
mcycles_z80 = cycles;
|
||||||
|
|
||||||
|
/* reset Z80 & YM2612 */
|
||||||
|
z80_reset();
|
||||||
|
fm_reset(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if 68k access to Z80 bus is granted */
|
||||||
|
else if (zstate == 2)
|
||||||
|
{
|
||||||
|
/* enable 68k access to Z80 bus */
|
||||||
|
m68k_memory_map[0xa0].read8 = z80_read_byte;
|
||||||
|
m68k_memory_map[0xa0].read16 = z80_read_word;
|
||||||
|
m68k_memory_map[0xa0].write8 = z80_write_byte;
|
||||||
|
m68k_memory_map[0xa0].write16 = z80_write_word;
|
||||||
|
|
||||||
|
/* reset Z80 & YM2612 */
|
||||||
|
z80_reset();
|
||||||
|
fm_reset(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate |= 1;
|
||||||
|
}
|
||||||
|
else /* !ZRESET asserted */
|
||||||
|
{
|
||||||
|
/* check if Z80 is going to be stopped */
|
||||||
|
if (zstate == 1)
|
||||||
|
{
|
||||||
|
/* resynchronize with 68k */
|
||||||
|
z80_run(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if 68k had access to Z80 bus */
|
||||||
|
else if (zstate == 3)
|
||||||
|
{
|
||||||
|
/* disable 68k access to Z80 bus */
|
||||||
|
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
|
||||||
|
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
|
||||||
|
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
|
||||||
|
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop YM2612 */
|
||||||
|
fm_reset(cycles);
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate &= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gen_zbank_w (unsigned int data)
|
||||||
|
{
|
||||||
|
zbank = ((zbank >> 1) | ((data & 1) << 23)) & 0xFF8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Z80 interrupt callback */
|
||||||
|
/* ----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int z80_irq_callback (int param)
|
||||||
|
{
|
||||||
|
return 0xFF;
|
||||||
|
}
|
50
source/genesis.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/***************************************************************************************
|
||||||
|
* Genesis Plus
|
||||||
|
* Internal hardware & Bus controllers
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
||||||
|
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
****************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GENESIS_H_
|
||||||
|
#define _GENESIS_H_
|
||||||
|
|
||||||
|
/* Global variables */
|
||||||
|
extern uint8 tmss[4];
|
||||||
|
extern uint8 bios_rom[0x800];
|
||||||
|
extern uint8 work_ram[0x10000];
|
||||||
|
extern uint8 zram[0x2000];
|
||||||
|
extern uint32 zbank;
|
||||||
|
extern uint8 zstate;
|
||||||
|
extern uint8 pico_current;
|
||||||
|
extern uint8 pico_page[7];
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
extern void gen_init(void);
|
||||||
|
extern void gen_reset(int hard_reset);
|
||||||
|
extern void gen_shutdown(void);
|
||||||
|
extern void gen_tmss_w(unsigned int offset, unsigned int data);
|
||||||
|
extern void gen_bankswitch_w(unsigned int data);
|
||||||
|
extern unsigned int gen_bankswitch_r(void);
|
||||||
|
extern void gen_zbusreq_w(unsigned int state, unsigned int cycles);
|
||||||
|
extern void gen_zreset_w(unsigned int state, unsigned int cycles);
|
||||||
|
extern void gen_zbank_w(unsigned int state);
|
||||||
|
extern int z80_irq_callback(int param);
|
||||||
|
|
||||||
|
#endif /* _GEN_H_ */
|
||||||
|
|
64
source/gx/aram.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* aram.c
|
||||||
|
*
|
||||||
|
* ARAM wrapper for libogc
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
#define ARAMSTART 0x8000
|
||||||
|
#define ARAM_READ 1
|
||||||
|
#define ARAM_WRITE 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StartARAM
|
||||||
|
* This simply sets up the call to internal libOGC.
|
||||||
|
* Passing NULL for array list, and 0 items to allocate.
|
||||||
|
* Required so libOGC knows to handle any interrupts etc.
|
||||||
|
*/
|
||||||
|
void StartARAM ()
|
||||||
|
{
|
||||||
|
AR_Init (NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARAMPut
|
||||||
|
*
|
||||||
|
* Move data from MAIN memory to ARAM
|
||||||
|
*/
|
||||||
|
void ARAMPut (char *src, char *dst, int len)
|
||||||
|
{
|
||||||
|
DCFlushRange (src, len);
|
||||||
|
AR_StartDMA( ARAM_WRITE, (u32)src, (u32)dst, len);
|
||||||
|
while (AR_GetDMAStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARAMFetch
|
||||||
|
*
|
||||||
|
* This function will move data from ARAM to MAIN memory
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ARAMFetch (char *dst, char *src, int len)
|
||||||
|
{
|
||||||
|
DCInvalidateRange(dst, len);
|
||||||
|
AR_StartDMA( ARAM_READ, (u32) dst, (u32) src, len);
|
||||||
|
while (AR_GetDMAStatus());
|
||||||
|
}
|
31
source/gx/aram.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* aram.c
|
||||||
|
*
|
||||||
|
* ARAM wrapper for libogc
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _ARAM_H
|
||||||
|
#define _ARAM_H
|
||||||
|
|
||||||
|
extern void StartARAM ();
|
||||||
|
extern void ARAMFetch (char *src, char *dst, int len);
|
||||||
|
extern void ARAMPut (char *src, char *dst, int len);
|
||||||
|
|
||||||
|
#endif
|
169
source/gx/config.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* config.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX configuration file support
|
||||||
|
*
|
||||||
|
* Eke-Eke (2008)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
#include "shared.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "file_load.h"
|
||||||
|
|
||||||
|
static int config_load(void)
|
||||||
|
{
|
||||||
|
/* open configuration file */
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
sprintf (fname, "%s/config.ini", DEFAULT_PATH);
|
||||||
|
FILE *fp = fopen(fname, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
/* read version */
|
||||||
|
char version[16];
|
||||||
|
fread(version, 16, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (strncmp(version,CONFIG_VERSION,16))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* read file */
|
||||||
|
fp = fopen(fname, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fread(&config, sizeof(config), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void config_save(void)
|
||||||
|
{
|
||||||
|
/* open configuration file */
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
sprintf (fname, "%s/config.ini", DEFAULT_PATH);
|
||||||
|
FILE *fp = fopen(fname, "wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
/* write file */
|
||||||
|
fwrite(&config, sizeof(config), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void config_default(void)
|
||||||
|
{
|
||||||
|
/* version TAG */
|
||||||
|
strncpy(config.version,CONFIG_VERSION,16);
|
||||||
|
|
||||||
|
/* sound options */
|
||||||
|
config.psg_preamp = 150;
|
||||||
|
config.fm_preamp = 100;
|
||||||
|
config.hq_fm = 1;
|
||||||
|
config.psgBoostNoise = 0;
|
||||||
|
config.filter = 1;
|
||||||
|
config.lp_range = 50;
|
||||||
|
config.low_freq = 880;
|
||||||
|
config.high_freq = 5000;
|
||||||
|
config.lg = 1.0;
|
||||||
|
config.mg = 1.0;
|
||||||
|
config.hg = 1.0;
|
||||||
|
config.rolloff = 0.995;
|
||||||
|
config.dac_bits = 14;
|
||||||
|
config.ym2413_enabled = 1;
|
||||||
|
|
||||||
|
/* system options */
|
||||||
|
config.region_detect = 0;
|
||||||
|
config.force_dtack = 0;
|
||||||
|
config.addr_error = 1;
|
||||||
|
config.tmss = 0;
|
||||||
|
config.lock_on = 0;
|
||||||
|
config.romtype = 0;
|
||||||
|
config.hot_swap = 0;
|
||||||
|
|
||||||
|
/* video options */
|
||||||
|
config.xshift = 0;
|
||||||
|
config.yshift = 0;
|
||||||
|
config.xscale = 0;
|
||||||
|
config.yscale = 0;
|
||||||
|
config.aspect = 1;
|
||||||
|
config.overscan = 3;
|
||||||
|
config.ntsc = 0;
|
||||||
|
if (VIDEO_HaveComponentCable())
|
||||||
|
{
|
||||||
|
config.render = 2;
|
||||||
|
config.bilinear = 1;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
config.trap = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.render = 0;
|
||||||
|
config.bilinear = 0;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
config.trap = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
config.gamma = VI_GM_1_0 / 10.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* controllers options */
|
||||||
|
config.gun_cursor[0] = 1;
|
||||||
|
config.gun_cursor[1] = 1;
|
||||||
|
config.invert_mouse = 0;
|
||||||
|
gx_input_SetDefault();
|
||||||
|
|
||||||
|
/* menu options */
|
||||||
|
config.autoload = 0;
|
||||||
|
config.autocheat = 0;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
config.s_auto = 1;
|
||||||
|
#else
|
||||||
|
config.s_auto = 0;
|
||||||
|
#endif
|
||||||
|
config.s_default = 1;
|
||||||
|
config.s_device = 0;
|
||||||
|
config.bg_type = 0;
|
||||||
|
config.bg_overlay = 1;
|
||||||
|
config.screen_w = 658;
|
||||||
|
config.bgm_volume = 100.0;
|
||||||
|
config.sfx_volume = 100.0;
|
||||||
|
|
||||||
|
/* default ROM directories */
|
||||||
|
#ifdef HW_RVL
|
||||||
|
sprintf (config.lastdir[TYPE_SD], "sd:%s/roms/", DEFAULT_PATH);
|
||||||
|
sprintf (config.lastdir[TYPE_USB], "usb:%s/roms/", DEFAULT_PATH);
|
||||||
|
sprintf (config.lastdir[TYPE_DVD], "dvd:%s/roms/", DEFAULT_PATH);
|
||||||
|
#else
|
||||||
|
sprintf (config.lastdir[TYPE_SD], "%s/roms/", DEFAULT_PATH);
|
||||||
|
sprintf (config.lastdir[TYPE_DVD], "dvd:%s/roms/", DEFAULT_PATH);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* try to restore settings from config file */
|
||||||
|
if (!config_load()) GUI_WaitPrompt("Info","Default Settings restored");
|
||||||
|
|
||||||
|
/* restore inputs */
|
||||||
|
input_init();
|
||||||
|
|
||||||
|
/* restore menu settings */
|
||||||
|
menu_configure();
|
||||||
|
}
|
||||||
|
|
105
source/gx/config.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* config.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX configuration file support
|
||||||
|
*
|
||||||
|
* Eke-Eke (2008)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _CONFIG_H_
|
||||||
|
#define _CONFIG_H_
|
||||||
|
|
||||||
|
#define CONFIG_VERSION "GENPLUS-GX 1.5.1"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Config Option
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char version[16];
|
||||||
|
uint8 hq_fm;
|
||||||
|
uint8 filter;
|
||||||
|
uint8 psgBoostNoise;
|
||||||
|
uint8 dac_bits;
|
||||||
|
uint8 ym2413_enabled;
|
||||||
|
int16 psg_preamp;
|
||||||
|
int16 fm_preamp;
|
||||||
|
int16 lp_range;
|
||||||
|
int16 low_freq;
|
||||||
|
int16 high_freq;
|
||||||
|
int16 lg;
|
||||||
|
int16 mg;
|
||||||
|
int16 hg;
|
||||||
|
float rolloff;
|
||||||
|
uint8 region_detect;
|
||||||
|
uint8 force_dtack;
|
||||||
|
uint8 addr_error;
|
||||||
|
uint8 tmss;
|
||||||
|
uint8 lock_on;
|
||||||
|
uint8 hot_swap;
|
||||||
|
uint8 romtype;
|
||||||
|
uint8 invert_mouse;
|
||||||
|
uint8 gun_cursor[2];
|
||||||
|
uint8 overscan;
|
||||||
|
uint8 ntsc;
|
||||||
|
uint8 render;
|
||||||
|
uint8 tv_mode;
|
||||||
|
uint8 bilinear;
|
||||||
|
uint8 aspect;
|
||||||
|
int16 xshift;
|
||||||
|
int16 yshift;
|
||||||
|
int16 xscale;
|
||||||
|
int16 yscale;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
uint32 trap;
|
||||||
|
float gamma;
|
||||||
|
#endif
|
||||||
|
t_input_config input[MAX_INPUTS];
|
||||||
|
uint16 pad_keymap[4][MAX_KEYS];
|
||||||
|
#ifdef HW_RVL
|
||||||
|
uint32 wpad_keymap[4*3][MAX_KEYS];
|
||||||
|
#endif
|
||||||
|
uint8 autoload;
|
||||||
|
uint8 autocheat;
|
||||||
|
uint8 s_auto;
|
||||||
|
uint8 s_default;
|
||||||
|
uint8 s_device;
|
||||||
|
uint8 autocheats;
|
||||||
|
int8 bg_type;
|
||||||
|
int8 bg_overlay;
|
||||||
|
int16 screen_w;
|
||||||
|
float bgm_volume;
|
||||||
|
float sfx_volume;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
char lastdir[3][MAXPATHLEN];
|
||||||
|
#else
|
||||||
|
char lastdir[2][MAXPATHLEN];
|
||||||
|
#endif
|
||||||
|
} t_config;
|
||||||
|
|
||||||
|
/* Global data */
|
||||||
|
t_config config;
|
||||||
|
|
||||||
|
|
||||||
|
extern void config_save(void);
|
||||||
|
extern void config_default(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _CONFIG_H_ */
|
||||||
|
|
394
source/gx/fileio/file_load.c
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
/*
|
||||||
|
* file_load.c
|
||||||
|
*
|
||||||
|
* ROM File loading support
|
||||||
|
*
|
||||||
|
* Eke-Eke (2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "file_load.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "history.h"
|
||||||
|
#include "unzip.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
|
||||||
|
#include <iso9660.h>
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#include <di/di.h>
|
||||||
|
#else
|
||||||
|
#include <ogc/dvd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* device root directories */
|
||||||
|
#ifdef HW_RVL
|
||||||
|
static const char rootdir[TYPE_RECENT][10] = {"sd:/","usb:/","dvd:/"};
|
||||||
|
#else
|
||||||
|
static const char rootdir[TYPE_RECENT][10] = {"/","dvd:/"};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* DVD interface */
|
||||||
|
#ifdef HW_RVL
|
||||||
|
static const DISC_INTERFACE* dvd = &__io_wiidvd;
|
||||||
|
#else
|
||||||
|
static const DISC_INTERFACE* dvd = &__io_gcdvd;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* current directory */
|
||||||
|
static char *fileDir;
|
||||||
|
|
||||||
|
/* current device */
|
||||||
|
static int deviceType = -1;
|
||||||
|
|
||||||
|
/* DVD status flag */
|
||||||
|
static u8 dvd_mounted = 0;
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* MountDVD
|
||||||
|
*
|
||||||
|
* return 0 on error, 1 on success
|
||||||
|
***************************************************************************/
|
||||||
|
static int MountDVD(void)
|
||||||
|
{
|
||||||
|
GUI_MsgBoxOpen("Information", "Mounting DVD ...",1);
|
||||||
|
|
||||||
|
/* check if DVD is already mounted */
|
||||||
|
if (dvd_mounted)
|
||||||
|
{
|
||||||
|
/* unmount DVD */
|
||||||
|
ISO9660_Unmount("dvd:");
|
||||||
|
dvd_mounted = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if disc is found */
|
||||||
|
if(!dvd->isInserted())
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","No Disc inserted !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mount DVD */
|
||||||
|
if(!ISO9660_Mount("dvd",dvd))
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Disc can not be read !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DVD is mounted */
|
||||||
|
dvd_mounted = 1;
|
||||||
|
|
||||||
|
GUI_MsgBoxClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* FileSortCallback (code by Marty Disibio)
|
||||||
|
*
|
||||||
|
* Quick sort callback to sort file entries with the following order:
|
||||||
|
* .
|
||||||
|
* ..
|
||||||
|
* <dirs>
|
||||||
|
* <files>
|
||||||
|
***************************************************************************/
|
||||||
|
static int FileSortCallback(const void *f1, const void *f2)
|
||||||
|
{
|
||||||
|
/* Special case for implicit directories */
|
||||||
|
if(((FILEENTRIES *)f1)->filename[0] == '.' || ((FILEENTRIES *)f2)->filename[0] == '.')
|
||||||
|
{
|
||||||
|
if(strcmp(((FILEENTRIES *)f1)->filename, ".") == 0) { return -1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f2)->filename, ".") == 0) { return 1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f1)->filename, "..") == 0) { return -1; }
|
||||||
|
if(strcmp(((FILEENTRIES *)f2)->filename, "..") == 0) { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If one is a file and one is a directory the directory is first. */
|
||||||
|
if(((FILEENTRIES *)f1)->flags == 1 && ((FILEENTRIES *)f2)->flags == 0) return -1;
|
||||||
|
if(((FILEENTRIES *)f1)->flags == 0 && ((FILEENTRIES *)f2)->flags == 1) return 1;
|
||||||
|
|
||||||
|
return stricmp(((FILEENTRIES *)f1)->filename, ((FILEENTRIES *)f2)->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* UpdateDirectory
|
||||||
|
*
|
||||||
|
* Update current browser directory
|
||||||
|
* return zero if going up while in root
|
||||||
|
* when going up, return previous dir name
|
||||||
|
***************************************************************************/
|
||||||
|
int UpdateDirectory(bool go_up, char *dirname)
|
||||||
|
{
|
||||||
|
/* go up to parent directory */
|
||||||
|
if (go_up)
|
||||||
|
{
|
||||||
|
/* special case */
|
||||||
|
if (deviceType == TYPE_RECENT) return 0;
|
||||||
|
|
||||||
|
/* check if we already are at root directory */
|
||||||
|
if (!strcmp(rootdir[deviceType], (const char *)fileDir)) return 0;
|
||||||
|
|
||||||
|
int size=0;
|
||||||
|
char temp[MAXPATHLEN];
|
||||||
|
|
||||||
|
/* determine last folder name length */
|
||||||
|
strcpy(temp, fileDir);
|
||||||
|
char *test= strtok(temp,"/");
|
||||||
|
while (test != NULL)
|
||||||
|
{
|
||||||
|
size = strlen(test);
|
||||||
|
strncpy(dirname,test,size);
|
||||||
|
dirname[size] = 0;
|
||||||
|
test = strtok(NULL,"/");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove last folder from path */
|
||||||
|
size = strlen(fileDir) - size;
|
||||||
|
fileDir[size - 1] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* by default, simply append folder name */
|
||||||
|
sprintf(fileDir, "%s%s/",fileDir, dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* ParseDirectory
|
||||||
|
*
|
||||||
|
* List files into one directory
|
||||||
|
***************************************************************************/
|
||||||
|
int ParseDirectory(void)
|
||||||
|
{
|
||||||
|
int nbfiles = 0;
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
struct stat filestat;
|
||||||
|
|
||||||
|
/* open directory */
|
||||||
|
DIR_ITER *dir = diropen(fileDir);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list files */
|
||||||
|
while ((dirnext(dir, filename, &filestat) == 0) && (nbfiles < MAXFILES))
|
||||||
|
{
|
||||||
|
if (filename[0] != '.')
|
||||||
|
{
|
||||||
|
memset(&filelist[nbfiles], 0, sizeof (FILEENTRIES));
|
||||||
|
sprintf(filelist[nbfiles].filename,"%s",filename);
|
||||||
|
filelist[nbfiles].flags = (filestat.st_mode & S_IFDIR) ? 1 : 0;
|
||||||
|
nbfiles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close directory */
|
||||||
|
dirclose(dir);
|
||||||
|
|
||||||
|
/* Sort the file list */
|
||||||
|
qsort(filelist, nbfiles, sizeof(FILEENTRIES), FileSortCallback);
|
||||||
|
|
||||||
|
return nbfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* LoadFile
|
||||||
|
*
|
||||||
|
* This function will load a BIN, SMD or ZIP file into the ROM buffer.
|
||||||
|
* This functions return the actual size of data copied into the buffer
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
int LoadFile(u8 *buffer, u32 selection, char *filename)
|
||||||
|
{
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
char *filepath;
|
||||||
|
int done = 0;
|
||||||
|
struct stat filestat;
|
||||||
|
|
||||||
|
/* file path */
|
||||||
|
filepath = (deviceType == TYPE_RECENT) ? history.entries[selection].filepath : fileDir;
|
||||||
|
|
||||||
|
/* full filename */
|
||||||
|
sprintf(fname, "%s%s", filepath, filelist[selection].filename);
|
||||||
|
|
||||||
|
/* retrieve file status */
|
||||||
|
if(stat(fname, &filestat) != 0)
|
||||||
|
{
|
||||||
|
/* only DVD hot swap is supported */
|
||||||
|
if (!strncmp(filepath, rootdir[TYPE_DVD], strlen(rootdir[TYPE_DVD])))
|
||||||
|
{
|
||||||
|
/* mount DVD */
|
||||||
|
if (!MountDVD()) return 0;
|
||||||
|
|
||||||
|
/* retrieve file status */
|
||||||
|
stat(fname, &filestat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get file length */
|
||||||
|
int length = filestat.st_size;
|
||||||
|
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
/* open file */
|
||||||
|
FILE *fd = fopen(fname, "rb");
|
||||||
|
if (!fd)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to open file !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read first data chunk */
|
||||||
|
unsigned char temp[FILECHUNK];
|
||||||
|
fread(temp, FILECHUNK, 1, fd);
|
||||||
|
fseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* Determine file type */
|
||||||
|
if (!IsZipFile ((char *) temp))
|
||||||
|
{
|
||||||
|
if (length > MAXROMSIZE)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","File is too large !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read file */
|
||||||
|
sprintf((char *)temp,"Loading %d bytes ...", length);
|
||||||
|
GUI_MsgBoxOpen("Information", (char *)temp, 1);
|
||||||
|
while (length > FILECHUNK)
|
||||||
|
{
|
||||||
|
fread(buffer + done, FILECHUNK, 1, fd);
|
||||||
|
length -= FILECHUNK;
|
||||||
|
done += FILECHUNK;
|
||||||
|
}
|
||||||
|
fread(buffer + done, length, 1, fd);
|
||||||
|
done += length;
|
||||||
|
GUI_MsgBoxClose();
|
||||||
|
|
||||||
|
/* update ROM filename (with extension) */
|
||||||
|
sprintf(filename, "%s", filelist[selection].filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* unzip file */
|
||||||
|
done = UnZipBuffer(buffer, fd, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close file */
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
/* add/move the file to the top of the history. */
|
||||||
|
history_add_file(filepath, filelist[selection].filename);
|
||||||
|
|
||||||
|
/* recent file list has changed */
|
||||||
|
if (deviceType == TYPE_RECENT) deviceType = -1;
|
||||||
|
|
||||||
|
/* return loaded size */
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* OpenDir
|
||||||
|
*
|
||||||
|
* Function to open a directory and load ROM file list.
|
||||||
|
****************************************************************************/
|
||||||
|
int OpenDirectory(int device)
|
||||||
|
{
|
||||||
|
int max = 0;
|
||||||
|
|
||||||
|
if (device == TYPE_RECENT)
|
||||||
|
{
|
||||||
|
/* fetch history list */
|
||||||
|
int i;
|
||||||
|
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
if(history.entries[i].filepath[0] > 0)
|
||||||
|
{
|
||||||
|
filelist[i].flags = 0;
|
||||||
|
strncpy(filelist[i].filename,history.entries[i].filename, MAXJOLIET-1);
|
||||||
|
filelist[i].filename[MAXJOLIET-1] = '\0';
|
||||||
|
max++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Found the end of the list. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* only DVD hot swap is supported */
|
||||||
|
if (device == TYPE_DVD)
|
||||||
|
{
|
||||||
|
/* try to access root directory */
|
||||||
|
DIR_ITER *dir = diropen(rootdir[TYPE_DVD]);
|
||||||
|
if (dir == NULL)
|
||||||
|
{
|
||||||
|
/* mount DVD */
|
||||||
|
if (!MountDVD()) return 0;
|
||||||
|
deviceType = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dirclose(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse last directory */
|
||||||
|
fileDir = config.lastdir[device];
|
||||||
|
max = ParseDirectory();
|
||||||
|
if (max <= 0)
|
||||||
|
{
|
||||||
|
/* parse root directory */
|
||||||
|
strcpy(fileDir, rootdir[device]);
|
||||||
|
max = ParseDirectory();
|
||||||
|
if (max < 0)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to open directory !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
deviceType = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 0)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","No files found !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if device type has changed */
|
||||||
|
if (device != deviceType)
|
||||||
|
{
|
||||||
|
/* reset current device type */
|
||||||
|
deviceType = device;
|
||||||
|
|
||||||
|
/* reset File selector */
|
||||||
|
ClearSelector(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
44
source/gx/fileio/file_load.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* file_fat.c
|
||||||
|
*
|
||||||
|
* FAT loading support
|
||||||
|
*
|
||||||
|
* Eke-Eke (2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FILE_FAT_H
|
||||||
|
#define _FILE_FAT_H
|
||||||
|
|
||||||
|
|
||||||
|
#define TYPE_SD (0)
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#define TYPE_USB (1)
|
||||||
|
#define TYPE_DVD (2)
|
||||||
|
#else
|
||||||
|
#define TYPE_DVD (1)
|
||||||
|
#endif
|
||||||
|
#define TYPE_RECENT (TYPE_DVD + 1)
|
||||||
|
|
||||||
|
#define FILECHUNK (2048)
|
||||||
|
|
||||||
|
extern int OpenDirectory(int device);
|
||||||
|
extern int UpdateDirectory(bool go_up, char *filename);
|
||||||
|
extern int ParseDirectory(void);
|
||||||
|
extern int LoadFile(u8* buffer,u32 selection, char *filename);
|
||||||
|
|
||||||
|
#endif
|
576
source/gx/fileio/file_slot.c
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
/*
|
||||||
|
* file_slot.c
|
||||||
|
*
|
||||||
|
* FAT and Memory Card SRAM/State slots managment
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "file_slot.h"
|
||||||
|
#include "file_load.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "saveicon.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libOGC CARD System Work Area
|
||||||
|
*/
|
||||||
|
static u8 SysArea[CARD_WORKAREA] ATTRIBUTE_ALIGN (32);
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* CardMount
|
||||||
|
*
|
||||||
|
* libOGC provides the CARD_Mount function, and it should be all you need.
|
||||||
|
* However, experience with previous emulators has taught me that you are
|
||||||
|
* better off doing a little bit more than that!
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
static int CardMount(int slot)
|
||||||
|
{
|
||||||
|
int tries = 0;
|
||||||
|
#if defined(HW_DOL)
|
||||||
|
*(unsigned long *) (0xCC006800) |= 1 << 13; /*** Disable Encryption ***/
|
||||||
|
#elif defined(HW_RVL)
|
||||||
|
*(unsigned long *) (0xCD006800) |= 1 << 13; /*** Disable Encryption ***/
|
||||||
|
#endif
|
||||||
|
while (tries < 10)
|
||||||
|
{
|
||||||
|
VIDEO_WaitVSync ();
|
||||||
|
if (CARD_Mount(slot, SysArea, NULL) == CARD_ERROR_READY)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
EXI_ProbeReset ();
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Slot Management
|
||||||
|
*
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void slot_autoload(int slot, int device)
|
||||||
|
{
|
||||||
|
if (!cart.romsize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SILENT = 1;
|
||||||
|
slot_load(slot, device);
|
||||||
|
SILENT = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void slot_autosave(int slot, int device)
|
||||||
|
{
|
||||||
|
if (!cart.romsize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* only save if SRAM changed */
|
||||||
|
if (!slot && (crc32(0, &sram.sram[0], 0x10000) == sram.crc))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SILENT = 1;
|
||||||
|
slot_save(slot, device);
|
||||||
|
SILENT = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void slot_autodetect(int slot, int device, t_slot *ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
memset(ptr,0,sizeof(t_slot));
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
/* FAT support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf (filename,"%s/saves/%s.gp%d", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf (filename,"%s/saves/%s.srm", DEFAULT_PATH, rom_filename);
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
/* Retrieve date & close */
|
||||||
|
struct stat filestat;
|
||||||
|
stat(filename, &filestat);
|
||||||
|
struct tm *timeinfo = localtime(&filestat.st_mtime);
|
||||||
|
ptr->year = 1900 + timeinfo->tm_year;
|
||||||
|
ptr->month = timeinfo->tm_mon;
|
||||||
|
ptr->day = timeinfo->tm_mday;
|
||||||
|
ptr->hour = timeinfo->tm_hour;
|
||||||
|
ptr->min = timeinfo->tm_min;
|
||||||
|
fclose(fp);
|
||||||
|
ptr->valid = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Memory Card support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf(filename,"MD-%04X.gp%d", rominfo.realchecksum, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf(filename,"MD-%04X.srm", rominfo.realchecksum);
|
||||||
|
|
||||||
|
/* Initialise the CARD system */
|
||||||
|
memset(&SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init("GENP", "00");
|
||||||
|
|
||||||
|
/* CARD slot */
|
||||||
|
device--;
|
||||||
|
|
||||||
|
/* Mount CARD */
|
||||||
|
if (CardMount(device))
|
||||||
|
{
|
||||||
|
/* Open file */
|
||||||
|
card_file CardFile;
|
||||||
|
if (CARD_Open(device, filename, &CardFile) == CARD_ERROR_READY)
|
||||||
|
{
|
||||||
|
/* Retrieve date & close */
|
||||||
|
card_stat CardStatus;
|
||||||
|
CARD_GetStatus(device, CardFile.filenum, &CardStatus);
|
||||||
|
time_t rawtime = CardStatus.time;
|
||||||
|
struct tm *timeinfo = localtime(&rawtime);
|
||||||
|
ptr->year = 1900 + timeinfo->tm_year;
|
||||||
|
ptr->month = timeinfo->tm_mon;
|
||||||
|
ptr->day = timeinfo->tm_mday;
|
||||||
|
ptr->hour = timeinfo->tm_hour;
|
||||||
|
ptr->min = timeinfo->tm_min;
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
ptr->valid = 1;
|
||||||
|
}
|
||||||
|
CARD_Unmount(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot_delete(int slot, int device)
|
||||||
|
{
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
/* FAT support */
|
||||||
|
if (slot > 0)
|
||||||
|
{
|
||||||
|
/* remove screenshot */
|
||||||
|
sprintf(filename,"%s/saves/%s__%d.png", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
remove(filename);
|
||||||
|
|
||||||
|
sprintf (filename,"%s/saves/%s.gp%d", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sprintf (filename,"%s/saves/%s.srm", DEFAULT_PATH, rom_filename);
|
||||||
|
|
||||||
|
/* Delete file */
|
||||||
|
ret = remove(filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Memory Card support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf(filename,"MD-%04X.gp%d", rominfo.realchecksum, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf(filename,"MD-%04X.srm", rominfo.realchecksum);
|
||||||
|
|
||||||
|
/* Initialise the CARD system */
|
||||||
|
memset(&SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init("GENP", "00");
|
||||||
|
|
||||||
|
/* CARD slot */
|
||||||
|
device--;
|
||||||
|
|
||||||
|
/* Mount CARD */
|
||||||
|
if (CardMount(device))
|
||||||
|
{
|
||||||
|
/* Delete file */
|
||||||
|
ret = CARD_Delete(device,filename);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot_load(int slot, int device)
|
||||||
|
{
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
int filesize, done = 0;
|
||||||
|
int offset = 0;
|
||||||
|
u8 *savebuffer;
|
||||||
|
|
||||||
|
if (slot > 0)
|
||||||
|
{
|
||||||
|
GUI_MsgBoxOpen("Information","Loading State ...",1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!sram.on)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","SRAM is disabled !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI_MsgBoxOpen("Information","Loading SRAM ...",1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
/* FAT support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf (filename,"%s/saves/%s.gp%d", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf (filename,"%s/saves/%s.srm", DEFAULT_PATH, rom_filename);
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to open file !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read size */
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
filesize = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* allocate buffer */
|
||||||
|
savebuffer = (u8 *)memalign(32,filesize);
|
||||||
|
if (!savebuffer)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to allocate memory !");
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read into buffer (2k blocks) */
|
||||||
|
while (filesize > FILECHUNK)
|
||||||
|
{
|
||||||
|
fread(savebuffer + done, FILECHUNK, 1, fp);
|
||||||
|
done += FILECHUNK;
|
||||||
|
filesize -= FILECHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read remaining bytes */
|
||||||
|
fread(savebuffer + done, filesize, 1, fp);
|
||||||
|
done += filesize;
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Memory Card support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf(filename, "MD-%04X.gp%d", rominfo.realchecksum, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf(filename, "MD-%04X.srm", rominfo.realchecksum);
|
||||||
|
|
||||||
|
/* Initialise the CARD system */
|
||||||
|
char action[64];
|
||||||
|
memset(&SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init("GENP", "00");
|
||||||
|
|
||||||
|
/* CARD slot */
|
||||||
|
device--;
|
||||||
|
|
||||||
|
/* Attempt to mount the card */
|
||||||
|
if (!CardMount(device))
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to mount memory card");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the sector size */
|
||||||
|
u32 SectorSize = 0;
|
||||||
|
int CardError = CARD_GetSectorSize(device, &SectorSize);
|
||||||
|
if (!SectorSize)
|
||||||
|
{
|
||||||
|
sprintf(action, "Invalid sector size (%d)", CardError);
|
||||||
|
GUI_WaitPrompt("Error",action);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
card_file CardFile;
|
||||||
|
CardError = CARD_Open(device, filename, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
sprintf(action, "Unable to open file (%d)", CardError);
|
||||||
|
GUI_WaitPrompt("Error",action);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve file size */
|
||||||
|
filesize = CardFile.len;
|
||||||
|
if (filesize % SectorSize)
|
||||||
|
filesize = ((filesize / SectorSize) + 1) * SectorSize;
|
||||||
|
|
||||||
|
/* Allocate buffer */
|
||||||
|
savebuffer = (u8 *)memalign(32,filesize);
|
||||||
|
if (!savebuffer)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to allocate memory !");
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read file sectors */
|
||||||
|
while (filesize > 0)
|
||||||
|
{
|
||||||
|
CARD_Read(&CardFile, &savebuffer[done], SectorSize, done);
|
||||||
|
done += SectorSize;
|
||||||
|
filesize -= SectorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
offset = 2112;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot > 0)
|
||||||
|
{
|
||||||
|
/* Load state */
|
||||||
|
if (state_load(&savebuffer[offset]) <= 0)
|
||||||
|
{
|
||||||
|
free(savebuffer);
|
||||||
|
GUI_WaitPrompt("Error","Invalid state file !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Load SRAM & update CRC */
|
||||||
|
memcpy(sram.sram, &savebuffer[offset], 0x10000);
|
||||||
|
sram.crc = crc32(0, sram.sram, 0x10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(savebuffer);
|
||||||
|
GUI_MsgBoxClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int slot_save(int slot, int device)
|
||||||
|
{
|
||||||
|
char filename[MAXPATHLEN];
|
||||||
|
int filesize, done = 0;
|
||||||
|
int offset = device ? 2112 : 0;
|
||||||
|
u8 *savebuffer;
|
||||||
|
|
||||||
|
if (slot > 0)
|
||||||
|
{
|
||||||
|
/* allocate buffer */
|
||||||
|
savebuffer = (u8 *)memalign(32,STATE_SIZE);
|
||||||
|
if (!savebuffer)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to allocate memory !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI_MsgBoxOpen("Information","Saving State ...",1);
|
||||||
|
filesize = state_save(&savebuffer[offset]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!sram.on)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","SRAM is disabled !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate buffer */
|
||||||
|
savebuffer = (u8 *)memalign(32,0x10000+offset);
|
||||||
|
if (!savebuffer)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to allocate memory !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI_MsgBoxOpen("Information","Saving SRAM ...",1);
|
||||||
|
memcpy(&savebuffer[offset], sram.sram, 0x10000);
|
||||||
|
sram.crc = crc32(0, sram.sram, 0x10000);
|
||||||
|
filesize = 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
/* FAT support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf(filename, "%s/saves/%s.gp%d", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf(filename, "%s/saves/%s.srm", DEFAULT_PATH, rom_filename);
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
FILE *fp = fopen(filename, "wb");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to open file !");
|
||||||
|
free(savebuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write from buffer (2k blocks) */
|
||||||
|
while (filesize > FILECHUNK)
|
||||||
|
{
|
||||||
|
fwrite(savebuffer + done, FILECHUNK, 1, fp);
|
||||||
|
done += FILECHUNK;
|
||||||
|
filesize -= FILECHUNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write remaining bytes */
|
||||||
|
fwrite(savebuffer + done, filesize, 1, fp);
|
||||||
|
done += filesize;
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Memory Card support */
|
||||||
|
if (slot > 0)
|
||||||
|
sprintf(filename, "MD-%04X.gp%d", rominfo.realchecksum, slot - 1);
|
||||||
|
else
|
||||||
|
sprintf(filename, "MD-%04X.srm", rominfo.realchecksum);
|
||||||
|
|
||||||
|
/* Initialise the CARD system */
|
||||||
|
char action[64];
|
||||||
|
memset(&SysArea, 0, CARD_WORKAREA);
|
||||||
|
CARD_Init("GENP", "00");
|
||||||
|
|
||||||
|
/* CARD slot */
|
||||||
|
device--;
|
||||||
|
|
||||||
|
/* Attempt to mount the card */
|
||||||
|
if (!CardMount(device))
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to mount memory card");
|
||||||
|
free(savebuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the sector size */
|
||||||
|
u32 SectorSize = 0;
|
||||||
|
int CardError = CARD_GetSectorSize(device, &SectorSize);
|
||||||
|
if (!SectorSize)
|
||||||
|
{
|
||||||
|
sprintf(action, "Invalid sector size (%d)", CardError);
|
||||||
|
GUI_WaitPrompt("Error",action);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
free(savebuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build the output buffer */
|
||||||
|
char comment[2][32] = { {"Genesis Plus GX"}, {"SRAM Save"} };
|
||||||
|
strcpy (comment[1], filename);
|
||||||
|
memcpy (&savebuffer[0], &icon, 2048);
|
||||||
|
memcpy (&savebuffer[2048], &comment[0], 64);
|
||||||
|
|
||||||
|
/* Adjust file size */
|
||||||
|
filesize += 2112;
|
||||||
|
if (filesize % SectorSize)
|
||||||
|
filesize = ((filesize / SectorSize) + 1) * SectorSize;
|
||||||
|
|
||||||
|
/* Check if file already exists */
|
||||||
|
card_file CardFile;
|
||||||
|
if (CARD_Open(device, filename, &CardFile) == CARD_ERROR_READY)
|
||||||
|
{
|
||||||
|
int size = filesize - CardFile.len;
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
memset(&CardFile,0,sizeof(CardFile));
|
||||||
|
|
||||||
|
/* Check file new size */
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
CardError = CARD_Create(device, "TEMP", size, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
sprintf(action, "Unable to increase file size (%d)", CardError);
|
||||||
|
GUI_WaitPrompt("Error",action);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
free(savebuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete temporary file */
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
memset(&CardFile,0,sizeof(CardFile));
|
||||||
|
CARD_Delete(device, "TEMP");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete previously existing file */
|
||||||
|
CARD_Delete(device, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new file */
|
||||||
|
CardError = CARD_Create(device, filename, filesize, &CardFile);
|
||||||
|
if (CardError)
|
||||||
|
{
|
||||||
|
sprintf(action, "Unable to create file (%d)", CardError);
|
||||||
|
GUI_WaitPrompt("Error",action);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
free(savebuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update file informations */
|
||||||
|
time_t rawtime;
|
||||||
|
time(&rawtime);
|
||||||
|
card_stat CardStatus;
|
||||||
|
CARD_GetStatus(device, CardFile.filenum, &CardStatus);
|
||||||
|
CardStatus.icon_addr = 0x0;
|
||||||
|
CardStatus.icon_fmt = 2;
|
||||||
|
CardStatus.icon_speed = 1;
|
||||||
|
CardStatus.comment_addr = 2048;
|
||||||
|
CardStatus.time = rawtime;
|
||||||
|
CARD_SetStatus(device, CardFile.filenum, &CardStatus);
|
||||||
|
|
||||||
|
/* Write file sectors */
|
||||||
|
while (filesize > 0)
|
||||||
|
{
|
||||||
|
CARD_Write(&CardFile, &savebuffer[done], SectorSize, done);
|
||||||
|
filesize -= SectorSize;
|
||||||
|
done += SectorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close file */
|
||||||
|
CARD_Close(&CardFile);
|
||||||
|
CARD_Unmount(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI_MsgBoxClose();
|
||||||
|
free(savebuffer);
|
||||||
|
|
||||||
|
/* Save screenshot */
|
||||||
|
if (slot && !device)
|
||||||
|
{
|
||||||
|
sprintf(filename,"%s/saves/%s__%d.png", DEFAULT_PATH, rom_filename, slot - 1);
|
||||||
|
gxSaveScreenshot(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
45
source/gx/fileio/file_slot.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* file_slot.c
|
||||||
|
*
|
||||||
|
* FAT and Memory Card SRAM/Savestate files managment
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FILE_SLOT_H
|
||||||
|
#define _FILE_SLOT_H
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int valid;
|
||||||
|
u16 year;
|
||||||
|
u8 month;
|
||||||
|
u8 day;
|
||||||
|
u8 hour;
|
||||||
|
u8 min;
|
||||||
|
} t_slot;
|
||||||
|
|
||||||
|
extern void slot_autoload(int slot, int device);
|
||||||
|
extern void slot_autosave(int slot, int device);
|
||||||
|
extern void slot_autodetect(int slot, int device, t_slot *ptr);
|
||||||
|
extern int slot_delete(int slot, int device);
|
||||||
|
extern int slot_load(int slot, int device);
|
||||||
|
extern int slot_save(int slot, int device);
|
||||||
|
|
||||||
|
#endif
|
115
source/gx/fileio/history.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* history.c
|
||||||
|
*
|
||||||
|
* Generic ROM history list managment
|
||||||
|
*
|
||||||
|
* Martin Disibio (6/17/08)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "history.h"
|
||||||
|
|
||||||
|
t_history history;
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* history_add_file
|
||||||
|
*
|
||||||
|
* Adds the given file path to the top of the history list, shifting each
|
||||||
|
* existing entry in the history down one place. If given file path is
|
||||||
|
* already in the list then the existing entry is (in effect) moved to the
|
||||||
|
* top instead.
|
||||||
|
****************************************************************************/
|
||||||
|
void history_add_file(char *filepath, char *filename)
|
||||||
|
{
|
||||||
|
/* Create the new entry for this path. */
|
||||||
|
t_history_entry newentry;
|
||||||
|
strncpy(newentry.filepath, filepath, MAXJOLIET - 1);
|
||||||
|
strncpy(newentry.filename, filename, MAXJOLIET - 1);
|
||||||
|
newentry.filepath[MAXJOLIET - 1] = '\0';
|
||||||
|
newentry.filename[MAXJOLIET - 1] = '\0';
|
||||||
|
|
||||||
|
t_history_entry oldentry; /* Old entry is the one being shuffled down a spot. */
|
||||||
|
t_history_entry currentry; /* Curr entry is the one that just replaced old path. */
|
||||||
|
|
||||||
|
/* Initially set curr entry to the new value. */
|
||||||
|
memcpy(¤try, &newentry, sizeof(t_history_entry));
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
/* Save off the next entry. */
|
||||||
|
memcpy(&oldentry, &history.entries[i], sizeof(t_history_entry));
|
||||||
|
|
||||||
|
/* Overwrite with the previous entry. */
|
||||||
|
memcpy(&history.entries[i], ¤try, sizeof(t_history_entry));
|
||||||
|
|
||||||
|
/* Switch the old entry to the curr entry now. */
|
||||||
|
memcpy(¤try, &oldentry, sizeof(t_history_entry));
|
||||||
|
|
||||||
|
/* If the entry in the list at this spot matches
|
||||||
|
the new entry then do nothing and let this
|
||||||
|
entry get deleted. */
|
||||||
|
if(strcmp(newentry.filepath, currentry.filepath) == 0 && strcmp(newentry.filename, currentry.filename) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now save to disk */
|
||||||
|
history_save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void history_save()
|
||||||
|
{
|
||||||
|
/* open file */
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
sprintf (fname, "%s/history.ini", DEFAULT_PATH);
|
||||||
|
FILE *fp = fopen(fname, "wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
/* write file */
|
||||||
|
fwrite(&history, sizeof(history), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void history_load(void)
|
||||||
|
{
|
||||||
|
/* open file */
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
sprintf (fname, "%s/history.ini", DEFAULT_PATH);
|
||||||
|
FILE *fp = fopen(fname, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
/* read file */
|
||||||
|
fread(&history, sizeof(history), 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void history_default(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i < NUM_HISTORY_ENTRIES; i++)
|
||||||
|
memset(&history.entries[i], 0, sizeof(t_history_entry));
|
||||||
|
|
||||||
|
/* restore history */
|
||||||
|
history_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
52
source/gx/fileio/history.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* history.c
|
||||||
|
*
|
||||||
|
* Generic ROM history list managment
|
||||||
|
*
|
||||||
|
* Martin Disibio (6/17/08)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _HISTORY_H
|
||||||
|
#define _HISTORY_H
|
||||||
|
|
||||||
|
#include "filesel.h"
|
||||||
|
|
||||||
|
#define NUM_HISTORY_ENTRIES (10)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* ROM Play History
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char filepath[MAXJOLIET];
|
||||||
|
char filename[MAXJOLIET];
|
||||||
|
} t_history_entry;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
t_history_entry entries[NUM_HISTORY_ENTRIES];
|
||||||
|
} t_history;
|
||||||
|
|
||||||
|
extern t_history history;
|
||||||
|
extern void history_add_file(char *filepath, char *filename);
|
||||||
|
extern void history_save(void);
|
||||||
|
extern void history_load(void);
|
||||||
|
extern void history_default(void);
|
||||||
|
|
||||||
|
#endif
|
201
source/gx/fileio/unzip.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* unzip.c
|
||||||
|
*
|
||||||
|
* Zip Support
|
||||||
|
*
|
||||||
|
* Only partial support is included, in that only the first file within the archive
|
||||||
|
* is considered to be a ROM image.
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PKWare Zip Header - adopted into zip standard
|
||||||
|
*/
|
||||||
|
#define PKZIPID 0x504b0304
|
||||||
|
#define MAXROM 0x500000
|
||||||
|
#define ZIPCHUNK 2048
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip file header definition
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int zipid __attribute__ ((__packed__)); // 0x04034b50
|
||||||
|
unsigned short zipversion __attribute__ ((__packed__));
|
||||||
|
unsigned short zipflags __attribute__ ((__packed__));
|
||||||
|
unsigned short compressionMethod __attribute__ ((__packed__));
|
||||||
|
unsigned short lastmodtime __attribute__ ((__packed__));
|
||||||
|
unsigned short lastmoddate __attribute__ ((__packed__));
|
||||||
|
unsigned int crc32 __attribute__ ((__packed__));
|
||||||
|
unsigned int compressedSize __attribute__ ((__packed__));
|
||||||
|
unsigned int uncompressedSize __attribute__ ((__packed__));
|
||||||
|
unsigned short filenameLength __attribute__ ((__packed__));
|
||||||
|
unsigned short extraDataLength __attribute__ ((__packed__));
|
||||||
|
} PKZIPHEADER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zip files are stored little endian
|
||||||
|
* Support functions for short and int types
|
||||||
|
*/
|
||||||
|
static inline u32 FLIP32 (u32 b)
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
c = (b & 0xff000000) >> 24;
|
||||||
|
c |= (b & 0xff0000) >> 8;
|
||||||
|
c |= (b & 0xff00) << 8;
|
||||||
|
c |= (b & 0xff) << 24;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u16 FLIP16 (u16 b)
|
||||||
|
{
|
||||||
|
u16 c;
|
||||||
|
c = (b & 0xff00) >> 8;
|
||||||
|
c |= (b & 0xff) << 8;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* IsZipFile
|
||||||
|
*
|
||||||
|
* Returns TRUE when PKZIPID is first four characters of buffer
|
||||||
|
****************************************************************************/
|
||||||
|
int IsZipFile (char *buffer)
|
||||||
|
{
|
||||||
|
unsigned int *check;
|
||||||
|
check = (unsigned int *) buffer;
|
||||||
|
if (check[0] == PKZIPID) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* UnZipBuffer
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int UnZipBuffer (unsigned char *outbuffer, FILE *fd, char *filename)
|
||||||
|
{
|
||||||
|
PKZIPHEADER pkzip;
|
||||||
|
int zipoffset = 0;
|
||||||
|
int zipchunk = 0;
|
||||||
|
char out[ZIPCHUNK];
|
||||||
|
z_stream zs;
|
||||||
|
int res;
|
||||||
|
int bufferoffset = 0;
|
||||||
|
int have = 0;
|
||||||
|
char readbuffer[ZIPCHUNK];
|
||||||
|
char msg[64];
|
||||||
|
|
||||||
|
/*** Read Zip Header ***/
|
||||||
|
fread(readbuffer, ZIPCHUNK, 1, fd);
|
||||||
|
|
||||||
|
/*** Copy PKZip header to local, used as info ***/
|
||||||
|
memcpy (&pkzip, &readbuffer, sizeof (PKZIPHEADER));
|
||||||
|
|
||||||
|
if (FLIP32 (pkzip.uncompressedSize) > MAXROMSIZE)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","File is too large !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (msg, "Unzipping %d bytes ...", FLIP32 (pkzip.uncompressedSize));
|
||||||
|
GUI_MsgBoxOpen("Information",msg,1);
|
||||||
|
|
||||||
|
/*** Prepare the zip stream ***/
|
||||||
|
memset (&zs, 0, sizeof (z_stream));
|
||||||
|
zs.zalloc = Z_NULL;
|
||||||
|
zs.zfree = Z_NULL;
|
||||||
|
zs.opaque = Z_NULL;
|
||||||
|
zs.avail_in = 0;
|
||||||
|
zs.next_in = Z_NULL;
|
||||||
|
res = inflateInit2 (&zs, -MAX_WBITS);
|
||||||
|
|
||||||
|
if (res != Z_OK)
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Unable to unzip file !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Get file name (first file) ***/
|
||||||
|
int size = FLIP16 (pkzip.filenameLength);
|
||||||
|
if (size > 255) size = 255;
|
||||||
|
strncpy(filename, &readbuffer[sizeof(PKZIPHEADER)], size);
|
||||||
|
filename[size] = 0;
|
||||||
|
|
||||||
|
/*** Set ZipChunk for first pass ***/
|
||||||
|
zipoffset = (sizeof (PKZIPHEADER) + size + FLIP16 (pkzip.extraDataLength));
|
||||||
|
zipchunk = ZIPCHUNK - zipoffset;
|
||||||
|
|
||||||
|
/*** Now do it! ***/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
zs.avail_in = zipchunk;
|
||||||
|
zs.next_in = (Bytef *) &readbuffer[zipoffset];
|
||||||
|
|
||||||
|
/*** Now inflate until input buffer is exhausted ***/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
zs.avail_out = ZIPCHUNK;
|
||||||
|
zs.next_out = (Bytef *) &out;
|
||||||
|
res = inflate (&zs, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
if (res == Z_MEM_ERROR)
|
||||||
|
{
|
||||||
|
inflateEnd (&zs);
|
||||||
|
GUI_WaitPrompt("Error","Unable to unzip file !");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
have = ZIPCHUNK - zs.avail_out;
|
||||||
|
if (have)
|
||||||
|
{
|
||||||
|
/*** Copy to normal block buffer ***/
|
||||||
|
memcpy (&outbuffer[bufferoffset], &out, have);
|
||||||
|
bufferoffset += have;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (zs.avail_out == 0);
|
||||||
|
|
||||||
|
/*** Readup the next 2k block ***/
|
||||||
|
zipoffset = 0;
|
||||||
|
zipchunk = ZIPCHUNK;
|
||||||
|
fread(readbuffer, ZIPCHUNK, 1, fd);
|
||||||
|
}
|
||||||
|
while (res != Z_STREAM_END);
|
||||||
|
|
||||||
|
inflateEnd (&zs);
|
||||||
|
GUI_MsgBoxClose();
|
||||||
|
|
||||||
|
if (res == Z_STREAM_END)
|
||||||
|
{
|
||||||
|
if (FLIP32 (pkzip.uncompressedSize) == (u32) bufferoffset)
|
||||||
|
return bufferoffset;
|
||||||
|
else
|
||||||
|
return FLIP32 (pkzip.uncompressedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
35
source/gx/fileio/unzip.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* unzip.c
|
||||||
|
*
|
||||||
|
* Zip Support
|
||||||
|
*
|
||||||
|
* Only partial support is included, in that only the first file within the archive
|
||||||
|
* is considered to be a ROM image.
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _UNZIP_H_
|
||||||
|
#define _UNZIP_H_
|
||||||
|
|
||||||
|
extern int IsZipFile (char *buffer);
|
||||||
|
int UnZipBuffer (unsigned char *outbuffer, FILE *fd, char *filename);
|
||||||
|
|
||||||
|
#endif
|
1260
source/gx/gui/cheats.c
Normal file
32
source/gx/gui/cheats.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* cheats.c
|
||||||
|
*
|
||||||
|
* Cheats menu
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _CHEATS_H
|
||||||
|
#define _CHEATS_H
|
||||||
|
|
||||||
|
extern void CheatMenu(void);
|
||||||
|
extern void CheatLoad(void);
|
||||||
|
extern void CheatUpdate(void);
|
||||||
|
|
||||||
|
#endif
|
578
source/gx/gui/filesel.c
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
/*
|
||||||
|
* filesel.c
|
||||||
|
*
|
||||||
|
* ROM File Browser
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "filesel.h"
|
||||||
|
#include "font.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "file_load.h"
|
||||||
|
#include "file_slot.h"
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BG_COLOR_1 {0x49,0x49,0x49,0xff}
|
||||||
|
#define BG_COLOR_2 {0x66,0x66,0x66,0xff}
|
||||||
|
|
||||||
|
extern const u8 Browser_dir_png[];
|
||||||
|
extern const u8 Snap_empty_png[];
|
||||||
|
extern const u8 Snap_frame_png[];
|
||||||
|
|
||||||
|
FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
static int offset = 0;
|
||||||
|
static int selection = 0;
|
||||||
|
static int maxfiles = 0;
|
||||||
|
static int string_offset = 0;
|
||||||
|
static char prev_folder[MAXJOLIET];
|
||||||
|
static void selector_cb(void);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Buttons data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
static butn_data arrow_up_data =
|
||||||
|
{
|
||||||
|
{NULL,NULL},
|
||||||
|
{Button_up_png,Button_up_over_png}
|
||||||
|
};
|
||||||
|
|
||||||
|
static butn_data arrow_down_data =
|
||||||
|
{
|
||||||
|
{NULL,NULL},
|
||||||
|
{Button_down_png,Button_down_over_png}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Arrows button */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static gui_butn arrow_up = {&arrow_up_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{0,0,0,0},14,76,360,32};
|
||||||
|
static gui_butn arrow_down = {&arrow_down_data,BUTTON_VISIBLE|BUTTON_ACTIVE|BUTTON_OVER_SFX,{0,0,0,0},14,368,360,32};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI helpers */
|
||||||
|
/*****************************************************************************/
|
||||||
|
static gui_item action_cancel =
|
||||||
|
{
|
||||||
|
NULL,Key_B_png,"","Previous Directory",10,422,28,28
|
||||||
|
};
|
||||||
|
|
||||||
|
static gui_item action_select =
|
||||||
|
{
|
||||||
|
NULL,Key_A_png,"","Load ROM file",602,422,28,28
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Background images */
|
||||||
|
/*****************************************************************************/
|
||||||
|
static gui_image bg_filesel[10] =
|
||||||
|
{
|
||||||
|
{NULL,Bg_main_png,IMAGE_VISIBLE,374,140,284,288,255},
|
||||||
|
{NULL,Bg_overlay_png,IMAGE_VISIBLE|IMAGE_REPEAT,0,0,640,480,255},
|
||||||
|
{NULL,Banner_top_png,IMAGE_VISIBLE,0,0,640,108,255},
|
||||||
|
{NULL,Banner_bottom_png,IMAGE_VISIBLE,0,380,640,100,255},
|
||||||
|
{NULL,Main_logo_png,IMAGE_VISIBLE,466,40,152,44,255},
|
||||||
|
{NULL,Frame_s1_png,IMAGE_VISIBLE,8,70,372,336,152},
|
||||||
|
{NULL,Frame_s2_png,0,384,264,248,140,152},
|
||||||
|
{NULL,Snap_empty_png,IMAGE_VISIBLE,422,114,164,116,255},
|
||||||
|
{NULL,NULL,0,424,116,160,112,255},
|
||||||
|
{NULL,Snap_frame_png,IMAGE_VISIBLE,388,112,236,148,255}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Descriptor */
|
||||||
|
/*****************************************************************************/
|
||||||
|
static gui_menu menu_selector =
|
||||||
|
{
|
||||||
|
"Game Selection",
|
||||||
|
-1,-1,
|
||||||
|
0,0,10,0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
bg_filesel,
|
||||||
|
{&action_cancel, &action_select},
|
||||||
|
{&arrow_up,&arrow_down},
|
||||||
|
selector_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void selector_cb(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char text[MAXPATHLEN];
|
||||||
|
int yoffset = 108;
|
||||||
|
|
||||||
|
/* Initialize directory icon */
|
||||||
|
gui_image dir_icon;
|
||||||
|
dir_icon.texture = gxTextureOpenPNG(Browser_dir_png,0);
|
||||||
|
dir_icon.w = dir_icon.texture->width;
|
||||||
|
dir_icon.h = dir_icon.texture->height;
|
||||||
|
dir_icon.x = 26;
|
||||||
|
dir_icon.y = (26 - dir_icon.h)/2;
|
||||||
|
|
||||||
|
/* Initialize selection bar */
|
||||||
|
gui_image bar_over;
|
||||||
|
bar_over.texture = gxTextureOpenPNG(Overlay_bar_png,0);
|
||||||
|
bar_over.w = bar_over.texture->width;
|
||||||
|
bar_over.h = bar_over.texture->height;
|
||||||
|
bar_over.x = 16;
|
||||||
|
bar_over.y = (26 - bar_over.h)/2;
|
||||||
|
|
||||||
|
/* Draw browser array */
|
||||||
|
gxDrawRectangle(15, 108, 358, 26, 127, (GXColor)BG_COLOR_1);
|
||||||
|
gxDrawRectangle(15, 134, 358, 26, 127, (GXColor)BG_COLOR_2);
|
||||||
|
gxDrawRectangle(15, 160, 358, 26, 127, (GXColor)BG_COLOR_1);
|
||||||
|
gxDrawRectangle(15, 186, 358, 26, 127, (GXColor)BG_COLOR_2);
|
||||||
|
gxDrawRectangle(15, 212, 358, 26, 127, (GXColor)BG_COLOR_1);
|
||||||
|
gxDrawRectangle(15, 238, 358, 26, 127, (GXColor)BG_COLOR_2);
|
||||||
|
gxDrawRectangle(15, 264, 358, 26, 127, (GXColor)BG_COLOR_1);
|
||||||
|
gxDrawRectangle(15, 290, 358, 26, 127, (GXColor)BG_COLOR_2);
|
||||||
|
gxDrawRectangle(15, 316, 358, 26, 127, (GXColor)BG_COLOR_1);
|
||||||
|
gxDrawRectangle(15, 342, 358, 26, 127, (GXColor)BG_COLOR_2);
|
||||||
|
|
||||||
|
/* Draw Files list */
|
||||||
|
for (i = offset; (i < (offset + 10)) && (i < maxfiles); i++)
|
||||||
|
{
|
||||||
|
if (i == selection)
|
||||||
|
{
|
||||||
|
/* selection bar */
|
||||||
|
gxDrawTexture(bar_over.texture,bar_over.x,yoffset+bar_over.y,bar_over.w,bar_over.h,255);
|
||||||
|
|
||||||
|
/* scrolling text */
|
||||||
|
if ((string_offset/10) >= strlen(filelist[i].filename))
|
||||||
|
{
|
||||||
|
string_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string_offset)
|
||||||
|
{
|
||||||
|
sprintf(text,"%s ",filelist[i].filename+string_offset/10);
|
||||||
|
strncat(text, filelist[i].filename, string_offset/10);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(text, filelist[i].filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print text */
|
||||||
|
if (filelist[i].flags)
|
||||||
|
{
|
||||||
|
/* directory icon */
|
||||||
|
gxDrawTexture(dir_icon.texture,dir_icon.x,yoffset+dir_icon.y,dir_icon.w,dir_icon.h,255);
|
||||||
|
if (FONT_write(text,18,dir_icon.x+dir_icon.w+6,yoffset+22,bar_over.w-dir_icon.w-26,(GXColor)WHITE))
|
||||||
|
{
|
||||||
|
/* string is too large -> scroll text */
|
||||||
|
string_offset ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FONT_write(text,18,dir_icon.x,yoffset+22,bar_over.w-20,(GXColor)WHITE))
|
||||||
|
{
|
||||||
|
/* text scrolling */
|
||||||
|
string_offset ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (filelist[i].flags)
|
||||||
|
{
|
||||||
|
/* directory icon */
|
||||||
|
gxDrawTexture(dir_icon.texture,dir_icon.x,yoffset+dir_icon.y,dir_icon.w,dir_icon.h,255);
|
||||||
|
FONT_write(filelist[i].filename,18,dir_icon.x+dir_icon.w+6,yoffset+22,bar_over.w-dir_icon.w-26,(GXColor)WHITE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FONT_write(filelist[i].filename,18,dir_icon.x,yoffset+22,bar_over.w-20,(GXColor)WHITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yoffset += 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
gxTextureClose(&bar_over.texture);
|
||||||
|
gxTextureClose(&dir_icon.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* FileSelector
|
||||||
|
*
|
||||||
|
* Browse directories and select a file from the file listing
|
||||||
|
* return ROM size
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
int FileSelector(void)
|
||||||
|
{
|
||||||
|
short p;
|
||||||
|
int i;
|
||||||
|
int size = 0;
|
||||||
|
int old = -1;
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
char text[MAXPATHLEN];
|
||||||
|
FILE *xml,*snap;
|
||||||
|
gui_menu *m = &menu_selector;
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
int x,y;
|
||||||
|
gui_butn *button;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* background type */
|
||||||
|
if (config.bg_type > 0)
|
||||||
|
{
|
||||||
|
bg_filesel[0].state &= ~IMAGE_REPEAT;
|
||||||
|
bg_filesel[0].data = (config.bg_type > 1) ? Bg_main_png : Bg_main_2_png;
|
||||||
|
bg_filesel[0].x = 374;
|
||||||
|
bg_filesel[0].y = 140;
|
||||||
|
bg_filesel[0].w = 284;
|
||||||
|
bg_filesel[0].h = 288;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bg_filesel[0].state |= IMAGE_REPEAT;
|
||||||
|
bg_filesel[0].data = Bg_layer_png;
|
||||||
|
bg_filesel[0].x = 0;
|
||||||
|
bg_filesel[0].y = 0;
|
||||||
|
bg_filesel[0].w = 640;
|
||||||
|
bg_filesel[0].h = 480;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* background overlay */
|
||||||
|
if (config.bg_overlay)
|
||||||
|
{
|
||||||
|
bg_filesel[1].state |= IMAGE_VISIBLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bg_filesel[1].state &= ~IMAGE_VISIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize Menu */
|
||||||
|
GUI_InitMenu(m);
|
||||||
|
string_offset = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* ROM file snapshot/database */
|
||||||
|
if (old != selection)
|
||||||
|
{
|
||||||
|
old = selection;
|
||||||
|
string_offset = 0;
|
||||||
|
|
||||||
|
/* delete previous texture if any */
|
||||||
|
gxTextureClose(&bg_filesel[8].texture);
|
||||||
|
bg_filesel[8].state &= ~IMAGE_VISIBLE;
|
||||||
|
bg_filesel[6].state &= ~IMAGE_VISIBLE;
|
||||||
|
|
||||||
|
if (!filelist[selection].flags)
|
||||||
|
{
|
||||||
|
/* get ROM filename without extension */
|
||||||
|
sprintf (text, "%s", filelist[selection].filename);
|
||||||
|
int i = strlen(text) - 1;
|
||||||
|
while ((i > 0) && (text[i] != '.')) i--;
|
||||||
|
if (i > 0) text[i] = 0;
|
||||||
|
|
||||||
|
/* ROM database informations */
|
||||||
|
sprintf (fname, "%s/db/%s.xml", DEFAULT_PATH, text);
|
||||||
|
xml = fopen(fname, "rb");
|
||||||
|
if (xml)
|
||||||
|
{
|
||||||
|
bg_filesel[6].state |= IMAGE_VISIBLE;
|
||||||
|
fclose(xml); /* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open screenshot file */
|
||||||
|
sprintf (fname, "%s/snaps/%s.png", DEFAULT_PATH, text);
|
||||||
|
snap = fopen(fname, "rb");
|
||||||
|
if (snap)
|
||||||
|
{
|
||||||
|
bg_filesel[8].texture = gxTextureOpenPNG(0,snap);
|
||||||
|
if (bg_filesel[8].texture)
|
||||||
|
bg_filesel[8].state |= IMAGE_VISIBLE;
|
||||||
|
fclose(snap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update helper */
|
||||||
|
if (m->selected != -1)
|
||||||
|
{
|
||||||
|
/* out of focus */
|
||||||
|
strcpy(action_select.comment,"");
|
||||||
|
}
|
||||||
|
else if (filelist[selection].flags)
|
||||||
|
{
|
||||||
|
/* this is a directory */
|
||||||
|
strcpy(action_select.comment,"Open Directory");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* this is a file */
|
||||||
|
strcpy(action_select.comment,"Load ROM File");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw menu*/
|
||||||
|
GUI_DrawMenu(m);
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
if (Shutdown)
|
||||||
|
{
|
||||||
|
gxTextureClose(&w_pointer);
|
||||||
|
GUI_DeleteMenu(m);
|
||||||
|
GUI_FadeOut();
|
||||||
|
shutdown();
|
||||||
|
SYS_ResetSystem(SYS_POWEROFF, 0, 0);
|
||||||
|
}
|
||||||
|
else if (m_input.ir.valid)
|
||||||
|
{
|
||||||
|
/* get cursor position */
|
||||||
|
x = m_input.ir.x;
|
||||||
|
y = m_input.ir.y;
|
||||||
|
|
||||||
|
/* draw wiimote pointer */
|
||||||
|
gxDrawTextureRotate(w_pointer, x-w_pointer->width/2, y-w_pointer->height/2, w_pointer->width, w_pointer->height,m_input.ir.angle,255);
|
||||||
|
|
||||||
|
/* ensure we are in the selectable area */
|
||||||
|
if ((x < 380) && (y >= 108) && (y <= 368))
|
||||||
|
{
|
||||||
|
/* find selected item */
|
||||||
|
selection = (y - 108) / 26;
|
||||||
|
if (selection > 9) selection = 9;
|
||||||
|
selection += offset;
|
||||||
|
if (selection >= maxfiles) selection = old;
|
||||||
|
|
||||||
|
/* reset selection */
|
||||||
|
m->selected = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* disable selection */
|
||||||
|
m->selected = m->max_buttons + 2;
|
||||||
|
|
||||||
|
/* find selected button */
|
||||||
|
for (i=0; i<2; i++)
|
||||||
|
{
|
||||||
|
button = m->arrows[i];
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
if (button->state & BUTTON_VISIBLE)
|
||||||
|
{
|
||||||
|
if ((x>=button->x)&&(x<=(button->x+button->w))&&(y>=button->y)&&(y<=(button->y+button->h)))
|
||||||
|
{
|
||||||
|
m->selected = m->max_buttons + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* reset selection */
|
||||||
|
m->selected = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* copy EFB to XFB */
|
||||||
|
gxSetScreen();
|
||||||
|
|
||||||
|
p = m_input.keys;
|
||||||
|
|
||||||
|
/* highlight next item */
|
||||||
|
if (p & PAD_BUTTON_DOWN)
|
||||||
|
{
|
||||||
|
selection++;
|
||||||
|
if (selection == maxfiles)
|
||||||
|
selection = offset = 0;
|
||||||
|
if ((selection - offset) >= 10)
|
||||||
|
offset += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* highlight previous item */
|
||||||
|
else if (p & PAD_BUTTON_UP)
|
||||||
|
{
|
||||||
|
selection--;
|
||||||
|
if (selection < 0)
|
||||||
|
{
|
||||||
|
selection = maxfiles - 1;
|
||||||
|
offset = selection - 10 + 1;
|
||||||
|
}
|
||||||
|
if (selection < offset)
|
||||||
|
offset -= 10;
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* go back one page */
|
||||||
|
else if (p & PAD_TRIGGER_L)
|
||||||
|
{
|
||||||
|
selection -= 10;
|
||||||
|
if (selection < 0)
|
||||||
|
{
|
||||||
|
selection = maxfiles - 1;
|
||||||
|
offset = selection - 10 + 1;
|
||||||
|
}
|
||||||
|
if (selection < offset)
|
||||||
|
offset -= 10;
|
||||||
|
if (offset < 0)
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* go forward one page */
|
||||||
|
else if (p & PAD_TRIGGER_R)
|
||||||
|
{
|
||||||
|
selection += 10;
|
||||||
|
if (selection > maxfiles - 1)
|
||||||
|
selection = offset = 0;
|
||||||
|
if ((selection - offset) >= 10)
|
||||||
|
offset += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* quit */
|
||||||
|
else if (p & PAD_TRIGGER_Z)
|
||||||
|
{
|
||||||
|
GUI_DeleteMenu(m);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* previous directory */
|
||||||
|
else if (p & PAD_BUTTON_B)
|
||||||
|
{
|
||||||
|
string_offset = 0;
|
||||||
|
|
||||||
|
/* update browser directory (and get current folder)*/
|
||||||
|
if (UpdateDirectory(1, prev_folder))
|
||||||
|
{
|
||||||
|
/* get directory entries */
|
||||||
|
maxfiles = ParseDirectory();
|
||||||
|
|
||||||
|
/* clear selection by default */
|
||||||
|
selection = offset = 0;
|
||||||
|
old = -1;
|
||||||
|
|
||||||
|
/* select previous directory */
|
||||||
|
for (i=0; i<maxfiles; i++)
|
||||||
|
{
|
||||||
|
if (filelist[i].flags && !strcmp(prev_folder,filelist[i].filename))
|
||||||
|
{
|
||||||
|
selection = i;
|
||||||
|
offset = (i / 10) * 10;
|
||||||
|
i = maxfiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* exit */
|
||||||
|
GUI_DeleteMenu(m);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open selected file or directory */
|
||||||
|
else if (p & PAD_BUTTON_A)
|
||||||
|
{
|
||||||
|
string_offset = 0;
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
/* arrow buttons selected */
|
||||||
|
if (m->selected == m->max_buttons)
|
||||||
|
{
|
||||||
|
/* up arrow */
|
||||||
|
selection--;
|
||||||
|
if (selection < 0)
|
||||||
|
{
|
||||||
|
selection = maxfiles - 1;
|
||||||
|
offset = selection - 10 + 1;
|
||||||
|
}
|
||||||
|
if (selection < offset) offset -= 10;
|
||||||
|
if (offset < 0) offset = 0;
|
||||||
|
}
|
||||||
|
else if (m->selected == (m->max_buttons+1))
|
||||||
|
{
|
||||||
|
/* down arrow */
|
||||||
|
selection++;
|
||||||
|
if (selection == maxfiles)
|
||||||
|
selection = offset = 0;
|
||||||
|
if ((selection - offset) >= 10)
|
||||||
|
offset += 10;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ensure we are in focus area */
|
||||||
|
if (m->selected < m->max_buttons)
|
||||||
|
{
|
||||||
|
if (filelist[selection].flags)
|
||||||
|
{
|
||||||
|
/* get new directory */
|
||||||
|
UpdateDirectory(0, filelist[selection].filename);
|
||||||
|
|
||||||
|
/* get directory entries */
|
||||||
|
maxfiles = ParseDirectory();
|
||||||
|
|
||||||
|
/* clear selection by default */
|
||||||
|
selection = offset = 0;
|
||||||
|
old = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* clear existing patches before loading new ROM file */
|
||||||
|
ggenie_shutdown();
|
||||||
|
areplay_shutdown();
|
||||||
|
|
||||||
|
/* load ROM file from device */
|
||||||
|
size = LoadFile(cart.rom, selection, fname);
|
||||||
|
|
||||||
|
/* exit menu */
|
||||||
|
GUI_DeleteMenu(m);
|
||||||
|
|
||||||
|
/* load new game */
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
/* save previous game state */
|
||||||
|
if (config.s_auto & 2)
|
||||||
|
{
|
||||||
|
slot_autosave(config.s_default,config.s_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reinitialize emulation */
|
||||||
|
reloadrom(size,fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearSelector(u32 max)
|
||||||
|
{
|
||||||
|
maxfiles = max;
|
||||||
|
offset = 0;
|
||||||
|
selection = 0;
|
||||||
|
}
|
42
source/gx/gui/filesel.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* filesel.c
|
||||||
|
*
|
||||||
|
* ROM File Browser
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FILESEL_H
|
||||||
|
#define _FILESEL_H
|
||||||
|
|
||||||
|
#define MAXJOLIET 256
|
||||||
|
#define MAXFILES 1000
|
||||||
|
|
||||||
|
/* Filelist structure */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char flags;
|
||||||
|
char filename[MAXJOLIET];
|
||||||
|
}FILEENTRIES;
|
||||||
|
|
||||||
|
/* Globals */
|
||||||
|
extern int FileSelector(void);
|
||||||
|
extern void ClearSelector(u32 max);
|
||||||
|
extern FILEENTRIES filelist[MAXFILES];
|
||||||
|
|
||||||
|
#endif
|
372
source/gx/gui/font.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* font.c
|
||||||
|
*
|
||||||
|
* IPL font engine (using GX rendering)
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
#define _SHIFTR(v, s, w) \
|
||||||
|
((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
|
||||||
|
|
||||||
|
typedef struct _yay0header {
|
||||||
|
unsigned int id ATTRIBUTE_PACKED;
|
||||||
|
unsigned int dec_size ATTRIBUTE_PACKED;
|
||||||
|
unsigned int links_offset ATTRIBUTE_PACKED;
|
||||||
|
unsigned int chunks_offset ATTRIBUTE_PACKED;
|
||||||
|
} yay0header;
|
||||||
|
|
||||||
|
u8 font_size[256];
|
||||||
|
int fheight;
|
||||||
|
|
||||||
|
static u8 *fontImage;
|
||||||
|
static u8 *fontTexture;
|
||||||
|
static void *ipl_fontarea;
|
||||||
|
static sys_fontheader *fontHeader;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef HW_RVL
|
||||||
|
|
||||||
|
/* disable Qoob Modchip before IPL access (emukiddid) */
|
||||||
|
static void ipl_set_config(unsigned char c)
|
||||||
|
{
|
||||||
|
volatile unsigned long* exi = (volatile unsigned long*)0xCC006800;
|
||||||
|
unsigned long val,addr;
|
||||||
|
addr=0xc0000000;
|
||||||
|
val = c << 24;
|
||||||
|
exi[0] = ((((exi[0]) & 0x405) | 256) | 48); //select IPL
|
||||||
|
//write addr of IPL
|
||||||
|
exi[0 * 5 + 4] = addr;
|
||||||
|
exi[0 * 5 + 3] = ((4 - 1) << 4) | (1 << 2) | 1;
|
||||||
|
while (exi[0 * 5 + 3] & 1);
|
||||||
|
//write the ipl we want to send
|
||||||
|
exi[0 * 5 + 4] = val;
|
||||||
|
exi[0 * 5 + 3] = ((4 - 1) << 4) | (1 << 2) | 1;
|
||||||
|
while (exi[0 * 5 + 3] & 1);
|
||||||
|
exi[0] &= 0x405; //deselect IPL
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void decode_szp(void *src,void *dest)
|
||||||
|
{
|
||||||
|
u32 i,k,link;
|
||||||
|
u8 *dest8,*tmp;
|
||||||
|
u32 loff,coff,roff;
|
||||||
|
u32 size,cnt,cmask,bcnt;
|
||||||
|
yay0header *header;
|
||||||
|
|
||||||
|
dest8 = (u8*)dest;
|
||||||
|
header = (yay0header*)src;
|
||||||
|
size = header->dec_size;
|
||||||
|
loff = header->links_offset;
|
||||||
|
coff = header->chunks_offset;
|
||||||
|
|
||||||
|
roff = sizeof(yay0header);
|
||||||
|
cmask = 0;
|
||||||
|
cnt = 0;
|
||||||
|
bcnt = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!bcnt) {
|
||||||
|
cmask = *(u32*)(src+roff);
|
||||||
|
roff += 4;
|
||||||
|
bcnt = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmask&0x80000000) {
|
||||||
|
dest8[cnt++] = *(u8*)(src+coff);
|
||||||
|
coff++;
|
||||||
|
} else {
|
||||||
|
link = *(u16*)(src+loff);
|
||||||
|
loff += 2;
|
||||||
|
|
||||||
|
tmp = dest8+(cnt-(link&0x0fff)-1);
|
||||||
|
k = link>>12;
|
||||||
|
if(k==0) {
|
||||||
|
k = (*(u8*)(src+coff))+18;
|
||||||
|
coff++;
|
||||||
|
} else k += 2;
|
||||||
|
|
||||||
|
for(i=0;i<k;i++) {
|
||||||
|
dest8[cnt++] = tmp[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmask <<= 1;
|
||||||
|
bcnt--;
|
||||||
|
} while(cnt<size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expand_font(u8 *src,u8 *dest)
|
||||||
|
{
|
||||||
|
s32 cnt;
|
||||||
|
u32 idx;
|
||||||
|
u8 val1,val2;
|
||||||
|
sys_fontheader *sys_fontdata = fontHeader;
|
||||||
|
u8 *data = (u8*)sys_fontdata+44;
|
||||||
|
|
||||||
|
if(sys_fontdata->sheet_format==0x0000) {
|
||||||
|
cnt = (sys_fontdata->sheet_fullsize/2)-1;
|
||||||
|
|
||||||
|
while(cnt>=0) {
|
||||||
|
idx = _SHIFTR(src[cnt],6,2);
|
||||||
|
val1 = data[idx];
|
||||||
|
|
||||||
|
idx = _SHIFTR(src[cnt],4,2);
|
||||||
|
val2 = data[idx];
|
||||||
|
|
||||||
|
dest[(cnt<<1)+0] =((val1&0xf0)|(val2&0x0f));
|
||||||
|
|
||||||
|
idx = _SHIFTR(src[cnt],2,2);
|
||||||
|
val1 = data[idx];
|
||||||
|
|
||||||
|
idx = _SHIFTR(src[cnt],0,2);
|
||||||
|
val2 = data[idx];
|
||||||
|
|
||||||
|
dest[(cnt<<1)+1] =((val1&0xf0)|(val2&0x0f));
|
||||||
|
|
||||||
|
cnt--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DCStoreRange(dest,sys_fontdata->sheet_fullsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetFontTexel(s32 c,void *image,s32 pos,s32 stride)
|
||||||
|
{
|
||||||
|
u32 sheets,rem;
|
||||||
|
u32 xoff,yoff;
|
||||||
|
u32 xpos,ypos;
|
||||||
|
u8 *img_start;
|
||||||
|
u8 *ptr1,*ptr2;
|
||||||
|
sys_fontheader *sys_fontdata = fontHeader;
|
||||||
|
|
||||||
|
if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
|
||||||
|
else c -= sys_fontdata->first_char;
|
||||||
|
|
||||||
|
sheets = sys_fontdata->sheet_column*sys_fontdata->sheet_row;
|
||||||
|
rem = c%sheets;
|
||||||
|
sheets = c/sheets;
|
||||||
|
xoff = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
|
||||||
|
yoff = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
|
||||||
|
img_start = fontImage+(sys_fontdata->sheet_size*sheets);
|
||||||
|
|
||||||
|
ypos = 0;
|
||||||
|
while(ypos<sys_fontdata->cell_height) {
|
||||||
|
xpos = 0;
|
||||||
|
while(xpos<sys_fontdata->cell_width) {
|
||||||
|
ptr1 = img_start+(((sys_fontdata->sheet_width/8)<<5)*((ypos+yoff)/8));
|
||||||
|
ptr1 = ptr1+(((xpos+xoff)/8)<<5);
|
||||||
|
ptr1 = ptr1+(((ypos+yoff)%8)<<2);
|
||||||
|
ptr1 = ptr1+(((xpos+xoff)%8)/2);
|
||||||
|
|
||||||
|
ptr2 = image+((ypos/8)*(((stride<<1)/8)<<5));
|
||||||
|
ptr2 = ptr2+(((xpos+pos)/8)<<5);
|
||||||
|
ptr2 = ptr2+(((xpos+pos)%8)/2);
|
||||||
|
ptr2 = ptr2+((ypos%8)<<2);
|
||||||
|
|
||||||
|
*ptr2 = *ptr1;
|
||||||
|
|
||||||
|
xpos += 2;
|
||||||
|
}
|
||||||
|
ypos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawChar(unsigned char c, int xpos, int ypos, int size, GXColor color)
|
||||||
|
{
|
||||||
|
/* reintialize texture object */
|
||||||
|
GXTexObj texobj;
|
||||||
|
GX_InitTexObj(&texobj, fontTexture, fontHeader->cell_width, fontHeader->cell_height, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||||
|
GX_LoadTexObj(&texobj, GX_TEXMAP0);
|
||||||
|
|
||||||
|
/* reinitialize font texture data */
|
||||||
|
memset(fontTexture,0,fontHeader->cell_width * fontHeader->cell_height / 2);
|
||||||
|
GetFontTexel(c,fontTexture,0,fontHeader->cell_width/2);
|
||||||
|
DCFlushRange(fontTexture, fontHeader->cell_width * fontHeader->cell_height / 2);
|
||||||
|
GX_InvalidateTexAll();
|
||||||
|
|
||||||
|
/* adjust texture width */
|
||||||
|
s32 width = (fontHeader->cell_width * size) / fontHeader->cell_height;
|
||||||
|
|
||||||
|
/* GX rendering */
|
||||||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||||||
|
GX_Position2s16(xpos, ypos - size);
|
||||||
|
GX_Color4u8(color.r, color.g, color.b, 0xff);
|
||||||
|
GX_TexCoord2f32(0.0, 0.0);
|
||||||
|
GX_Position2s16(xpos + width, ypos - size);
|
||||||
|
GX_Color4u8(color.r, color.g, color.b, 0xff);
|
||||||
|
GX_TexCoord2f32(1.0, 0.0);
|
||||||
|
GX_Position2s16(xpos + width, ypos);
|
||||||
|
GX_Color4u8(color.r, color.g, color.b, 0xff);
|
||||||
|
GX_TexCoord2f32(1.0, 1.0);
|
||||||
|
GX_Position2s16(xpos, ypos);
|
||||||
|
GX_Color4u8(color.r, color.g, color.b, 0xff);
|
||||||
|
GX_TexCoord2f32(0.0, 1.0);
|
||||||
|
GX_End ();
|
||||||
|
GX_DrawDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* IPL font support
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
extern void __SYS_ReadROM(void *buf,u32 len,u32 offset);
|
||||||
|
|
||||||
|
int FONT_Init(void)
|
||||||
|
{
|
||||||
|
#ifndef HW_RVL
|
||||||
|
/* --- Game Cube --- disable Qoob before accessing IPL */
|
||||||
|
ipl_set_config(6);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* read IPL font (ASCII) from Mask ROM */
|
||||||
|
ipl_fontarea = memalign(32,131360);
|
||||||
|
if (!ipl_fontarea)
|
||||||
|
return 0;
|
||||||
|
memset(ipl_fontarea,0,131360);
|
||||||
|
__SYS_ReadROM(ipl_fontarea+119072,12288,0x1FCF00);
|
||||||
|
|
||||||
|
/* YAY0 decompression */
|
||||||
|
decode_szp(ipl_fontarea+119072,ipl_fontarea);
|
||||||
|
|
||||||
|
/* retrieve IPL font data */
|
||||||
|
fontHeader = (sys_fontheader*)ipl_fontarea;
|
||||||
|
fontImage = (u8*)((((u32)ipl_fontarea+fontHeader->sheet_image)+31)&~31);
|
||||||
|
|
||||||
|
/* expand to I4 format */
|
||||||
|
expand_font((u8*)ipl_fontarea+fontHeader->sheet_image,fontImage);
|
||||||
|
|
||||||
|
/* character width table */
|
||||||
|
int i,c;
|
||||||
|
for (i=0; i<256; ++i)
|
||||||
|
{
|
||||||
|
if ((i < fontHeader->first_char) || (i > fontHeader->last_char))
|
||||||
|
c = fontHeader->inval_char;
|
||||||
|
else
|
||||||
|
c = i - fontHeader->first_char;
|
||||||
|
|
||||||
|
font_size[i] = ((u8*)fontHeader)[fontHeader->width_table + c];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* font height */
|
||||||
|
fheight = fontHeader->cell_height;
|
||||||
|
|
||||||
|
/* initialize texture data */
|
||||||
|
fontTexture = memalign(32, fontHeader->cell_width * fontHeader->cell_height / 2);
|
||||||
|
if (!fontTexture)
|
||||||
|
{
|
||||||
|
free(ipl_fontarea);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FONT_Shutdown(void)
|
||||||
|
{
|
||||||
|
if (fontHeader)
|
||||||
|
free(ipl_fontarea);
|
||||||
|
if (fontTexture)
|
||||||
|
free(fontTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FONT_write(char *string, int size, int x, int y, int max_width, GXColor color)
|
||||||
|
{
|
||||||
|
x -= (vmode->fbWidth / 2);
|
||||||
|
y -= (vmode->efbHeight / 2);
|
||||||
|
int w, ox = x;
|
||||||
|
|
||||||
|
while (*string && (*string != '\n'))
|
||||||
|
{
|
||||||
|
w = (font_size[(u8)*string] * size) / fheight;
|
||||||
|
if ((x + w) > (ox + max_width)) return strlen(string);
|
||||||
|
DrawChar(*string, x, y, size,color);
|
||||||
|
x += w;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*string == '\n')
|
||||||
|
{
|
||||||
|
string++;
|
||||||
|
return FONT_write(string, size, ox + (vmode->fbWidth / 2), y + size + (vmode->efbHeight / 2), max_width, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FONT_writeCenter(char *string, int size, int x1, int x2, int y, GXColor color)
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
int w = 0;
|
||||||
|
while (string[i] && (string[i] != '\n'))
|
||||||
|
{
|
||||||
|
w += (font_size[(u8)string[i++]] * size) / fheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x1 + w) > x2) w = x2 - x1;
|
||||||
|
int x = x1 + (x2 - x1 - w - vmode->fbWidth) / 2;
|
||||||
|
y -= (vmode->efbHeight / 2);
|
||||||
|
x2 -= (vmode->fbWidth / 2);
|
||||||
|
|
||||||
|
while (*string && (*string != '\n'))
|
||||||
|
{
|
||||||
|
w = (font_size[(u8)*string] * size) / fheight;
|
||||||
|
if ((x + w) > x2) return strlen(string);
|
||||||
|
DrawChar(*string, x, y, size,color);
|
||||||
|
x += w;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*string == '\n')
|
||||||
|
{
|
||||||
|
string++;
|
||||||
|
return FONT_writeCenter(string, size, x1, x2 + (vmode->fbWidth / 2), y + size + (vmode->efbHeight / 2), color);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FONT_alignRight(char *string, int size, int x, int y, GXColor color)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int w = 0;
|
||||||
|
|
||||||
|
x -= (vmode->fbWidth / 2);
|
||||||
|
y -= (vmode->efbHeight / 2);
|
||||||
|
|
||||||
|
int ox = x;
|
||||||
|
|
||||||
|
for (i=0; i<strlen(string); i++)
|
||||||
|
{
|
||||||
|
w += (font_size[(u8)string[i]] * size) / fheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = ox - w;
|
||||||
|
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
w = (font_size[(u8)*string] * size) / fheight;
|
||||||
|
if ((x + w) > ox) return strlen(string);
|
||||||
|
DrawChar(*string, x, y, size,color);
|
||||||
|
x += w;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
33
source/gx/gui/font.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* font.c
|
||||||
|
*
|
||||||
|
* IPL font engine (using GX rendering)
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _FONT_H
|
||||||
|
#define _FONT_H
|
||||||
|
|
||||||
|
extern int FONT_Init(void);
|
||||||
|
extern void FONT_Shutdown(void);
|
||||||
|
extern int FONT_write(char *string, int size, int x, int y, int max_width, GXColor color);
|
||||||
|
extern int FONT_writeCenter(char *string, int size, int x1, int x2, int y, GXColor color);
|
||||||
|
extern int FONT_alignRight(char *string, int size, int x, int y, GXColor color);
|
||||||
|
|
||||||
|
#endif
|
1992
source/gx/gui/gui.c
Normal file
239
source/gx/gui/gui.h
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* gui.c
|
||||||
|
*
|
||||||
|
* generic GUI Engine (using GX rendering)
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GUI_H
|
||||||
|
#define _GUI_H
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BG_COLOR_MAX 15
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Buttons state */
|
||||||
|
/*****************************************************************************/
|
||||||
|
#define BUTTON_VISIBLE 0x01
|
||||||
|
#define BUTTON_ACTIVE 0x02
|
||||||
|
#define BUTTON_SELECTED 0x04
|
||||||
|
#define BUTTON_OVER_SFX 0x08
|
||||||
|
#define BUTTON_SELECT_SFX 0x10
|
||||||
|
#define BUTTON_FADE 0x20
|
||||||
|
#define BUTTON_SLIDE_LEFT 0x40
|
||||||
|
#define BUTTON_SLIDE_RIGHT 0x80
|
||||||
|
#define BUTTON_SLIDE_TOP 0x100
|
||||||
|
#define BUTTON_SLIDE_BOTTOM 0x200
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* GUI Image state */
|
||||||
|
/*****************************************************************************/
|
||||||
|
#define IMAGE_VISIBLE 0x01
|
||||||
|
#define IMAGE_REPEAT 0x02
|
||||||
|
#define IMAGE_FADE 0x04
|
||||||
|
#define IMAGE_SLIDE_LEFT 0x08
|
||||||
|
#define IMAGE_SLIDE_RIGHT 0x10
|
||||||
|
#define IMAGE_SLIDE_TOP 0x20
|
||||||
|
#define IMAGE_SLIDE_BOTTOM 0x40
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Generic GUI structures */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/* Item descriptor*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gx_texture *texture; /* temporary texture data */
|
||||||
|
const u8 *data; /* pointer to png image data (items icon only) */
|
||||||
|
char text[64]; /* item string (items list only) */
|
||||||
|
char comment[64]; /* item comment */
|
||||||
|
u16 x; /* item image or text X position (upper left corner) */
|
||||||
|
u16 y; /* item image or text Y position (upper left corner) */
|
||||||
|
u16 w; /* item image or text width */
|
||||||
|
u16 h; /* item image or text height */
|
||||||
|
} gui_item;
|
||||||
|
|
||||||
|
/* Button Data descriptor */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gx_texture *texture[2]; /* temporary texture datas */
|
||||||
|
const u8 *image[2]; /* pointer to png image datas (default) */
|
||||||
|
} butn_data;
|
||||||
|
|
||||||
|
/* Button descriptor */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
butn_data *data; /* pointer to button image/texture data */
|
||||||
|
u16 state; /* button state (ACTIVE,VISIBLE,SELECTED...) */
|
||||||
|
u8 shift[4]; /* direction offsets */
|
||||||
|
u16 x; /* button image X position (upper left corner) */
|
||||||
|
u16 y; /* button image Y position (upper left corner) */
|
||||||
|
u16 w; /* button image pixels width */
|
||||||
|
u16 h; /* button image pixels height */
|
||||||
|
} gui_butn;
|
||||||
|
|
||||||
|
/* Image descriptor */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gx_texture *texture; /* temporary texture data */
|
||||||
|
const u8 *data; /* pointer to png image data */
|
||||||
|
u8 state; /* image state (VISIBLE) */
|
||||||
|
u16 x; /* image X position (upper left corner) */
|
||||||
|
u16 y; /* image Y position (upper left corner) */
|
||||||
|
u16 w; /* image width */
|
||||||
|
u16 h; /* image height */
|
||||||
|
u8 alpha; /* alpha transparency */
|
||||||
|
} gui_image;
|
||||||
|
|
||||||
|
/* Menu descriptor */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char title[64]; /* menu title */
|
||||||
|
s8 selected; /* index of selected item */
|
||||||
|
s8 offset; /* items list offset */
|
||||||
|
u8 max_items; /* total number of items */
|
||||||
|
u8 max_buttons; /* total number of buttons */
|
||||||
|
u8 max_images; /* total number of background images */
|
||||||
|
u8 screenshot; /* game screen background */
|
||||||
|
gui_item *items; /* menu items */
|
||||||
|
gui_butn *buttons; /* menu buttons */
|
||||||
|
gui_image *bg_images; /* background images */
|
||||||
|
gui_item *helpers[2]; /* left & right key comments */
|
||||||
|
gui_butn *arrows[2]; /* arrows buttons */
|
||||||
|
void (*cb)(void); /* specific draw callback */
|
||||||
|
} gui_menu;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u32 progress; /* progress counter */
|
||||||
|
bool refresh; /* messagebox current state */
|
||||||
|
gui_menu *parent; /* parent menu */
|
||||||
|
char title[64]; /* box title */
|
||||||
|
char msg[64]; /* box message */
|
||||||
|
gx_texture *window; /* pointer to box texture */
|
||||||
|
gx_texture *top; /* pointer to box title texture */
|
||||||
|
gx_texture *buttonA; /* pointer to button A texture */
|
||||||
|
gx_texture *throbber; /* pointer to throbber texture */
|
||||||
|
} gui_message;
|
||||||
|
|
||||||
|
/* Menu inputs */
|
||||||
|
struct t_input_menu
|
||||||
|
{
|
||||||
|
u16 keys;
|
||||||
|
#ifdef HW_RVL
|
||||||
|
struct ir_t ir;
|
||||||
|
#endif
|
||||||
|
} m_input;
|
||||||
|
|
||||||
|
/* Optionbox callback */
|
||||||
|
typedef void (*optioncallback)(void);
|
||||||
|
|
||||||
|
/* Generic textures*/
|
||||||
|
#ifdef HW_RVL
|
||||||
|
extern gx_texture *w_pointer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Generic backgrounds */
|
||||||
|
extern const u8 Bg_layer_png[];
|
||||||
|
extern const u8 Bg_main_png[];
|
||||||
|
extern const u8 Bg_main_2_png[];
|
||||||
|
extern const u8 Bg_overlay_png[];
|
||||||
|
extern const u8 Banner_main_png[];
|
||||||
|
extern const u8 Banner_bottom_png[];
|
||||||
|
extern const u8 Banner_top_png[];
|
||||||
|
extern const u8 Banner_main_2_png[];
|
||||||
|
extern const u8 Banner_bottom_2_png[];
|
||||||
|
extern const u8 Banner_top_2_png[];
|
||||||
|
extern const u8 Main_logo_png[];
|
||||||
|
|
||||||
|
/* Generic frames */
|
||||||
|
extern const u8 Frame_s1_png[];
|
||||||
|
extern const u8 Frame_s2_png[];
|
||||||
|
extern const u8 Frame_s3_png[];
|
||||||
|
extern const u8 Frame_s1_title_png[];
|
||||||
|
extern const u8 Frame_s2_title_png[];
|
||||||
|
extern const u8 Frame_throbber_png[];
|
||||||
|
|
||||||
|
/* Generic Buttons */
|
||||||
|
extern const u8 Button_text_png[];
|
||||||
|
extern const u8 Button_text_over_png[];
|
||||||
|
extern const u8 Button_icon_png[];
|
||||||
|
extern const u8 Button_icon_over_png[];
|
||||||
|
extern const u8 Button_icon_sm_png[];
|
||||||
|
extern const u8 Button_icon_sm_over_png[];
|
||||||
|
extern const u8 Button_up_png[];
|
||||||
|
extern const u8 Button_up_over_png[];
|
||||||
|
extern const u8 Button_down_png[];
|
||||||
|
extern const u8 Button_down_over_png[];
|
||||||
|
extern const u8 Button_arrow_png[];
|
||||||
|
extern const u8 Button_arrow_over_png[];
|
||||||
|
extern const u8 Button_digit_png[];
|
||||||
|
extern const u8 Button_digit_over_png[];
|
||||||
|
|
||||||
|
/* Generic images*/
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#define Key_A_png Key_A_wii_png
|
||||||
|
#define Key_B_png Key_B_wii_png
|
||||||
|
extern const u8 generic_point_png[];
|
||||||
|
extern const u8 Key_A_wii_png[];
|
||||||
|
extern const u8 Key_B_wii_png[];
|
||||||
|
#else
|
||||||
|
#define Key_A_png Key_A_gcn_png
|
||||||
|
#define Key_B_png Key_B_gcn_png
|
||||||
|
extern const u8 Key_A_gcn_png[];
|
||||||
|
extern const u8 Key_B_gcn_png[];
|
||||||
|
#endif
|
||||||
|
extern const u8 Star_full_png[];
|
||||||
|
extern const u8 Star_empty_png[];
|
||||||
|
extern const u8 Overlay_bar_png[];
|
||||||
|
|
||||||
|
/* Generic Sounds */
|
||||||
|
extern const u8 button_over_pcm[];
|
||||||
|
extern const u8 button_select_pcm[];
|
||||||
|
extern const u8 intro_pcm[];
|
||||||
|
extern const u32 button_select_pcm_size;
|
||||||
|
extern const u32 button_over_pcm_size;
|
||||||
|
extern const u32 intro_pcm_size;
|
||||||
|
|
||||||
|
extern u8 SILENT;
|
||||||
|
|
||||||
|
extern void GUI_InitMenu(gui_menu *menu);
|
||||||
|
extern void GUI_DeleteMenu(gui_menu *menu);
|
||||||
|
extern void GUI_DrawMenu(gui_menu *menu);
|
||||||
|
extern void GUI_DrawMenuFX(gui_menu *menu, u8 speed, u8 out);
|
||||||
|
extern void GUI_SlideMenuTitle(gui_menu *m, int title_offset);
|
||||||
|
extern int GUI_UpdateMenu(gui_menu *menu);
|
||||||
|
extern int GUI_RunMenu(gui_menu *menu);
|
||||||
|
extern void GUI_TextWindow(gui_menu *parent, char *title, char items[][64], u8 nb_items, u8 fontsize);
|
||||||
|
extern int GUI_OptionWindow(gui_menu *parent, char *title, char *items[], u8 nb_items);
|
||||||
|
extern void GUI_OptionBox(gui_menu *parent, optioncallback cb, char *title, void *option, float step, float min, float max, u8 type);
|
||||||
|
extern void GUI_OptionBox2(gui_menu *parent, char *text_1, char *text_2, s16 *option_1, s16 *option_2, s16 step, s16 min, s16 max);
|
||||||
|
extern void GUI_MsgBoxOpen(char *title, char *msg, bool throbber);
|
||||||
|
extern void GUI_MsgBoxUpdate(char *title, char *msg);
|
||||||
|
extern void GUI_MsgBoxClose(void);
|
||||||
|
extern void GUI_WaitPrompt(char *title, char *msg);
|
||||||
|
extern void GUI_FadeOut();
|
||||||
|
extern GXColor *GUI_GetBgColor(void);
|
||||||
|
extern void GUI_SetBgColor(u8 color);
|
||||||
|
extern void GUI_Initialize(void);
|
||||||
|
|
||||||
|
#endif
|
167
source/gx/gui/legal.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* legal.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX Disclaimer
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009,2010)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
#include "font.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
|
extern const u8 Bg_intro_c1_png[];
|
||||||
|
extern const u8 Bg_intro_c2_png[];
|
||||||
|
extern const u8 Bg_intro_c3_png[];
|
||||||
|
extern const u8 Bg_intro_c4_png[];
|
||||||
|
extern const u8 Bg_intro_c5_png[];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the legal stuff - which must be shown at program startup
|
||||||
|
* Any derivative work MUST include the same textual output.
|
||||||
|
*
|
||||||
|
* In other words, play nice and give credit where it's due.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void show_disclaimer(int ypos)
|
||||||
|
{
|
||||||
|
FONT_writeCenter ("DISCLAIMER",22,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 32;
|
||||||
|
FONT_writeCenter ("This is free software, and you are welcome to",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("redistribute it under the conditions of the",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("GNU GENERAL PUBLIC LICENSE Version 2.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("Authors can not be held responsible for any damage or",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("or dysfunction that could occur while using this port.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("You may not sell, lease, rent or generally use",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("this software in any commercial product or activity.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("You may not distribute this software with any ROM image",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("unless you have the legal right to distribute them.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("This software is not endorsed by or affiliated",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("with Sega Enterprises Ltd or Nintendo Co Ltd.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("All trademarks and registered trademarks are",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 20;
|
||||||
|
FONT_writeCenter ("the property of their respective owners.",20,0,640,ypos,(GXColor)WHITE);
|
||||||
|
ypos += 38;
|
||||||
|
}
|
||||||
|
|
||||||
|
void legal ()
|
||||||
|
{
|
||||||
|
int count = 2000;
|
||||||
|
int vis = 0;
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
gx_texture *button = gxTextureOpenPNG(Key_A_wii_png,0);
|
||||||
|
#else
|
||||||
|
gx_texture *button = gxTextureOpenPNG(Key_A_gcn_png,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gx_texture *logo_left= gxTextureOpenPNG(Bg_intro_c5_png,0);
|
||||||
|
gx_texture *logo_right = gxTextureOpenPNG(Bg_intro_c4_png,0);
|
||||||
|
|
||||||
|
gxClearScreen((GXColor)BLACK);
|
||||||
|
show_disclaimer(56);
|
||||||
|
gxDrawTexture(logo_left, (640-logo_left->width-logo_right->width -32)/2, 480-logo_left->height-24, logo_left->width, logo_left->height,255);
|
||||||
|
gxDrawTexture(logo_right, (640-logo_left->width-logo_right->width -32)/2+logo_left->width+32, 480-logo_right->height-24, logo_right->width, logo_right->height,255);
|
||||||
|
gxSetScreen();
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
while (!(m_input.keys & PAD_BUTTON_A) && (count > 0))
|
||||||
|
{
|
||||||
|
gxClearScreen((GXColor)BLACK);
|
||||||
|
show_disclaimer(56);
|
||||||
|
if (count%25 == 0) vis^=1;
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
FONT_writeCenter("Press button to continue.",24,0,640,366,(GXColor)SKY_BLUE);
|
||||||
|
gxDrawTexture(button, 220, 366-24+(24-button->height)/2, button->width, button->height,255);
|
||||||
|
}
|
||||||
|
gxDrawTexture(logo_left, (640-logo_left->width-logo_right->width -32)/2, 480-logo_left->height-24, logo_left->width, logo_left->height,255);
|
||||||
|
gxDrawTexture(logo_right, (640-logo_left->width-logo_right->width -32)/2+logo_left->width+32, 480-logo_right->height-24, logo_right->width, logo_right->height,255);
|
||||||
|
gxSetScreen();
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
gxTextureClose(&button);
|
||||||
|
gxTextureClose(&logo_left);
|
||||||
|
gxTextureClose(&logo_right);
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
ASND_Init();
|
||||||
|
ASND_Pause(0);
|
||||||
|
int voice = ASND_GetFirstUnusedVoice();
|
||||||
|
ASND_SetVoice(voice,VOICE_MONO_16BIT,44100,0,(u8 *)button_select_pcm,button_select_pcm_size,200,200,NULL);
|
||||||
|
GUI_FadeOut();
|
||||||
|
ASND_Pause(1);
|
||||||
|
ASND_End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gxClearScreen((GXColor)BLACK);
|
||||||
|
gx_texture *texture = gxTextureOpenPNG(Bg_intro_c1_png,0);
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
|
||||||
|
if (texture->data) free(texture->data);
|
||||||
|
free(texture);
|
||||||
|
}
|
||||||
|
gxSetScreen();
|
||||||
|
|
||||||
|
sleep (1);
|
||||||
|
|
||||||
|
gxClearScreen((GXColor)WHITE);
|
||||||
|
texture = gxTextureOpenPNG(Bg_intro_c2_png,0);
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
|
||||||
|
if (texture->data) free(texture->data);
|
||||||
|
free(texture);
|
||||||
|
}
|
||||||
|
gxSetScreen();
|
||||||
|
|
||||||
|
sleep (1);
|
||||||
|
|
||||||
|
gxClearScreen((GXColor)BLACK);
|
||||||
|
texture = gxTextureOpenPNG(Bg_intro_c3_png,0);
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
gxDrawTexture(texture, (640-texture->width)/2, (480-texture->height)/2, texture->width, texture->height,255);
|
||||||
|
if (texture->data) free(texture->data);
|
||||||
|
free(texture);
|
||||||
|
}
|
||||||
|
gxSetScreen();
|
||||||
|
|
||||||
|
ASND_Pause(0);
|
||||||
|
int voice = ASND_GetFirstUnusedVoice();
|
||||||
|
ASND_SetVoice(voice,VOICE_MONO_16BIT,44100,0,(u8 *)intro_pcm,intro_pcm_size,200,200,NULL);
|
||||||
|
sleep (2);
|
||||||
|
ASND_Pause(1);
|
||||||
|
}
|
3369
source/gx/gui/menu.c
Normal file
32
source/gx/gui/menu.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* menu.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX menus
|
||||||
|
*
|
||||||
|
* Eke-Eke (2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _MENU_H
|
||||||
|
#define _MENU_H
|
||||||
|
|
||||||
|
extern void menu_execute(void);
|
||||||
|
extern void menu_configure(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
136
source/gx/gui/saveicon.h
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/***********************************************************
|
||||||
|
* Genesis Plus Save Icon
|
||||||
|
* Made by Brakken (http://www.tehskeen.com)
|
||||||
|
*
|
||||||
|
************************************************************/
|
||||||
|
unsigned short icon[1024] = {
|
||||||
|
|
||||||
|
0xFFFF, 0xFFFF, 0xFBDE, 0xFBDE, 0xFBDE, 0xFBDE, 0xFBDE, 0xEB5A,
|
||||||
|
0xFBDE, 0xFBDE, 0xFBDE, 0xBDCD, 0xFBDE, 0xF7BD, 0xF7BD, 0xAD49,
|
||||||
|
0xEB59, 0xB9AD, 0xC1EF, 0xC1EF, 0x9062, 0x8000, 0x8C41, 0x8C41,
|
||||||
|
0x8000, 0x9CE6, 0xA0E6, 0xA507, 0x8400, 0x9CC5, 0xA0E6, 0xA0E6,
|
||||||
|
0xC1EF, 0xC1EF, 0xC1EF, 0xC1EF, 0x8000, 0x8000, 0x8000, 0x8000,
|
||||||
|
0x9083, 0x8C63, 0x8C63, 0x9484, 0x8C63, 0x9083, 0x9484, 0x94A4,
|
||||||
|
0xC1EF, 0xC20F, 0xC20F, 0xBDCE, 0x8000, 0x8000, 0x8000, 0x8000,
|
||||||
|
0x9083, 0x8821, 0x8842, 0x8842, 0x8842, 0xA107, 0xB58C, 0xAD6B,
|
||||||
|
0xA529, 0x94A4, 0x9083, 0x94A4, 0x8000, 0x8000, 0x8400, 0x8400,
|
||||||
|
0x8842, 0x8842, 0x8842, 0x8821, 0xB18B, 0xA949, 0xA108, 0xA107,
|
||||||
|
0xA528, 0xB9AD, 0xC630, 0xCE51, 0x8000, 0x8000, 0x8000, 0x8000,
|
||||||
|
0x8821, 0x8821, 0x8821, 0x8400, 0xA108, 0xA529, 0xA108, 0xA529,
|
||||||
|
0xCA30, 0xC630, 0xCA30, 0xFBDE, 0x8000, 0x8000, 0x8000, 0xAD27,
|
||||||
|
0x8400, 0x9083, 0x8863, 0x8400, 0x9CE6, 0x8842, 0x8C63, 0x8C20,
|
||||||
|
0xFBDE, 0xFBDE, 0xFFFF, 0xFFFF, 0xFBDE, 0xFBDE, 0xFBDE, 0xFBDE,
|
||||||
|
0xDA92, 0xFBDE, 0xFBDE, 0xFBDE, 0xC1AB, 0xF7BD, 0xFBDE, 0xFBDE,
|
||||||
|
0xF7BD, 0xF7BD, 0xF7BD, 0xA0E6, 0xF7BD, 0xF7BD, 0xF39C, 0x9484,
|
||||||
|
0xF39C, 0xF39C, 0xDEF7, 0x8C41, 0xF39C, 0xEF7B, 0xD272, 0x8400,
|
||||||
|
0x8C42, 0x9CE6, 0xA507, 0xA0E6, 0x8C63, 0x9CC5, 0xA107, 0x9CE6,
|
||||||
|
0x9484, 0x98A5, 0x9CE6, 0x98C5, 0x9CC5, 0x98C5, 0xA0E7, 0x98C5,
|
||||||
|
0x8C42, 0x9083, 0x94A5, 0x9083, 0x8C42, 0x9083, 0x9084, 0x8C62,
|
||||||
|
0x8C62, 0x9083, 0x9084, 0x8C62, 0x8C63, 0x9083, 0x94A4, 0x8C63,
|
||||||
|
0x8842, 0x9CC6, 0xA107, 0xA0E7, 0x8842, 0x8842, 0xA108, 0xA54A,
|
||||||
|
0x8842, 0x8C63, 0xB5AD, 0xB5AD, 0x8C63, 0x8C62, 0x8842, 0x8C63,
|
||||||
|
0x98C5, 0xA528, 0xB5AC, 0xB5AC, 0xA52A, 0xBDEF, 0xC631, 0xCA52,
|
||||||
|
0xB9CE, 0xB9CE, 0xA94A, 0xAD6B, 0x8C63, 0x8821, 0x8821, 0x8821,
|
||||||
|
0xA529, 0x98C5, 0x98C5, 0xA0E6, 0xC210, 0xA529, 0xA529, 0xA529,
|
||||||
|
0xB5AD, 0xB5CD, 0xB5AD, 0xBDEF, 0x8400, 0x8821, 0x8C62, 0x8821,
|
||||||
|
0xA0E7, 0x8842, 0x8842, 0x8C41, 0x9083, 0x8842, 0x8842, 0x8842,
|
||||||
|
0x94A5, 0x8842, 0x8C62, 0x8C62, 0x8C42, 0x9083, 0x8C62, 0x8C62,
|
||||||
|
0xB548, 0xF7BD, 0xF7BD, 0xF7BD, 0xA4C4, 0xF7BD, 0xF7BD, 0xF7BD,
|
||||||
|
0x9461, 0xDED5, 0xF39C, 0xF39C, 0x8C20, 0xD271, 0xF39C, 0xF39C,
|
||||||
|
0xEF7B, 0xEF7B, 0xC610, 0x8400, 0xEF7B, 0xEB5A, 0xB9AC, 0x8000,
|
||||||
|
0xEB5A, 0xEB5A, 0xA528, 0x9CC5, 0xE739, 0xE739, 0x9CC6, 0x98A5,
|
||||||
|
0x98C5, 0x98C5, 0xA0E6, 0x94A4, 0x94A4, 0x98C5, 0x94A5, 0x9484,
|
||||||
|
0xA528, 0x98C5, 0x9CE6, 0xA0E7, 0x9CE6, 0xA4E6, 0x98A4, 0xA507,
|
||||||
|
0x8C62, 0x9083, 0x9484, 0x9083, 0x94A4, 0x94A5, 0x98C5, 0x98C5,
|
||||||
|
0xA107, 0xA107, 0xA107, 0xB18B, 0xA907, 0x9062, 0x9484, 0x9CE6,
|
||||||
|
0x8842, 0x94A4, 0x9484, 0x9084, 0x8C62, 0x8C63, 0x9CC5, 0x9CC5,
|
||||||
|
0x98C6, 0x8C63, 0x9484, 0xA0E6, 0x9CE6, 0x9084, 0x94A4, 0x90A5,
|
||||||
|
0x8C63, 0x8C42, 0x8C62, 0x8C62, 0x8C63, 0xA108, 0xA94A, 0xA528,
|
||||||
|
0x94A5, 0x8884, 0x8884, 0x8884, 0xB0A5, 0xBC84, 0xA483, 0xA484,
|
||||||
|
0x8C63, 0x8C42, 0x8C63, 0x9083, 0xA94A, 0x9083, 0x8C62, 0x94A4,
|
||||||
|
0x8884, 0x8063, 0x90A5, 0x94A4, 0xA483, 0xBC63, 0xA884, 0x8884,
|
||||||
|
0x9083, 0x8C63, 0x8C42, 0x8C63, 0x9084, 0x8842, 0x9083, 0x9084,
|
||||||
|
0x8C42, 0x8C62, 0x98C6, 0xAD6A, 0x9083, 0x8C63, 0x98C5, 0xA107,
|
||||||
|
0x8400, 0xC1ED, 0xEF7B, 0xEF7B, 0x8400, 0xAD27, 0xEF7B, 0xEF7B,
|
||||||
|
0x9CE6, 0x9CA4, 0xEB5A, 0xEB5A, 0x9CE6, 0x9062, 0xDAB4, 0xE739,
|
||||||
|
0xE739, 0xE318, 0x9483, 0x8C63, 0xE318, 0xCE72, 0x9062, 0x9CC5,
|
||||||
|
0xDEF7, 0xC20F, 0x8C41, 0x9CE6, 0xDAD6, 0xB9AC, 0x8C20, 0x9CC5,
|
||||||
|
0xA0E6, 0xA528, 0x9CC5, 0xA528, 0xA508, 0x94A5, 0x98C6, 0xA108,
|
||||||
|
0x9CE6, 0x9CC5, 0xA0E7, 0xA94A, 0xA0E6, 0xA0E7, 0xA507, 0xAD6B,
|
||||||
|
0xA107, 0x98C6, 0x9CE6, 0x9083, 0x98C6, 0xA108, 0xA107, 0x98C5,
|
||||||
|
0xB9CD, 0xB18B, 0xA107, 0x9CC6, 0xC210, 0xB9CE, 0xA528, 0x9CC6,
|
||||||
|
0x98C5, 0x94A5, 0x9084, 0x8884, 0x9CC6, 0x9CE6, 0x9CC6, 0x94A5,
|
||||||
|
0x9CE6, 0x9CE6, 0x9CE7, 0xA108, 0x98C5, 0x98C5, 0x98C6, 0x98C6,
|
||||||
|
0xB0C6, 0xD0C6, 0xD0C6, 0xD0C6, 0x90A4, 0x90A4, 0x98A5, 0x9CA4,
|
||||||
|
0x9CE6, 0x90A4, 0x9084, 0x9084, 0x98C6, 0x98C6, 0x98C6, 0x98C6,
|
||||||
|
0xD0A5, 0xD0A5, 0xA484, 0x8483, 0x9484, 0x9083, 0x8C83, 0x9084,
|
||||||
|
0x90A5, 0x94A5, 0x9CE6, 0x9CE6, 0x98C6, 0x98C6, 0x9CE6, 0x98C6,
|
||||||
|
0x8C63, 0x9084, 0x9484, 0x9083, 0x98C5, 0x98C5, 0x94A4, 0x94A5,
|
||||||
|
0x98C6, 0x98C6, 0x98C5, 0x98C5, 0x98C6, 0x98C6, 0x98C6, 0x98C6,
|
||||||
|
0x9084, 0x8821, 0xCE51, 0xE739, 0x94A5, 0x8C20, 0xBDCE, 0xE318,
|
||||||
|
0x98C5, 0x8821, 0xB18B, 0xE318, 0x98C6, 0x8842, 0xAD49, 0xDEF7,
|
||||||
|
0xDAD6, 0xAD49, 0x8C41, 0xA508, 0xD6B5, 0xBDCC, 0x8C20, 0x8C41,
|
||||||
|
0xD6B5, 0xD294, 0xB98A, 0xAD06, 0xD294, 0xCE73, 0xCE73, 0xCA52,
|
||||||
|
0xA94A, 0xB5AD, 0xB18C, 0xAD6B, 0x9062, 0x9062, 0x9062, 0x9062,
|
||||||
|
0xAD27, 0xAD06, 0xAD06, 0xAD06, 0xCA52, 0xC631, 0xC631, 0xC210,
|
||||||
|
0xA94B, 0xB18C, 0xB58D, 0xAD6B, 0x9062, 0x9484, 0x98A4, 0x98A4,
|
||||||
|
0xA906, 0xA906, 0xA506, 0xA907, 0xC210, 0xC210, 0xB9F0, 0xBDEF,
|
||||||
|
0xA94B, 0xA94B, 0xA94B, 0xA94B, 0x98A5, 0x98A5, 0x98A4, 0x98A4,
|
||||||
|
0xA907, 0xA907, 0xA907, 0xA506, 0xBDEF, 0xBDEF, 0xBDEF, 0xB1F2,
|
||||||
|
0xA94B, 0xA94A, 0xA54A, 0xA529, 0x9484, 0x9484, 0x9483, 0x9483,
|
||||||
|
0xA4E6, 0xA4E6, 0xA4E6, 0xA4E6, 0xBDEF, 0xBDEF, 0xBDEF, 0xBDEF,
|
||||||
|
0xA529, 0xA529, 0xA529, 0xA108, 0x9062, 0x8C63, 0x9062, 0x9062,
|
||||||
|
0xA4E6, 0x9CE6, 0xA0E6, 0xA506, 0xBDEF, 0xC210, 0xC210, 0xC210,
|
||||||
|
0xA108, 0x9CE7, 0x9CE7, 0x98C6, 0x8C41, 0x8C42, 0x8C41, 0x8C41,
|
||||||
|
0xA507, 0xA508, 0xAD27, 0xB127, 0xC631, 0xC631, 0xCA52, 0xCA52,
|
||||||
|
0x98C6, 0x8C63, 0xA0E6, 0xDAD6, 0x8C41, 0x8400, 0xB548, 0xDAD6,
|
||||||
|
0xB127, 0xB548, 0xD6B5, 0xD6B5, 0xCE73, 0xCE73, 0xD294, 0xD6B5,
|
||||||
|
0xD294, 0xCA74, 0xBA56, 0xB635, 0x9A3B, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0x81FF, 0x8A1F, 0xA27F, 0xA27F, 0x81FF, 0xA27F, 0xFFFF, 0xFFFF,
|
||||||
|
0xB635, 0xB214, 0xB214, 0xBE11, 0x81FF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xA27F, 0xA27F, 0xA27F, 0x8A1F, 0xFFFF, 0xFFFF, 0xFFFF, 0xDF7F,
|
||||||
|
0xA1F7, 0x91FA, 0x81FF, 0x95F9, 0x81FF, 0x81FF, 0x8A1F, 0x81FF,
|
||||||
|
0x81FF, 0xD75F, 0xBEFF, 0x81FF, 0x81FF, 0xFFFF, 0xBEFF, 0x81FF,
|
||||||
|
0xB9CE, 0xB9CE, 0x8DFC, 0x81FF, 0xA9D2, 0xA9D2, 0x81FF, 0x9A5F,
|
||||||
|
0x99D6, 0x99D6, 0x81FF, 0xBEFF, 0x99D6, 0x99D6, 0x81FF, 0xBEFF,
|
||||||
|
0x85FD, 0x95F9, 0xB5CF, 0xB1F1, 0x81FF, 0x81FF, 0x95F9, 0x81FF,
|
||||||
|
0xEFBF, 0x81FF, 0x85FD, 0x81FF, 0xFFFF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xA5F5, 0xA5F5, 0xB5F2, 0xB214, 0x81FF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xB2BF, 0xB2BF, 0x81FF, 0x9A5F, 0xDF7F, 0xDF7F, 0x81FF, 0xE79F,
|
||||||
|
0xA218, 0xA218, 0xA218, 0xA639, 0x81FF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xBEFF, 0xBEFF, 0xBEFF, 0xBEFF, 0xF7DF, 0xDF7F, 0xDF7F, 0xDF7F,
|
||||||
|
0xA639, 0xB657, 0xCA75, 0xD294, 0x81FF, 0x81FF, 0x861E, 0xCA95,
|
||||||
|
0xBEFF, 0xAA9F, 0x81FF, 0xB658, 0xD75F, 0x8A1F, 0x81FF, 0xCA75,
|
||||||
|
0x81FF, 0xA27F, 0xFFFF, 0xA27F, 0x81FF, 0xA27F, 0xFFFF, 0xFFFF,
|
||||||
|
0x81FF, 0xA27F, 0xFFFF, 0xBADF, 0x81FF, 0xA27F, 0xFFFF, 0xA27F,
|
||||||
|
0x81FF, 0x81FF, 0xCF3F, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xBADF,
|
||||||
|
0xA27F, 0xA27F, 0xA27F, 0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0x923F, 0xFFFF, 0xBEFF, 0x81FF, 0x81FF, 0xFFFF, 0xBEFF, 0x81FF,
|
||||||
|
0x81FF, 0xFFFF, 0xCF3F, 0xA27F, 0x81FF, 0xFFFF, 0xFFFF, 0xFFFF,
|
||||||
|
0x99D6, 0x99D6, 0x81FF, 0xBEFF, 0x81FF, 0x81FF, 0x81FF, 0xBEFF,
|
||||||
|
0xA27F, 0xA27F, 0x9A5F, 0xBADF, 0xFFFF, 0xFFFF, 0xA27F, 0x81FF,
|
||||||
|
0xFFFF, 0x81FF, 0x81FF, 0x81FF, 0xFFFF, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xFFFF, 0xBEFF, 0xBEFF, 0xBEFF, 0xC71F, 0xDF7F, 0xDF7F, 0xDF7F,
|
||||||
|
0xDF7F, 0xDF7F, 0x923F, 0xF7DF, 0xDF7F, 0xDF7F, 0x81FF, 0xAA9F,
|
||||||
|
0xEFBF, 0xC71F, 0x81FF, 0x9A5F, 0xCF3F, 0x81FF, 0x8A1F, 0xD75F,
|
||||||
|
0xE79F, 0xBEFF, 0xBEFF, 0xBEFF, 0xDF7F, 0xDF7F, 0xDF7F, 0xDF7F,
|
||||||
|
0xBEFF, 0xBEFF, 0xBEFF, 0xC71F, 0xDF7F, 0xDF7F, 0xDF7F, 0xDF7F,
|
||||||
|
0xBEFF, 0x81FF, 0x81FF, 0xB657, 0xFFFF, 0xC71F, 0x81FF, 0xA23A,
|
||||||
|
0xFFFF, 0xC71F, 0x81FF, 0xA23A, 0xD75F, 0x8A1F, 0x81FF, 0xB658,
|
||||||
|
0x81FF, 0x9A5F, 0xAA9F, 0x81FF, 0x921D, 0x81FF, 0x81FF, 0x85FE,
|
||||||
|
0xD294, 0xBE55, 0xB657, 0xC653, 0xD294, 0xD294, 0xCE73, 0xCA52,
|
||||||
|
0x8A1D, 0xB214, 0xB214, 0x8DFC, 0xBA34, 0xC631, 0xC210, 0xB612,
|
||||||
|
0xC631, 0xC631, 0xC631, 0xC210, 0xCA52, 0xCA52, 0xC631, 0xC631,
|
||||||
|
0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x8DFC, 0x81FF, 0x81FF, 0x81FF,
|
||||||
|
0xC210, 0xBE10, 0xBDEF, 0xBDEF, 0xC210, 0xC210, 0xC210, 0xBE10,
|
||||||
|
0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x8DFB, 0xA5D4,
|
||||||
|
0xBDEF, 0xB9CE, 0xB9CE, 0xB9CE, 0xBDEF, 0xBDEF, 0xBDEF, 0xBDEF,
|
||||||
|
0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x99F8, 0x8DFB, 0x8DFB, 0x8DFB,
|
||||||
|
0xB9CE, 0xBDEF, 0xBDEF, 0xBDEF, 0xBDEF, 0xBDEF, 0xBE10, 0xC210,
|
||||||
|
0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x95F9, 0xA5F5, 0xA1F7, 0x91FA,
|
||||||
|
0xBDEF, 0xBE10, 0xC210, 0xC210, 0xC210, 0xC210, 0xC631, 0xC631,
|
||||||
|
0x81FF, 0x81FF, 0x81FF, 0x81FF, 0x921C, 0x921C, 0x921C, 0x921C,
|
||||||
|
0xC631, 0xC631, 0xCA52, 0xCA52, 0xC631, 0xCA52, 0xCA52, 0xCE73,
|
||||||
|
0x81FF, 0x81FF, 0x9A3B, 0xD294, 0x961B, 0xAA39, 0xD294, 0xD294,
|
||||||
|
0xCE73, 0xCE73, 0xD294, 0xD6B5, 0xCE73, 0xD294, 0xD6B5, 0xD6B5,
|
||||||
|
};
|
186
source/gx/gx_audio.c
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* gx_audio.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX audio support
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "shared.h"
|
||||||
|
|
||||||
|
/* DMA soundbuffers (required to be 32-bytes aligned)
|
||||||
|
Length is dimensionned for one frame of emulation (800/808 samples @60hz, 960 samples@50Hz)
|
||||||
|
To prevent audio clashes, we use double buffering technique:
|
||||||
|
one buffer is the active DMA buffer
|
||||||
|
the other one is the current work buffer (updated during frame emulation)
|
||||||
|
We do not need more since frame emulation and DMA operation are synchronized
|
||||||
|
*/
|
||||||
|
u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
|
||||||
|
|
||||||
|
/* Current work soundbuffer */
|
||||||
|
u32 mixbuffer;
|
||||||
|
|
||||||
|
/* audio DMA status */
|
||||||
|
u32 audioStarted;
|
||||||
|
|
||||||
|
/* Background music */
|
||||||
|
static u8 *Bg_music_ogg = NULL;
|
||||||
|
static u32 Bg_music_ogg_size = 0;
|
||||||
|
|
||||||
|
/***************************************************************************************/
|
||||||
|
/* Audio engine */
|
||||||
|
/***************************************************************************************/
|
||||||
|
|
||||||
|
/* Audio DMA callback */
|
||||||
|
static void ai_callback(void)
|
||||||
|
{
|
||||||
|
frameticker++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AUDIO engine initialization */
|
||||||
|
void gx_audio_Init(void)
|
||||||
|
{
|
||||||
|
/* Initialize AUDIO processing library (ASNDLIB) */
|
||||||
|
/* AUDIO & DSP hardware are initialized */
|
||||||
|
/* Default samplerate is set to 48kHz */
|
||||||
|
ASND_Init();
|
||||||
|
|
||||||
|
/* Load background music from FAT device */
|
||||||
|
char fname[MAXPATHLEN];
|
||||||
|
sprintf(fname,"%s/Bg_music.ogg",DEFAULT_PATH);
|
||||||
|
FILE *f = fopen(fname,"rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
struct stat filestat;
|
||||||
|
stat(fname, &filestat);
|
||||||
|
Bg_music_ogg_size = filestat.st_size;
|
||||||
|
Bg_music_ogg = memalign(32,Bg_music_ogg_size);
|
||||||
|
if (Bg_music_ogg)
|
||||||
|
{
|
||||||
|
fread(Bg_music_ogg,1,Bg_music_ogg_size,f);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AUDIO engine shutdown */
|
||||||
|
void gx_audio_Shutdown(void)
|
||||||
|
{
|
||||||
|
PauseOgg(1);
|
||||||
|
StopOgg();
|
||||||
|
ASND_Pause(1);
|
||||||
|
ASND_End();
|
||||||
|
if (Bg_music_ogg)
|
||||||
|
{
|
||||||
|
free(Bg_music_ogg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
gx_audio_Update
|
||||||
|
|
||||||
|
This function retrieves samples for the frame then set the next DMA parameters
|
||||||
|
Parameters will be taken in account only when current DMA operation is over
|
||||||
|
***/
|
||||||
|
void gx_audio_Update(void)
|
||||||
|
{
|
||||||
|
/* retrieve audio samples */
|
||||||
|
int size = audio_update() * 4;
|
||||||
|
|
||||||
|
/* set next DMA soundbuffer */
|
||||||
|
s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
|
||||||
|
DCFlushRange((void *)sb, size);
|
||||||
|
AUDIO_InitDMA((u32) sb, size);
|
||||||
|
mixbuffer ^= 1;
|
||||||
|
|
||||||
|
/* Start Audio DMA */
|
||||||
|
/* this is called once to kick-off DMA from external memory to audio interface */
|
||||||
|
/* DMA operation is automatically restarted when all samples have been sent. */
|
||||||
|
/* If DMA settings are not updated at that time, previous sound buffer will be used. */
|
||||||
|
/* Therefore we need to make sure frame emulation is completed before current DMA is */
|
||||||
|
/* completed, either by synchronizing frame emulation with DMA start or by syncing it */
|
||||||
|
/* with Vertical Interrupt and outputing a suitable number of samples per frame. */
|
||||||
|
/* */
|
||||||
|
/* In both cases, audio DMA need to be synchronized with VSYNC and therefore need to */
|
||||||
|
/* be resynchronized (restarted) every time video settings are changed (hopefully, */
|
||||||
|
/* this generally happens while no music is played. */
|
||||||
|
if (!audioStarted)
|
||||||
|
{
|
||||||
|
/* restart audio DMA */
|
||||||
|
AUDIO_StopDMA();
|
||||||
|
AUDIO_StartDMA();
|
||||||
|
audioStarted = 1;
|
||||||
|
|
||||||
|
/* resynchronize emulation */
|
||||||
|
frameticker = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
gx_audio_Start
|
||||||
|
|
||||||
|
This function restart the audio engine
|
||||||
|
This is called when coming back from Main Menu
|
||||||
|
***/
|
||||||
|
void gx_audio_Start(void)
|
||||||
|
{
|
||||||
|
/* shutdown background music */
|
||||||
|
PauseOgg(1);
|
||||||
|
StopOgg();
|
||||||
|
|
||||||
|
/* shutdown menu audio processing */
|
||||||
|
ASND_Pause(1);
|
||||||
|
AUDIO_StopDMA();
|
||||||
|
AUDIO_RegisterDMACallback(NULL);
|
||||||
|
DSP_Halt();
|
||||||
|
|
||||||
|
/* when TV mode does not match emulated video mode, frame emulation is synchronized with Audio Interface DMA */
|
||||||
|
if (gc_pal != vdp_pal)
|
||||||
|
{
|
||||||
|
AUDIO_RegisterDMACallback(ai_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset emulation audio processing */
|
||||||
|
memset(soundbuffer, 0, 2 * 3840);
|
||||||
|
audioStarted = 0;
|
||||||
|
mixbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
gx_audio_Stop
|
||||||
|
|
||||||
|
This function stops current Audio DMA process
|
||||||
|
This is called when going back to Main Menu
|
||||||
|
DMA need to be restarted when going back to the game (see above)
|
||||||
|
***/
|
||||||
|
void gx_audio_Stop(void)
|
||||||
|
{
|
||||||
|
/* restart menu audio processing */
|
||||||
|
DSP_Unhalt();
|
||||||
|
ASND_Init();
|
||||||
|
ASND_Pause(0);
|
||||||
|
|
||||||
|
/* play background music */
|
||||||
|
if (Bg_music_ogg && !Shutdown)
|
||||||
|
{
|
||||||
|
PauseOgg(0);
|
||||||
|
PlayOgg((char *)Bg_music_ogg, Bg_music_ogg_size, 0, OGG_INFINITE_TIME);
|
||||||
|
SetVolumeOgg(((int)config.bgm_volume * 255) / 100);
|
||||||
|
}
|
||||||
|
}
|
38
source/gx/gx_audio.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* gx_audio.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX audio support
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GC_AUDIO_H_
|
||||||
|
#define _GC_AUDIO_H_
|
||||||
|
|
||||||
|
extern u8 soundbuffer[2][3840];
|
||||||
|
extern u32 mixbuffer;
|
||||||
|
extern u32 audioStarted;
|
||||||
|
|
||||||
|
extern void gx_audio_Init(void);
|
||||||
|
extern void gx_audio_Shutdown(void);
|
||||||
|
extern void gx_audio_Start(void);
|
||||||
|
extern void gx_audio_Stop(void);
|
||||||
|
extern void gx_audio_Update(void);
|
||||||
|
|
||||||
|
#endif
|
1435
source/gx/gx_input.c
Normal file
53
source/gx/gx_input.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* gx_input.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX input support
|
||||||
|
*
|
||||||
|
* Eke-Eke (2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GC_INPUT_H_
|
||||||
|
#define _GC_INPUT_H_
|
||||||
|
|
||||||
|
/* max. supported inputs */
|
||||||
|
#ifdef HW_DOL
|
||||||
|
#define MAX_INPUTS 4
|
||||||
|
#else
|
||||||
|
#define MAX_INPUTS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Configurable keys */
|
||||||
|
#define MAX_KEYS 8
|
||||||
|
|
||||||
|
/* Key configuration structure */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
s8 device;
|
||||||
|
u8 port;
|
||||||
|
u8 padtype;
|
||||||
|
} t_input_config;
|
||||||
|
|
||||||
|
|
||||||
|
extern void gx_input_Init(void);
|
||||||
|
extern int gx_input_FindDevices(void);
|
||||||
|
extern void gx_input_SetDefault(void);
|
||||||
|
extern void gx_input_Config(u8 chan, u8 device, u8 type);
|
||||||
|
extern void gx_input_UpdateEmu(void);
|
||||||
|
extern void gx_input_UpdateMenu(u32 cnt);
|
||||||
|
|
||||||
|
#endif
|
1686
source/gx/gx_video.c
Normal file
74
source/gx/gx_video.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* gx_video.c
|
||||||
|
*
|
||||||
|
* Genesis Plus GX video support
|
||||||
|
*
|
||||||
|
* Softdev (2006)
|
||||||
|
* Eke-Eke (2007,2008,2009)
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GC_VIDEO_H_
|
||||||
|
#define _GC_VIDEO_H_
|
||||||
|
|
||||||
|
/* EFB colors */
|
||||||
|
#define BLACK {0x00,0x00,0x00,0xff}
|
||||||
|
#define DARK_GREY {0x22,0x22,0x22,0xff}
|
||||||
|
#define LIGHT_BLUE {0xb8,0xc7,0xda,0xff}
|
||||||
|
#define SKY_BLUE {0x99,0xcc,0xff,0xff}
|
||||||
|
#define LIGHT_GREEN {0xa9,0xc7,0xc6,0xff}
|
||||||
|
#define WHITE {0xff,0xff,0xff,0xff}
|
||||||
|
|
||||||
|
/* image texture */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 *data;
|
||||||
|
u16 width;
|
||||||
|
u16 height;
|
||||||
|
u8 format;
|
||||||
|
} gx_texture;
|
||||||
|
|
||||||
|
/* Global variables */
|
||||||
|
extern GXRModeObj *vmode;
|
||||||
|
extern u8 *texturemem;
|
||||||
|
extern u32 gc_pal;
|
||||||
|
|
||||||
|
|
||||||
|
/* GX rendering */
|
||||||
|
extern void gxDrawRectangle(s32 x, s32 y, s32 w, s32 h, u8 alpha, GXColor color);
|
||||||
|
extern void gxDrawTexture(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
|
||||||
|
extern void gxDrawTextureRepeat(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, u8 alpha);
|
||||||
|
extern void gxDrawTextureRotate(gx_texture *texture, s32 x, s32 y, s32 w, s32 h, f32 angle, u8 alpha);
|
||||||
|
extern void gxDrawScreenshot(u8 alpha);
|
||||||
|
extern void gxCopyScreenshot(gx_texture *texture);
|
||||||
|
extern void gxSaveScreenshot(char *filename);
|
||||||
|
extern void gxClearScreen(GXColor color);
|
||||||
|
extern void gxSetScreen(void);
|
||||||
|
|
||||||
|
/* PNG textures */
|
||||||
|
extern gx_texture *gxTextureOpenPNG(const u8 *png_data, FILE *png_file);
|
||||||
|
extern void gxTextureWritePNG(gx_texture *p_texture, FILE *png_file);
|
||||||
|
extern void gxTextureClose(gx_texture **p_texture);
|
||||||
|
|
||||||
|
/* GX video engine */
|
||||||
|
extern void gx_video_Init(void);
|
||||||
|
extern void gx_video_Shutdown(void);
|
||||||
|
extern void gx_video_Start(void);
|
||||||
|
extern void gx_video_Stop(void);
|
||||||
|
extern void gx_video_Update(void);
|
||||||
|
|
||||||
|
#endif
|
BIN
source/gx/images/Banner_bottom.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
source/gx/images/Banner_main.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
source/gx/images/Banner_top.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
source/gx/images/Bg_credits.png
Normal file
After Width: | Height: | Size: 285 KiB |
BIN
source/gx/images/Bg_intro_c1.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
source/gx/images/Bg_intro_c2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
source/gx/images/Bg_intro_c3.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
source/gx/images/Bg_intro_c4.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
source/gx/images/Bg_intro_c5.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
source/gx/images/Bg_layer.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
source/gx/images/Bg_main.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
source/gx/images/Bg_main_2.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
source/gx/images/Bg_overlay.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
source/gx/images/Browser_dir.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
source/gx/images/Button_arrow.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
source/gx/images/Button_arrow_over.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
source/gx/images/Button_delete.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
source/gx/images/Button_delete_over.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
source/gx/images/Button_digit.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
source/gx/images/Button_digit_over.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
source/gx/images/Button_down.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
source/gx/images/Button_down_over.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
source/gx/images/Button_icon.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
source/gx/images/Button_icon_over.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
source/gx/images/Button_icon_sm.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
source/gx/images/Button_icon_sm_over.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
source/gx/images/Button_load.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
source/gx/images/Button_load_over.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
source/gx/images/Button_save.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
source/gx/images/Button_save_over.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
source/gx/images/Button_sm_blue.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
source/gx/images/Button_sm_grey.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
source/gx/images/Button_sm_yellow.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
source/gx/images/Button_special.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
source/gx/images/Button_special_over.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
source/gx/images/Button_text.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
source/gx/images/Button_text_over.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
source/gx/images/Button_up.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
source/gx/images/Button_up_over.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
source/gx/images/Crosshair_p1.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
source/gx/images/Crosshair_p2.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
source/gx/images/Ctrl_4wayplay.png
Normal file
After Width: | Height: | Size: 5.4 KiB |