Compare commits

..

No commits in common. "main" and "1.4" have entirely different histories.
main ... 1.4

73 changed files with 7631 additions and 7480 deletions

Binary file not shown.

1
A7800DS.pnproj Normal file
View file

@ -0,0 +1 @@
<Project name="A7800DS"><Folder name="arm7"><File path="arm7\Makefile"></File><File path="arm7\source\main.c"></File><File path="arm7\source\emusoundfifo.c"></File></Folder><Folder name="arm9"><Folder name="emu"><Folder name="zip"><File path="arm9\source\emu\zip\ioapi.c"></File><File path="arm9\source\emu\zip\ioapi.h"></File><File path="arm9\source\emu\zip\miniunz.c"></File><File path="arm9\source\emu\zip\miniunz.h"></File><File path="arm9\source\emu\zip\unzip.c"></File><File path="arm9\source\emu\zip\unzip.h"></File><File path="arm9\source\emu\zip\zip.c"></File><File path="arm9\source\emu\zip\zip.h"></File></Folder><File path="arm9\source\emu\Archive.c"></File><File path="arm9\source\emu\Archive.h"></File><File path="arm9\source\emu\Bios.c"></File><File path="arm9\source\emu\Bios.h"></File><File path="arm9\source\emu\Cartridge.c"></File><File path="arm9\source\emu\Cartridge.h"></File><File path="arm9\source\emu\Database.c"></File><File path="arm9\source\emu\Database.h"></File><File path="arm9\source\emu\Equates.h"></File><File path="arm9\source\emu\Hash.c"></File><File path="arm9\source\emu\Hash.h"></File><File path="arm9\source\emu\Logger.c"></File><File path="arm9\source\emu\Logger.h"></File><File path="arm9\source\emu\Maria.h"></File><File path="arm9\source\emu\Memory.c"></File><File path="arm9\source\emu\Memory.h"></File><File path="arm9\source\emu\Pair.h"></File><File path="arm9\source\emu\Palette.c"></File><File path="arm9\source\emu\Palette.h"></File><File path="arm9\source\emu\Pokey.c"></File><File path="arm9\source\emu\Pokey.h"></File><File path="arm9\source\emu\ProSystem.h"></File><File path="arm9\source\emu\Rect.h"></File><File path="arm9\source\emu\Region.c"></File><File path="arm9\source\emu\Region.h"></File><File path="arm9\source\emu\Riot.c"></File><File path="arm9\source\emu\Riot.h"></File><File path="arm9\source\emu\Sally.h"></File><File path="arm9\source\emu\shared.h"></File><File path="arm9\source\emu\Sound.c"></File><File path="arm9\source\emu\Sound.h"></File><File path="arm9\source\emu\Tia.h"></File><File path="arm9\source\emu\Sally.itcm.c"></File><File path="arm9\source\emu\ProSystem.c"></File><File path="arm9\source\emu\Maria.c"></File><File path="arm9\source\emu\Tia.itcm.c"></File></Folder><Folder name="Fst6502"><File path="arm9\source\emu\Fst6502\Fst6502.h"></File><File path="arm9\source\emu\Fst6502\Fst6502.s"></File><File path="arm9\source\emu\Fst6502\Fst6502_interface.c"></File><File path="arm9\source\emu\Fst6502\Fst6502_interface.h"></File></Folder><File path="arm9\Makefile"></File><File path="arm9\source\main.c"></File><File path="arm9\source\a7800utils.h"></File><File path="arm9\source\a7800utils.c"></File><File path="arm9\source\intro.h"></File><File path="arm9\source\intro.c"></File></Folder><File path="readme.txt"></File><File path="Makefile"></File></Project>

View file

@ -1,4 +1,4 @@
VERSION=5.1
VERSION=1.4
TARGNAME=A7800DS
#---------------------------------------------------------------------------------
@ -13,7 +13,7 @@ include $(DEVKITARM)/ds_rules
export TARGET := $(shell basename $(TARGNAME))
export TOPDIR := $(CURDIR)
ICON := -b $(CURDIR)/logo.bmp "A7800DS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/A7800DS"
ICON := -b $(CURDIR)/logo.bmp "A7800DS $(VERSION);AlekMaul;http://www.portabledev.com"
.PHONY: arm7/$(TARGET).elf arm9/$(TARGET).elf

432
README.md
View file

@ -1,432 +0,0 @@
# a7800DS
a7800DS is an Atari ProSystem 7800 console emulator for the DS/DSi.
To use this emulator, you must use compatible roms with a78/bin format.
Strongly recommend you use NTSC roms... PAL ones have more scanlines and will render
more slowly and since the sound core is tied to scanlines, the sound will be wrong.
All the debug on this port to the DS has been done with NTSC roms - seek them out!
Do not ask me about such files, I only supply the emulator. A search with Google will certainly
help you. The emulator was developed using Trebor's "7800 ProPack" of well-curated games.
The emulator will auto-start in /roms/a7800 or /roms/a78 if those directories exist.
Features :
----------
Most things you should expect from an emulator. Speed is excellent on the DSi and
a little less great on the older DS-LITE. For the DS-LITE you can expect full speed on
a very large chunk of the 7800 library. The more traditional games (think: Asteroids,
Astro Blaster, Robotron, Food Fight, Centipede, Pac-Man Collection, etc) will
all run great. The really big bankswitched games may struggle on the older
DS-LITE/PHAT hardware - try the game and see!
The emulator will support ROMs up to 1024K (1MB!) in size + the 128 byte .a78 header.
All popular bank-switching schemes are supported including an extra 16K of RAM at 4000h.
Pokey support at 4000h, 800h and 450h - change this in Configuration if it's not auto-detected.
The Banksets scheme is fully supported - this new banking/memory handling is designed
for homebrew authors to provide increased ROM density and improved packing and access of
graphics data vs code. This allows for games that would have been difficult or impossible
without the scheme. See http://7800.8bitdev.org/index.php/Bankset_Bankswitching for more details.
Add highscore.rom for 7800 High Score saving. This can be in /roms/bios, /data/bios
or in the same directory as the emulator. It's worth the effort to track down the highscore.rom file!
If you want to use a real Atari 7800 BIOS, find yourself the 4K version and place it
into the same directory as mentioned in the paragraph above.
Copyright :
----------
A7800DS is Copyright 2021-2025 by Dave Bernazzani (wavemotion-dave).
This emulator is based heavily upon ProSystem and that emulator was released
in 2005 by Greg Stanton under the GNU General Public License and, as such,
this derived work is released in the same manner. The original license text
that Greg used is included here:
```
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
```
Philosophy :
----------
For this particular emulator, we use ProSystem as the base. That's always been a bit
problematic in terms of accuracy - often resulting in small graphical glitches and
other artifacts on screen. However, in the past year I've worked out many of those
issues and most of the games look, sound and play great now. However, do not expect
perfect emulation - if you're looking for a highly accurate emulator for the 7800
ProSystem, this isn't it - try A7800 or JS7800 instead. But if you're looking to enjoy
some classic 7800 console goodness on your DS/DSi then you've come to the right place!
Known Issues and Limitations:
----------
- Lightgun is not supported.
- Paddles are not supported.
- PAL is not supported - use NTSC instead.
- Souper mapper (Ricky & Vicky) is not supported.
- Keystone Koppers and ARTI have slight sound issues as Pokey emulation is not perfect.
- Only one Pokey is supported at 4000h, 800h or 450h (no Dual Pokey).
- XM is not supported (beyond HSC and Pokey).
--------------------------------------------------------------------------------
How to use a7800DS :
--------------------------------------------------------------------------------
Place .NDS on your SD card and launch with Twilight Menu++ or Unlaunch.
If you want to run on a flash cart place it as you would any homebrew pretty
much anywhere on your flashcart SD card.
If you want to use a real Atari 7800 BIOS, find yourself the 4K version and place
this file named exactly 7800.rom in the /roms/bios directory (alternate locations
are /data/bios or you can place it in the same directory as the emulator).
When the emulator starts, click on the cartridge slot to choose a file. Use Up/Down
to select a file, then use A to load it.
Controls :
* Direction pad : the joystick ...
* A : Fire button 1
* B : Fire button 2
* SELECT : SELECT Button
* START : PAUSE Button
* X : Configurable (default: Pan Screen Down)
* Y : Configurable (default: Pan Screen Up)
* L/R + DPAD : Used to Shift Offsets and Scale Screen to desired ratio
* L + R + X : Hold for 1 second to swap LCD screens top/bottom
Use stylus on buttons for other actions on bottom screen.
The new SNES2Atari adaptor is supported as a controller type for the few new games
that utilize it. This allows all of the DS buttons to map into the game - exactly
as labeled (D-Pad plus ABXY, Left Shoulder, Right Shoulder and Start, Select).
High Score Saving works if you have highscore.rom (exact name) in your
roms directory where you load your games... The .hsc backing file will be written
automatically as the game runs. Only games programmed to use the highscore cart
will save scores.
Configuration :
----------
Generally you would use this to select a bankswitching scheme if the proper type wasn't auto-detected.
The following schemes are supported:
* NORMAL Anything 48K or less... fits into memory (0xffff downwards) without switching.
* SUPERCART Games that are 128+K in size with nothing mapped in at 0x4000
* SUPERCART_LARGE Games that are 144+K in size with the extra 16K bank 0 fixed at 0x4000
* SUPERCART_RAM Games that are 128+K in size with extra 16K of RAM at 0x4000
* SUPERCART_ROM Games that are 128+K in size with bank 6 fixed at 0x4000
* SUPERCART_RAMX2 Games that are 128+K in size with extra 32K of RAM at 0x4000 (bankswitched in 16K chunks)
* FLAT WITH RAM Games that are 16K or 32K in size and utilize 16K of RAM at 0x4000
* BANKSETS Games that use the new Banksets handling (2x32, 2x48, 2x52, 2x128, 2x256 and 2x512 supported).
* BANKSETS RAM Games that use the new Banksets handling with 16K of RAM at 0x4000 (same RAM for Maria and Sally).
* BANKSETS HALT RAM Games that use the new Banksets handling with 16K of RAM at 0x4000 (Maria and Sally see different 16K RAM).
* ACTIVISION Mostly for Double Dragon and Rampage by Activision
* ABSOLETE Only for the F-18 Hornet game by Absolete Entertainment
* FRACTALUS Only for the Rescue on Fractalus prototype (not a complete game but neat to see). This is EXRAM/A8.
Frame Skipping can be OFF (show all frames), Moderate (Show 3/4 frames) or Agressive (only show 1/2 frames). The latter is
only really needed for the DS-Lite/Phat where the faster DSi CPU isn't available.
Press START to save off your configuration - if you made changes you should re-load the game to ensure all settings are applied.
Of Mice, Men and Screen Resolutions :
----------
The DS/DSi has a native screen resolution of 256x192. This is not ideal for the Atari 7800 where many of the games are 320
pixels across and often more than 192 scanlines. The original Atari NTSC spec called for 192 vertical scanlines and a few
of the early games (Asteroids, Ms. Pac-Man, etc.) did stick to that but most later games utilize more vertical scanlines.
A typical NTSC TV can handle 230+ scanlines fairly well and so many of the Atari 7800 games utilize some number of extra
scanlines to pack as much awesome gameplay as possible onto the screen.
This is a problem for our hero, the DS/DSi. Fortunately the DS has the ability to scale/stretch as needed. But when doing
so, there will be missing scanlines. For example, if the game utilizes 200 scalines but the DS can only show 192, there are
8 scanlines that must go missing... if scaled down to 192 pixels to fit the screen, these extra scalines might be in the
middle of the playfield which is not great. If you scale the screen up (using Configuration options or the L/R shoulder
buttons in conjunction with the D-PAD to shift/scale the sceren), then some of the pixels (left or right, up or down) will
be cropped off the screen. This might not be a big deal - sometimes the very top and bottom of a game are just clouds or
ground that can be safely cropped without any loss in gameplay. For many games, the top 16 pixels are the score / lives
remaining.
Most games have scaling defaults that look good enough. Some games will cut off a few pixel lines at the top and bottom - but
they will still be perfectly playalbe. However there are some thigns you can (and should!) do to help.
Recent versions of the emulator have a magnifying glass icon that will zoom and center the display to 1:1 of the actual 7800 output.
This will crop some pixels off the sides and top/bottom but is useful to temporarily zoom up to enter things like high scores
where the text may be hard to read when shrunk down.
More importantly, you can utilize the X and Y buttons as a pan down/up. This is massively useful for games that have a score at
the top of the display (Galaxian, Space Invaders, Popeye, bonQ, etc). Here you can stretch up the screen in the Y direction so
that it is nearly 1:1 and shift the score off the top of the screen. Then, during gameplay, you can tap the X button to temporarily
pan the display down so the score comes into view briefly... and it will magically shift back up after a half second. You can do
this while you are playing - usually when you lose a life you can tap the X button to quickly glace at your score. This gives
more useable scanlines for actual gameplay. Think of this like you're at the arcade and you have to glance up to see your
score when focused on the field of play. It takes a little getting used to but this mechanism really helps map the more complicated
game graphics onto the small sceren. Of course youc an always scale the screen down to it's totally visible - but there will be
some loss of scanline information. Experiment and determine what works best for you. Many of the popular games already have
the screen set to perfectly pan up/down to bring in the score/status while leaving the playfield as close to 1:1 as possible.
And remember - once you get your screen settings the way you want, be sure to go into the GEAR icon and hit START to save out
your current configuration (which includes your screen offset/scaling tweaks on a per-game basis).
--------------------------------------------------------------------------------
Credits:
--------------------------------------------------------------------------------
* Thanks Wintermute for devkitpro and libnds (http://www.devkitpro.org).
* Greg Stanton for ProSystem source code (https://home.comcast.net/~gscottstanton/) an Atari 7800 emulator.
* zx81 (http://zx81.zx81.free.fr/serendipity_fr/) for PSP A7800 version (that helped to understand ProSystem).
* raz0red (http://www.twitchasylum.com/forum/viewtopic.php?t=519) for WII7800 (that helped me to fix some timing problems).
* The folks at AtariAge who helped weed out many of the old ProSystem Maria rendering and timing issues.
* The MAXMOD audio library is Copyright (c) 2008, Mukunda Johnson (mukunda@maxmod.org). See https://github.com/devkitPro/maxmod
--------------------------------------------------------------------------------
Original Author:
Alekmaul
alekmaul@portabledev.com
http://www.portabledev.com
Updates by wavemotion-dave: https://github.com/wavemotion-dave/A7800DS
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
History :
--------------------------------------------------------------------------------
V5.1 : 27-Feb-2025 by wavemotion-dave
* 7800 BIOS is now supported. Place bios exactly named '7800.rom' in /roms/bios, /data/bios or same directory as the emulator itself.
* New internal database with many cleanups and corrections. Now compliant with Trebor Pro-Pack v8_16 from early 2025.
* New configuration option to allow mapping both both X and Y buttons.
* Maria and CPU cycle counting are much closer to real hardware - all of the DMA Cycle adjustments/hacks have been removed.
* This fixes a number of small problems such as Pole Position II joystick selection of track when game loads.
V5.0 : 21-Feb-2025 by wavemotion-dave
* Kangaroo mode fixed and fully implemented. Cleans up some small graphical glitches on a number of games.
* Composite Artifacting implemented for Tower Toppler and Jinks.
* Sound handler fixed so that drop-outs of sounds are eliminated (or at least greatly minimized).
* The X button on the NDS is now configurable to a range of joystick/console buttons.
V4.9 : 17-Feb-2025 by wavemotion-dave
* High Score (HSC) auto-save improvements - no longer write the backing .hsc file if the write didn't actually change HSC data.
* Improved Sally emulation accuracy and optimization pass to render the games 3-4% faster.
* Improved Pokey emulation - missing sounds on games like Ballblazer are now much better.
* Improved memory emulation for more accurate mirror handling - 7800 Utility cart now shows this as a PASS.
* Improved memory caching to help with the really big games (those 512K or larger).
* All but two games on the DSi are now rendered without any form of frameskip. Older DS-Lite/Phat reduces frameskip due to new optimizations.
V4.8 : 15-Feb-2025 by wavemotion-dave
* High Score (HSC) now auto-saves the .hsc file after it is written by the game. The HSC button is gone.
* Smoother console button operation so that a press is registered more consistently and with better debounce.
* Improved magnifying glass icon debounce so that it registers more consistently and with better debounce.
* New game icon to align with the other emulators in the Atari lineup on the DS.
V4.7 : 11-May-2024 by wavemotion-dave
* X and Y buttons now shift the screen down/up by 16 pixels so you can position the score off-screen and use these to pan up/down to see it.
* Fix for Supercarts so that they start in bank 0 (Legend of Silverpeak should now load)
* Internal database tweaks for the latest homebrews and ports.
* Other minor tweaks and improvements as time permitted.
V4.6 : 06-May-2024 by wavemotion-dave
* Each game that utilizes a High Score Cart (HSC) gets its own 2K .hsc file
* Improved High Score Cart (HSC) emulation - improved initialization of the SRAM contents.
* Sanity checks added so that carts marked as 'NORMAL' (or selected as such) but are larger than 48K will not corrupt memory.
* New magnifying glass icon to ZOOM (and center) the display 1:1 with real 7800 output. This will crop on a DS/DSi since it only has 256x192 but very useful to toggle the 1:1 zoom for High Score Entries, etc.
* Support for .a78 V4 headers (will fall back to V3 if not available)
V4.5 : 18-Nov-2022 by wavemotion-dave
* SNES2Atari adaptor supported.
* Improved display output to smooth over the fonts a bit.
* Small tweaks to internal database to ensure everything looks as good as possible.
V4.4 : 14-Nov-2022 by wavemotion-dave
* New palette options from the Trebor 'Pro Pack' of colors. COOL, WARM (default), and HOT allow you to shift the color temperature slightly on a per-game basis.
* Improved sound channel mixing so as not to halve the volume when mixing POKEY + TIA.
V4.3 : 11-Nov-2022 by wavemotion-dave
* Full support for the new Banksets scheme including the upcoming Attack of the Petscii Robots game!
* Added the stable "illegal" opcode support for the 6502 CPU to ensure all games run properly.
* New Maria cycle handling is more accurate than it's been in any previous version. More games run closer to perfect.
* Improved rendering and a bit more optmization to make almost every game playable on the older DS-Lite.
V4.2 : 06-Nov-2022 by wavemotion-dave
* Added support for bankswitched RAM (32K of RAM swiched in 16K chunks). This makes the Ex version of 1942 playable.
* Added alternate way of handling bankswitched RAM the same way as the DragonFly cart or SN board: via writes to 0xFFFF.
* Fix graphical glitch for Ballblazer (just hiding it off screen).
* Numerous small updates to the internal cart database to ensure game run with the proper settings (mostly High Scores)
* New 8x density on the High Score Cart - transparent to the user but provides more slots so the HSC won't fill up.
* Flat 32K plus RAM cart type supported.
* Pokey @800 supported for upcoming homebrews.
V4.1 : 02-Nov-2022 by wavemotion-dave
* Overhaul Maria cycle stealing - all games now use the proper cycle stealing with much closer to accurate timing. This fixes games like One-on-One and Kung Fu Master.
* Other minor cleanups and tweaks as time permitted.
V4.0 : 01-Nov-2022 by wavemotion-dave
* Overhaul the audio system to use the MAXMOD streaming library to eliminate sound 'zingers'
* Other minor cleanup and tweaks as time permitted.
V3.9 : 29-Oct-2022 by wavemotion-dave
* More optmization and more games playable on the DS-Lite.
* Highscore A7800.SRAM file moved to /data (move yours manually) - this allows the same high score file even if your roms are in different directories.
* Fix for One-on-One.
* Fix for voices in Jinx.
* Cleanup of code - removed unused functions and vars. Switched to a memory-lite sprintf().
V3.8 : 26-Oct-2022 by wavemotion-dave
* Massive optmization of the Maria rendering to help the DS-Lite run more games.
* Fix for Rampage
* Fix for Rescue on Fractalus
* Fix for F-18 Hornet
* Fix for Double Dragon
* Fix for Basketbrawl
* Better A78 header parsing for improved game detection
* New Moderate Frameskip to show 3/4 frames (not as aggressive as the old 1/2 frameskip)
* Support for 1024K (+128 byte header) games. Only a few tech demos available so far.
* Removed most of the old hacks for DS-Lite as the speed is good enough to render those games properly.
V3.7 : 23-Oct-2022 by wavemotion-dave
* Optmization across the board for faster and smoother performance.
* Gained enough speed that we have restored full HQ sound for the DS-Lite.
* bonQ fixed graphical glitches.
* Keystone Koppers fixed graphical glitches.
* Latest homebrews added to the internal database.
* New configuration menu so you can tweak settings - new homebrews won't need a new A7800DS.
* Better A78 v3 header support so more games run right.
V3.6 : 04-Jun-2022 by wavemotion-dave
* Fix for XM detection so the newest Pac-Man Collection (PMC-XM) works!
* Minor database cleanups so all the more recent games run.
V3.5 : 12-Feb-2022 by wavemotion-dave
* Across the board cleanup of code. Copyright notice added.
* Fixed High-Score save on Time Salvo
* Slight memory optmization for reduced memory footprint.
V3.4 : 6-Feb-2022 by wavemotion-dave
* Frameskip rendering improved by more than 10% - making more DS-LITE games playable!
* Minor improvements to touch-screen key handling and other code cleanups.
V3.3 : 4-Feb-2022 by wavemotion-dave
* Squeezed out another frame of performance.
* Super Skateboardin' graphics fixed.
* DSi eliminates frameskip on 80% of the library.
* Updated 50 entries in the internal database - more new homebrews run.
V3.2 : 1-Feb-2022 by wavemotion-dave
* A 5-8% speedup across the board through a number of small optimizations in core areas.
V3.1 : 31-Jan-2022 by wavemotion-dave
* Now using more VRAM for bank swapping and partial DMA transfer to speed up large games.
* Reverted part of the sound core to improve sound quality.
* File selection cleanups to scroll less fast and be generally easier to see.
V3.0 : 06-Nov-2021 by wavemotion-dave
* Reworked sound output core so it's now zinger-free!
* Refresh of bottom screen - improved font and button debounce.
V2.9 : 03-Nov-2021 by wavemotion-dave
* Fixed loading of large SUPER CART roms.
V2.8 : 02-Nov-2021 by wavemotion-dave
* A bit of speed - enough to eliminate the old DS-LITE version.
* A few new homebrews added to the internal database.
* Optmized sound buffers for (very) slightly better performance.
* highscore.rom can now bin in /roms/bios or /data/bios
* Cleanup code as time permitted.
V2.7 : 02-Apr-2021 by wavemotion-dave
* New support for the latest homebrews: Galaxian final
* Added ability to swap screens using L+R+A
V2.6 : 02-Apr-2021 by wavemotion-dave
* Faster directory/file listing.
* Support for the latest homebrews: Galaxian and Popeye
* Improved scaling and offset handling using L/R + Arrow Keys to match other emulators.
V2.5 : 15-Jan-2021 by wavemotion-dave
* Added .A78 header naming search and as a backup filename search to help
properly identify the game being loaded so that the right settings can be applied.
V2.4 : 8-Jan-2021 by wavemotion-dave
* Improvement in bank switching allowing most games to run 60FPS.
V2.3 : 6-Jan-2021 by wavemotion-dave
* Fixed large cart support so 512kb games run fine.
* Fixed voice in Frenzy/Berzerk.
* Fixed graphical glitches in Alien Brigade.
* Optmized bank switching so more big games run smoothly.
* Added default difficulty switches for the few games that need them.
* Lots of cleanups as time permitted.
V2.2 : 5-Jan-2021 by wavemotion-dave
* More memory tweaks - faster processing of memory for another 5% speedup.
V2.1 : 3-Jan-2021 by wavemotion-dave
* Now using DTCM and VRAM for some key memory areas to speed up the emulator almost 10%
V2.0 : 1-Jan-2021 by wavemotion-dave
* Pokey and TIA sound core reworked to provide sound that is worth listening to.
* Please run on a DSi, DSi-XL/LL or 3DS. You won't be happy with the performance on a DS-LITE/PHAT.
V1.9 : 31-Dec-2020 by wavemotion-dave
* Robotron now works with with Twin-Sticks!
* Minor cleanup and polish to end the year...
V1.8 : 23-Dec-2020 by wavemotion-dave
* Major improvements to CPU core to get about 10% speed boost across the board.
More games playable at full speed on DSi and above. Special DS-LITE build
included that supports only the smallest and most basic games (but at near
full speed).
V1.7a : 21-Dec-2020 by wavemotion-dave
* Full Pokey Support at both 450 and 4000. XM RAM mapping at 4000 so games
like Serpentine will run properly now. Undocumented opcodes for the Sally
processor now implemented so games like Popeye will run fine.
V1.7 : 20-Dec-2020 by wavemotion-dave
* After much thought and debug, I've ditched Kangaroo mode. As near as I can
tell it's used on only a couple of games and not for gameplay - and it costs
more DS-CPU time than it's worth. There is no harm other than a potential
graphical glitch which I've not noticed and that CPU time is precious.
V1.6b : 19-Dec-2020 by wavemotion-dave
* Fixed bug causing black rectangles on some games - thanks to Wii-7800!
V1.6 : 17-Dec-2020 by wavemotion-dave
* Minor cleanup. Rebranding to PHOENIX EDITION.
V1.5 : 15-Dec-2020 by wavemotion-dave
* Overhaul of scaling and X/Y offsets so that more games look pixel perfect.
* More homebrews run... compatibility table added to the back end of this doc.
* More robust handling of High Score Cart and saving of files.
V1.4 : 13-Dec-2020 by wavemotion-dave
* Implemented Hiscore Saving per the HSC cart. Put the 4k highscore.rom (don't ask)
where your ROMs live. If found, it will enable saving of high scores
on all 9 original games (Asteroids, Joust, Centipede, Xevious, Dig Dug, Galaga,
Food Fight, Ms Pac-Man and Robotron) as well as most of the newer homebrews.
V1.3 : 12-Dec-2020 by wavemotion-dave
* Backported some fixes and emulation timing improvments from Prosystem 1.3g
plus the Wii version. Renders a few more games playable.
* Fixed region for Froggie and Beef Drop - they now look right and play
at full speed.
* Minor other improvements as time permitted.
V1.2 : 10-Dec-2020 by wavemotion-dave
* More speed improvements. Fixed some 320 pixel games. Improved sound.
V1.1 : 09-Dec-2020 by wavemotion-dave
* Brought back to life... cleanup and about a 50% speed improvement, better
screen rendering/scaling and slightly improved UI features.
V1.0 : 24/05/2011
* Initial release based on my a320 version (which is based on Prosystem 1.0.3)
* Compiled with last version of Devkitpro/libnds, so DSi compatible \o/

Binary file not shown.

View file

@ -24,7 +24,7 @@ DATA :=
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork
CFLAGS := -g -Wall -O2\
CFLAGS := -g -Wall -O3\
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-ffast-math \
$(ARCH)
@ -36,8 +36,8 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
#LIBS := -ldswifi7 -lmm7 -lnds7 -lmm7
LIBS := -ldswifi7 -lnds7 -lmm7
#LIBS := -ldswifi7 -lmm7 -lnds7
LIBS := -ldswifi7 -lnds7
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View file

@ -9,8 +9,7 @@ typedef enum {
} FifoMesType;
//---------------------------------------------------------------------------------
void soundEmuDataHandler(int bytes, void *user_data)
{
void soundEmuDataHandler(int bytes, void *user_data) {
int channel = -1;
FifoMessage msg;
@ -41,8 +40,7 @@ void soundEmuCommandHandler(u32 command, void* userdata) {
int data = command & 0xFFFF;
int channel = (command >> 16) & 0xF;
switch(cmd)
{
switch(cmd) {
case SOUND_SET_VOLUME:
SCHANNEL_CR(channel) &= ~0xFF;
@ -77,8 +75,7 @@ void soundEmuCommandHandler(u32 command, void* userdata) {
}
//---------------------------------------------------------------------------------
void installSoundEmuFIFO(void)
{
void installSoundEmuFIFO(void) {
fifoSetDatamsgHandler(FIFO_USER_01, soundEmuDataHandler, 0);
fifoSetValue32Handler(FIFO_USER_01, soundEmuCommandHandler, 0);
}

View file

@ -32,7 +32,6 @@
#include <maxmod7.h>
extern void installSoundEmuFIFO(void);
extern void mmInstall( int fifo_channel );
//---------------------------------------------------------------------------------
void VblankHandler(void) {
@ -55,10 +54,9 @@ void powerButtonCB() {
exitflag = true;
}
void mmInstall(int);
//---------------------------------------------------------------------------------
int main() {
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
readUserSettings();
@ -68,7 +66,7 @@ int main() {
touchInit();
fifoInit();
mmInstall( FIFO_MAXMOD );
//mmInstall(FIFO_MAXMOD);
SetYtrigger(80);
@ -77,10 +75,12 @@ int main() {
installSystemFIFO();
irqSet(IRQ_VCOUNT, VcountHandler);
irqSet(IRQ_VBLANK, VblankHandler);
installSoundEmuFIFO();
irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK);
irqSet(IRQ_VCOUNT, VcountHandler);
//irqSet(IRQ_VBLANK, VblankHandler);
irqEnable( IRQ_VCOUNT | IRQ_NETWORK);
setPowerButtonCB(powerButtonCB);

View file

@ -14,10 +14,10 @@ include $(DEVKITARM)/ds_rules
# DATA is a list of directories containing binary files
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD := build
BUILD := build
SOURCES := source/emu source
INCLUDES := source/emu source include
DATA := data
DATA := data
GRAPHICS := gfx
#---------------------------------------------------------------------------------
@ -26,19 +26,22 @@ GRAPHICS := gfx
#ARCH := -mthumb -mthumb-interwork
ARCH :=
#CFLAGS := -g -Wall -O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(ARCH)
CFLAGS := -Wall -Ofast -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math -fsigned-char $(ARCH)
CFLAGS += $(INCLUDE) -DARM9
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s
#ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s
ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s
LDFLAGS = -specs=ds_arm9.specs $(ARCH) -Wl,-Map,$(notdir $*.map)
#LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LDFLAGS = -specs=ds_arm9.specs $(ARCH) -Wl,-Map,$(notdir $*.map)
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lfat -lnds9 -lmm9
LIBS := -lfat -lnds9
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
@ -53,7 +56,7 @@ LIBDIRS := $(LIBNDS)
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export ARM9ELF := $(CURDIR)/$(TARGET).elf
export ARM9ELF := $(CURDIR)/$(TARGET).elf
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
@ -120,8 +123,13 @@ $(ARM9ELF) : $(OFILES)
@$(bin2o)
%.s %.h : %.png
# grit $< -fts -W3 -gT! -gzl -gB16 -gb -o$*
grit $^ -o $@ -gt -mrt -mR8 -mLs -gzl -mzl
#%.gif.o : %.gif
# @echo $(notdir $<)
# @$(bin2o)
%.wav.o : %.wav
@echo $(notdir $<)
@$(bin2o)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,3 @@
// =====================================================================================
// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, it's source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and wavemotion-dave (Phoenix-Edition),
// Alekmaul (original port) and Greg Stanton (ProSystem Emulator) are thanked profusely.
//
// A7800DS emulator is offered as-is, without any warranty.
//
// The original GPL license:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// =====================================================================================
#ifndef _A7800UTILS_H
#define _A7800UTILS_H
@ -33,7 +7,7 @@
#define A7800_PLAYGAME 0x04
#define A7800_QUITSTDS 0x05
extern short int emu_state;
extern int etatEmu;
typedef enum {
EMUARM7_INIT_SND = 0x123C,
@ -43,13 +17,14 @@ typedef enum {
typedef struct FICtoLoad {
char filename[255];
u8 directory;
bool directory;
unsigned int uCrc;
} FICA7800;
typedef struct {
unsigned int sndLevel;
unsigned int m_ScreenRatio; // 0 = original show, 1 = full screen
unsigned short DS_Pad[16]; // each key mapping
unsigned short DS_Pad[12]; // each key mapping
unsigned int m_DisplayFPS;
} gamecfg;
@ -57,14 +32,20 @@ typedef struct {
extern gamecfg GameConf;
extern uint video_height; // Actual video height
extern unsigned short *bufVideo; // Video buffer
extern unsigned int gameCRC; // crc checksum of file
extern void FadeToColor(unsigned char ucSens, unsigned short ucBG, unsigned char ucScr, unsigned char valEnd, unsigned char uWait);
extern unsigned long crc32 (unsigned int crc, const unsigned char *buf, unsigned int len);
extern void vblankIntr();
extern void dsInitScreenMain(void);
extern void dsInitTimer(void);
extern void dsShowScreenEmu(void);
extern void dsShowScreenMain(bool);
extern void dsShowScreenMain(void);
extern void dsFreeEmu(void);
extern void VsoundHandler(void);
extern void dsLoadGame(char *filename);

View file

@ -1,389 +0,0 @@
// =====================================================================================
// Copyright (c) 2022-2025 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, it's source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and wavemotion-dave (Phoenix-Edition),
// Alekmaul (original port) and Greg Stanton (ProSystem Emulator) are thanked profusely.
//
// A7800DS emulator is offered as-is, without any warranty.
//
// The original GPL license:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// =====================================================================================
#include <nds.h>
#include <stdio.h>
#include <fat.h>
#include <dirent.h>
#include <unistd.h>
#include "config.h"
#include "Region.h"
#include "bgBottom.h"
#include "bgFileSel.h"
#include "printf.h"
struct AllConfig_t allConfigs;
extern int bg0, bg0b, bg1b;
static int display_options_list(bool bFullDisplay);
#define CONFIG_INSTRUCTION_STR " B=EXIT START=SAVE "
#define WAITVBL swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank(); swiWaitForVBlank();
extern void dsPrintValue(int x, int y, unsigned int isSelect, char *pchStr);
extern void dsShowScreenMain(bool);
char strBuf[35];
// ---------------------------------------------------------------------------
// Write out the A7800DS.DAT configuration file to capture the settings for
// each game. We can store more than 350 game settings!
// ---------------------------------------------------------------------------
void SaveConfig(bool bShow)
{
FILE *fp;
int slot = 0;
if (bShow) dsPrintValue(0,23,0, (char*)" SAVING CONFIGURATION ");
// Set the global configuration version number...
allConfigs.config_ver = CONFIG_VER;
// Find the slot we should save into...
for (slot=0; slot<MAX_CONFIGS; slot++)
{
if (strncmp(allConfigs.cart[slot].half_digest, myCartInfo.half_digest, 16) == 0) // Got a match?!
{
break;
}
if (strcmp(allConfigs.cart[slot].half_digest, "xxxxxxxxxxxxxxxx") == 0) // Didn't find it... use a blank slot...
{
break;
}
}
allConfigs.cart[slot] = myCartInfo;
// -------------------------------------------------------------------------------------
// Compute the CRC32 of everything and we can check this as integrity in the future...
// -------------------------------------------------------------------------------------
u8 *ptr=(u8*)&allConfigs;
allConfigs.crc32 = 0x00000000;
for (u32 i=0; i < sizeof(allConfigs) - 4; i++)
{
allConfigs.crc32 += *ptr++;
}
DIR* dir = opendir("/data");
if (dir)
{
closedir(dir); // Directory exists.
}
else
{
mkdir("/data", 0777); // Doesn't exist - make it...
}
fp = fopen("/data/A7800DS.DAT", "wb+");
if (fp != NULL)
{
fwrite(&allConfigs, sizeof(allConfigs), 1, fp);
fclose(fp);
} else dsPrintValue(2,20,0, (char*)" ERROR SAVING CONFIG FILE ");
if (bShow)
{
WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;
dsPrintValue(0,23, 0, (char *)CONFIG_INSTRUCTION_STR);
}
}
// -------------------------------------------------------------------------------------------------
// After settings hae changed, we call this to apply the new options to the game being played.
// This is also called when loading a game and after the configuration if read from StelaDS.DAT
// -------------------------------------------------------------------------------------------------
static void ApplyOptions(void)
{
extern u8 bRefreshXY, frameSkipMask;
extern unsigned char keyboard_data[];
bRefreshXY = true;
keyboard_data[15] = myCartInfo.diff1;
keyboard_data[16] = myCartInfo.diff2;
frameSkipMask = 0xFF; // Assume frameskip disabled until proven otherwise directly below
if (myCartInfo.frameSkip == FRAMESKIP_MEDIUM) frameSkipMask = 0x03;
if (myCartInfo.frameSkip == FRAMESKIP_AGGRESSIVE) frameSkipMask = 0x01;
region_Reset();
}
static void SetDefaultGameConfig(void)
{
// Init the entire database
for (int slot=0; slot<MAX_CONFIGS; slot++)
{
strcpy(allConfigs.cart[slot].half_digest, "xxxxxxxxxxxxxxxx");
// TBD - do more?
}
}
// -------------------------------------------------------------------------
// Find the A7800DS.DAT file and load it... if it doesn't exist, then
// default values will be used for the entire configuration database...
// -------------------------------------------------------------------------
void LoadConfig(void)
{
bool bInitDatabase = true;
FILE *fp;
fp = fopen("/data/A7800DS.DAT", "rb");
if (fp != NULL)
{
fread(&allConfigs, sizeof(allConfigs), 1, fp);
fclose(fp);
if (allConfigs.config_ver == CONFIG_VER)
{
bInitDatabase = false;
}
}
if (bInitDatabase)
{
dsPrintValue(0,1,0, (char*)"PLEASE WAIT...");
memset(&allConfigs, 0x00, sizeof(allConfigs));
allConfigs.config_ver = CONFIG_VER;
SetDefaultGameConfig();
SaveConfig(FALSE);
dsPrintValue(0,1,0, (char*)" ");
}
ApplyOptions();
}
// ------------------------------------------------------------------------------
// Options are handled here... we have a number of things the user can tweak
// and these options are applied immediately. The user can also save off
// their option choices for the currently running game into the A7800DS.DAT
// configuration database. When games are loaded back up, A7800DS.DAT is read
// to see if we have a match and the user settings can be restored for the game.
// ------------------------------------------------------------------------------
struct options_t
{
const char *label;
u8 isNumeric; // 0=String List, 1=Positive 8-bit, 2=Negative 8-bit
const char *option[15];
u8 *option_val;
u8 option_max;
};
const struct options_t Game_Option_Table[] =
{
{"CART TYPE", 0, {"NORMAL/FLAT", "SUPERCART", "SUPER LARGE", "SUPER RAM", "SUPER ROM", "SUPER RAM X2", "ABSOLUTE", "ACTIVISION", "FRACTALUS", "FLAT WITH RAM", "BANKSETS", "BANKSETS RAM", "BANKSETS HALT"},&myCartInfo.cardtype, 13},
{"HIGHSCORE", 0, {"DISABLED", "ENABLED"}, &myCartInfo.hsc, 2},
{"FRAMESKIP", 0, {"DISABLED", "MEDIUM 3/4", "HIGH 1/2"}, &myCartInfo.frameSkip, 3},
{"POKEY", 0, {"NONE", "AT 4000", "AT 450", "AT 800"}, &myCartInfo.pokeyType, 4},
{"LEFT DIFF", 0, {"A", "B"}, &myCartInfo.diff1, 2},
{"RIGHT DIFF", 0, {"A", "B"}, &myCartInfo.diff2, 2},
{"PALETTE", 0, {"CRT V2 COOL", "CRT V2 WARM", "CRT V2 HOT"}, &myCartInfo.palette, 3},
{"LEFT JOY", 0, {"NONE", "JOYSTICK", "LIGHTGUN", "PADDLES", "TWIN STICKS", "SOTA", "SNES2ATARI"}, &myCartInfo.cardctrl1, 7},
{"RIGHT JOY", 0, {"NONE", "JOYSTICK", "LIGHTGUN", "PADDLES", "TWIN STICKS", "SOTA", "SNES2ATARI"}, &myCartInfo.cardctrl2, 7},
{"X BUTTON", 0, {"DEFAULT", "PAN UP", "PAN DOWN", "JOY UP", "JOY DOWN", "JOY LEFT", "JOY RIGHT", "JOY B1", "JOY B2", "CONSOLE PAUSE"}, &myCartInfo.xButton, 10},
{"Y BUTTON", 0, {"DEFAULT", "PAN UP", "PAN DOWN", "JOY UP", "JOY DOWN", "JOY LEFT", "JOY RIGHT", "JOY B1", "JOY B2", "CONSOLE PAUSE"}, &myCartInfo.yButton, 10},
{"X OFFSET", 2, {"-50", "+50"}, (u8*)&myCartInfo.xOffset, 2},
{"Y OFFSET", 2, {"-50", "+50"}, (u8*)&myCartInfo.yOffset, 2},
{"X SCALE", 2, {"+200", "+320"}, (u8*)&myCartInfo.xScale, 2},
{"Y SCALE", 2, {"+180", "+234"}, (u8*)&myCartInfo.yScale, 2},
{"X JIGGLE", 1, {"+1", "+256"}, (u8*)&myCartInfo.xJiggle, 2},
{"Y JIGGLE", 1, {"+1", "+256"}, (u8*)&myCartInfo.yJiggle, 2},
{NULL, 0, {"", ""}, NULL, 1},
};
void display_line(u8 idx, u8 highlight)
{
if (Game_Option_Table[idx].isNumeric == 1) // Unsigned 8 bit
{
sprintf(strBuf, " %-11s : %-15d", Game_Option_Table[idx].label, *(Game_Option_Table[idx].option_val));
}
else if (Game_Option_Table[idx].isNumeric == 2) // Signed 16 bit
{
sprintf(strBuf, " %-11s : %-15d", Game_Option_Table[idx].label, *((s16*)Game_Option_Table[idx].option_val));
}
else // Array of strings
{
sprintf(strBuf, " %-11s : %-15s", Game_Option_Table[idx].label, Game_Option_Table[idx].option[*(Game_Option_Table[idx].option_val)]);
}
dsPrintValue(1,5+idx, highlight, strBuf);
}
// ------------------------------------------------------------------
// Display the current list of options...
// ------------------------------------------------------------------
static int display_options_list(bool bFullDisplay)
{
int len=0;
if (bFullDisplay)
{
while (true)
{
display_line(len, (len==0 ? 1:0));
len++;
if (Game_Option_Table[len].label == NULL) break;
}
// Blank out rest of the screen... option menus are of different lengths...
for (int i=len; i<20; i++)
{
dsPrintValue(1,6+i, 0, (char *)" ");
}
}
dsPrintValue(0,23, 0, (char *)CONFIG_INSTRUCTION_STR);
return len;
}
// -----------------------------------------------------------------------------
// Allows the user to move the cursor up and down through the various table
// enties above to select options for the game they wish to play.
// -----------------------------------------------------------------------------
void ShowConfig(void)
{
int optionHighlighted;
int idx;
bool bDone=false;
int keys_pressed;
int last_keys_pressed = 999;
// Show the Options background...
decompress(bgFileSelTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgFileSelMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
dmaCopy((void *) bgFileSelPal,(u16*) BG_PALETTE_SUB,256*2);
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
swiWaitForVBlank();
idx=display_options_list(true);
optionHighlighted = 0;
while (!bDone)
{
keys_pressed = keysCurrent();
if (keys_pressed != last_keys_pressed)
{
last_keys_pressed = keys_pressed;
if (keysCurrent() & KEY_UP) // Previous option
{
display_line(optionHighlighted, 0);
if (optionHighlighted > 0) optionHighlighted--; else optionHighlighted=(idx-1);
display_line(optionHighlighted, 1);
}
if (keysCurrent() & KEY_DOWN) // Next option
{
display_line(optionHighlighted, 0);
if (optionHighlighted < (idx-1)) optionHighlighted++; else optionHighlighted=0;
display_line(optionHighlighted, 1);
}
if (keysCurrent() & KEY_RIGHT) // Toggle option clockwise
{
if (Game_Option_Table[optionHighlighted].isNumeric == 1)
{
if (*(Game_Option_Table[optionHighlighted].option_val) < atoi(Game_Option_Table[optionHighlighted].option[1]))
{
*(Game_Option_Table[optionHighlighted].option_val) += 1;
}
}
else if (Game_Option_Table[optionHighlighted].isNumeric == 2)
{
if (*((s16*)Game_Option_Table[optionHighlighted].option_val) < atoi(Game_Option_Table[optionHighlighted].option[1]))
{
*((s16*)Game_Option_Table[optionHighlighted].option_val) += 1;
}
}
else
{
*(Game_Option_Table[optionHighlighted].option_val) = (*(Game_Option_Table[optionHighlighted].option_val) + 1) % Game_Option_Table[optionHighlighted].option_max;
}
display_line(optionHighlighted, 1);
ApplyOptions();
}
if (keysCurrent() & KEY_LEFT) // Toggle option counterclockwise
{
if (Game_Option_Table[optionHighlighted].isNumeric == 1)
{
if (*(Game_Option_Table[optionHighlighted].option_val) > atoi(Game_Option_Table[optionHighlighted].option[0]))
{
*(Game_Option_Table[optionHighlighted].option_val) -= 1;
}
}
else if (Game_Option_Table[optionHighlighted].isNumeric == 2)
{
if (*((s16*)Game_Option_Table[optionHighlighted].option_val) > atoi(Game_Option_Table[optionHighlighted].option[0]))
{
*((s16*)Game_Option_Table[optionHighlighted].option_val) -= 1;
}
}
else
{
if ((*(Game_Option_Table[optionHighlighted].option_val)) == 0)
*(Game_Option_Table[optionHighlighted].option_val) = Game_Option_Table[optionHighlighted].option_max -1;
else
*(Game_Option_Table[optionHighlighted].option_val) = (*(Game_Option_Table[optionHighlighted].option_val) - 1) % Game_Option_Table[optionHighlighted].option_max;
}
display_line(optionHighlighted, 1);
ApplyOptions();
}
if (keysCurrent() & KEY_START) // Save Options
{
SaveConfig(TRUE);
}
if (keysCurrent() & KEY_SELECT) // Restore Defaults
{
//extern void CartSetDefaultFromInternalDatabase(void);
//CartSetDefaultFromInternalDatabase();
display_options_list(true);
optionHighlighted = 0;
}
if ((keysCurrent() & KEY_B) || (keysCurrent() & KEY_A)) // Exit options
{
break;
}
}
swiWaitForVBlank();
}
// Restore original bottom graphic
dsShowScreenMain(false);
// Give a third of a second time delay...
for (int i=0; i<20; i++)
{
swiWaitForVBlank();
}
return;
}
// End of Line

View file

@ -1,69 +0,0 @@
// =====================================================================================
// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, it's source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and wavemotion-dave (Phoenix-Edition),
// Alekmaul (original port) and Greg Stanton (ProSystem Emulator) are thanked profusely.
//
// A7800DS emulator is offered as-is, without any warranty.
//
// The original GPL license:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// =====================================================================================
#ifndef __CONFIG_H
#define __CONFIG_H
#include <nds.h>
#include "Database.h"
#include "Cartridge.h"
// ---------------------------
// Config handling...
// ---------------------------
#define CONFIG_VER 0x000B
#define MAX_CONFIGS 640
struct AllConfig_t
{
u16 config_ver;
u8 global_buttonAB;
u8 global_showBios;
u8 global_spare1;
u8 global_spare2;
u8 global_spare3;
u8 global_spare4;
u8 global_spare5;
u8 global_spare6;
u8 global_spare7;
u8 global_spare10;
u8 global_spare11;
u8 global_spare12;
u8 global_spare13;
u8 global_spare14;
u8 global_unused[512];
Database_Entry cart[MAX_CONFIGS];
u32 crc32;
};
extern struct AllConfig_t allConfigs;
void LoadConfig(void);
void ShowConfig(void);
void SaveConfig(bool bShow);
#endif

172
arm9/source/emu/Archive.c Normal file
View file

@ -0,0 +1,172 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Archive.cpp
// ----------------------------------------------------------------------------
#include "Archive.h"
#define ARCHIVE_SOURCE "Archive.cpp"
#define _MAX_PATH 128
// ----------------------------------------------------------------------------
// GetUncompressedFileSize
// ----------------------------------------------------------------------------
uint archive_GetUncompressedFileSize(char* filename) {
#if 0
if(strlen(filename) == 0) {
logger_LogError("Zip filename is invalid.", ARCHIVE_SOURCE);
return 0;
}
unzFile file = unzOpen(filename);
if(file == NULL) {
logger_LogInfo("Filename " + filename + " is not a valid zip file.", ARCHIVE_SOURCE);
return 0;
}
int result = unzGoToFirstFile(file);
if(result != UNZ_OK) {
logger_LogInfo("Failed to find the first file within the zip file.", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
unzClose(file);
return 0;
}
unz_file_info_s zipInfo = {0};
char buffer[_MAX_PATH] = {0};
result = unzGetCurrentFileInfo(file, &zipInfo, buffer, _MAX_PATH, NULL, 0, NULL, 0);
if(result != UNZ_OK) {
logger_LogInfo("Failed to retrieve the current zipped file info.", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
unzClose(file);
return 0;
}
uint size = zipInfo.uncompressed_size;
unzClose(file);
return size;
#endif
return 0;
}
// ----------------------------------------------------------------------------
// Uncompress
// ----------------------------------------------------------------------------
bool archive_Uncompress(char* filename, byte* data, uint size) {
#if 0
if(strlen(filename) == 0) {
logger_LogError("Zip filename is invalid.", ARCHIVE_SOURCE);
return false;
}
if(data == NULL) {
logger_LogError("Data parameter is invalid.", ARCHIVE_SOURCE);
return false;
}
unzFile file = unzOpen(filename);
if(file == NULL) {
logger_LogInfo("Filename " + filename + " is not a valid zip file.", ARCHIVE_SOURCE);
return false;
}
int result = unzGoToFirstFile(file);
if(result != UNZ_OK) {
logger_LogInfo("Failed to find the first file within the zip file " + filename + ".", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
unzClose(file);
return false;
}
result = unzOpenCurrentFile(file);
if(result != UNZ_OK) {
logger_LogInfo("Failed to open the first file within the zip file " + filename + ".", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
unzClose(file);
return false;
}
result = unzReadCurrentFile(file, data, size);
if(result != size) {
logger_LogInfo("Failed to read first file data within the zip file " + filename + ".", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
unzCloseCurrentFile(file);
unzClose(file);
return false;
}
unzCloseCurrentFile(file);
unzClose(file);
return true;
#endif
return true;
}
// ----------------------------------------------------------------------------
// Compress
// ----------------------------------------------------------------------------
bool archive_Compress(char* zipFilename, char* filename, const byte* data, uint size) {
#if 0
if(strlen(zipFilename) == 0) {
logger_LogError("Zip filename is invalid.", ARCHIVE_SOURCE);
return false;
}
if(strlen(filename) == 0) {
logger_LogError("Filename is invalid.", ARCHIVE_SOURCE);
return false;
}
if(data == NULL) {
logger_LogError("Data parameter is invalid.", ARCHIVE_SOURCE);
return false;
}
zipFile file = zipOpen(zipFilename, APPEND_STATUS_CREATE);
if(file == NULL) {
logger_LogInfo("Failed to create the zip file " + zipFilename + ".", ARCHIVE_SOURCE);
return false;
}
zip_fileinfo fileInfo = {0};
fileInfo.dosDate = 1;
int result = zipOpenNewFileInZip(file, filename, &fileInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_BEST_COMPRESSION);
if(result != ZIP_OK) {
logger_LogInfo("Failed to open a new file within the zip file " + filename + ".", ARCHIVE_SOURCE);
logger_LogInfo("Result: " + result, ARCHIVE_SOURCE);
zipClose(file, "Failed to compress.");
return false;
}
result = zipWriteInFileInZip(file, data, size);
if(result != ZIP_OK) {
logger_LogInfo("Failed to write data to the zip file " + filename + ".", ARCHIVE_SOURCE);
zipCloseFileInZip(file);
zipClose(file, "Failed to compress.");
return false;
}
zipCloseFileInZip(file);
zipClose(file, "Comment");
return true;
#endif
return true;
}

40
arm9/source/emu/Archive.h Normal file
View file

@ -0,0 +1,40 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Archive.h
// ----------------------------------------------------------------------------
#ifndef ARCHIVE_H
#define ARCHIVE_H
#include <string.h>
#include "Logger.h"
#include "Cartridge.h"
//#include "zip.h"
//#include "unzip.h"
#include "shared.h"
extern uint archive_GetUncompressedFileSize(char* filename);
extern bool archive_Uncompress(char* filename, byte* data, uint size);
extern bool archive_Compress(char* zipFilename, char* filename, const byte* data, uint size);
#endif

126
arm9/source/emu/Bios.c Normal file
View file

@ -0,0 +1,126 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Bios.cpp
// ----------------------------------------------------------------------------
#include "Bios.h"
#define BIOS_SOURCE "Bios.cpp"
bool bios_enabled = false;
char bios_filename[128];
static byte* bios_data = NULL;
static word bios_size = 0;
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
bool bios_Load(char* filename) {
if(strlen(filename) == 0) {
#if 0
logger_LogError("Bios filename is invalid.", BIOS_SOURCE);
#endif
return false;
}
bios_Release( );
#if 0
logger_LogInfo("Opening bios file " + filename + ".");
#endif
bios_size = archive_GetUncompressedFileSize(filename);
if(bios_size == 0) {
FILE* file = fopen(filename, "rb");
if(file == NULL) {
#if 0
logger_LogError("Failed to open the bios file " + filename + " for reading.", BIOS_SOURCE);
#endif
return false;
}
fseek(file, 0, SEEK_END);
#if 0
if(fseek(file, 0, SEEK_END)) {
fclose(file);
logger_LogError("Failed to find the end of the bios file.", BIOS_SOURCE);
return false;
}
#endif
bios_size = ftell(file);
fseek(file, 0, SEEK_SET);
#if 0
if(fseek(file, 0, SEEK_SET)) {
fclose(file);
logger_LogError("Failed to find the size of the bios file.", BIOS_SOURCE);
return false;
}
#endif
bios_data = (byte *) malloc(bios_size);
fread(bios_data, 1, bios_size, file);
#if 0
if(fread(bios_data, 1, bios_size, file) != bios_size && ferror(file)) {
fclose(file);
logger_LogError("Failed to read the bios data.", BIOS_SOURCE);
bios_Release( );
return false;
}
#endif
fclose(file);
}
else {
bios_data = (byte *) malloc(bios_size);
archive_Uncompress(filename, bios_data, bios_size);
}
strcpy(bios_filename,filename);
return true;
}
// ----------------------------------------------------------------------------
// IsLoaded
// ----------------------------------------------------------------------------
bool bios_IsLoaded( ) {
return (bios_data != NULL)? true: false;
}
// ----------------------------------------------------------------------------
// Release
// ----------------------------------------------------------------------------
void bios_Release( ) {
if(bios_data) {
free(bios_data);
bios_size = 0;
bios_data = NULL;
}
}
// ----------------------------------------------------------------------------
// Store
// ----------------------------------------------------------------------------
void bios_Store( ) {
if(bios_data != NULL && bios_enabled) {
memory_WriteROM(65536 - bios_size, bios_size, bios_data);
}
}

View file

@ -20,23 +20,23 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// HighScore.h
// Bios.h
// ----------------------------------------------------------------------------
#ifndef HIGHSCORE_H
#define HIGHSCORE_H
#ifndef BIOS_H
#define BIOS_H
#include <stdio.h>
#include <string.h>
#include "Equates.h"
#include "Memory.h"
#include "Hash.h"
#include "Pokey.h"
#include "Archive.h"
#include "Logger.h"
#include "shared.h"
extern bool cartridge_LoadHighScoreCart(void);
extern bool cartridge_SaveHighScoreSram(void);
extern byte high_score_cart_loaded;
extern bool bios_Load(char* filename);
extern bool bios_IsLoaded( );
extern void bios_Store( );
extern void bios_Release( );
extern char bios_filename[128];
extern bool bios_enabled;
#endif

File diff suppressed because it is too large Load diff

View file

@ -24,98 +24,57 @@
// ----------------------------------------------------------------------------
#ifndef CARTRIDGE_H
#define CARTRIDGE_H
#define CARTRIDGE_TYPE_NORMAL 0
#define CARTRIDGE_TYPE_SUPERCART 1
#define CARTRIDGE_TYPE_SUPERCART_LARGE 2
#define CARTRIDGE_TYPE_SUPERCART_RAM 3
#define CARTRIDGE_TYPE_SUPERCART_ROM 4
#define CARTRIDGE_TYPE_ABSOLUTE 5
#define CARTRIDGE_TYPE_ACTIVISION 6
#define CARTRIDGE_CONTROLLER_NONE 0
#define CARTRIDGE_CONTROLLER_JOYSTICK 1
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
#define CARTRIDGE_WSYNC_MASK 2
#define CARTRIDGE_CYCLE_STEALING_MASK 1
#include <stdio.h>
#include <string.h>
#include "Equates.h"
#include "Memory.h"
#include "Hash.h"
#include "Logger.h"
#include "Pokey.h"
#include "Archive.h"
#include "shared.h"
#define MAX_CART_SIZE (1024 * 1024) // 1MB Cart is HUGE!
extern u8 use_composite_filtering;
extern u8 bios_show_counter;
extern u8 bios_available;
#define CARTRIDGE_CONTROLLER_NONE 0
#define CARTRIDGE_CONTROLLER_JOYSTICK 1
#define CARTRIDGE_CONTROLLER_LIGHTGUN 2
#define CARTRIDGE_CONTROLLER_PADDLES 3
#define CARTRIDGE_CONTROLLER_TWIN_STICKS 4
#define CARTRIDGE_CONTROLLER_SOTA 5
#define CARTRIDGE_CONTROLLER_SNES2ATARI 6
#define JOY CARTRIDGE_CONTROLLER_JOYSTICK
#define LGN CARTRIDGE_CONTROLLER_LIGHTGUN
#define PAD CARTRIDGE_CONTROLLER_PADDLES
#define TWIN CARTRIDGE_CONTROLLER_TWIN_STICKS
#define SOTA CARTRIDGE_CONTROLLER_SOTA
#define SNES CARTRIDGE_CONTROLLER_SNES2ATARI
#define CARTRIDGE_CYCLE_STEALING_MASK 0x01
#define CARTRIDGE_WSYNC_MASK 0x02
#define POKEY_NONE 0
#define POKEY_AT_4000 1
#define POKEY_AT_450 2
#define POKEY_AT_800 3
#define FRAMESKIP_DISABLE 0
#define FRAMESKIP_MEDIUM 1
#define FRAMESKIP_AGGRESSIVE 2
#define HSC_YES true
#define HSC_NO false
#define NTSC 0
#define PAL 1
#define STEAL_CYCLE true
#define NO_STEALING false
#define USES_WSYNC true
#define SKIP_WSYNC false
#define CARTRIDGE_TYPE_NORMAL 0
#define CARTRIDGE_TYPE_SUPERCART 1
#define CARTRIDGE_TYPE_SUPERCART_LARGE 2
#define CARTRIDGE_TYPE_SUPERCART_RAM 3
#define CARTRIDGE_TYPE_SUPERCART_ROM 4
#define CARTRIDGE_TYPE_SUPERCART_RAMX2 5
#define CARTRIDGE_TYPE_ABSOLUTE 6
#define CARTRIDGE_TYPE_ACTIVISION 7
#define CARTRIDGE_TYPE_FRACTALUS 8
#define CARTRIDGE_TYPE_FLAT_WITH_RAM 9
#define CARTRIDGE_TYPE_BANKSETS 10
#define CARTRIDGE_TYPE_BANKSETS_RAM 11
#define CARTRIDGE_TYPE_BANKSETS_HALTRAM 12
#define CT_NORMAL CARTRIDGE_TYPE_NORMAL
#define CT_SUPCAR CARTRIDGE_TYPE_SUPERCART
#define CT_SUPLRG CARTRIDGE_TYPE_SUPERCART_LARGE
#define CT_SUPRAM CARTRIDGE_TYPE_SUPERCART_RAM
#define CT_SUPRAMX2 CARTRIDGE_TYPE_SUPERCART_RAMX2
#define CT_SUPROM CARTRIDGE_TYPE_SUPERCART_ROM
#define CT_ABSOLU CARTRIDGE_TYPE_ABSOLUTE
#define CT_ACTVIS CARTRIDGE_TYPE_ACTIVISION
#define CT_FRACTALUS CARTRIDGE_TYPE_FRACTALUS
#define CT_FLATWRAM CARTRIDGE_TYPE_FLAT_WITH_RAM
#define CT_BANKSETS CARTRIDGE_TYPE_BANKSETS
#define CT_BANKSRAM CARTRIDGE_TYPE_BANKSETS_RAM
#define CT_BANKSHALT CARTRIDGE_TYPE_BANKSETS_HALTRAM
extern bool cartridge_Load(char* filename);
extern bool cartridge_Load_buffer(char* rom_buffer, int rom_size);
extern void cartridge_Store( );
extern void cartridge_StoreBank(byte bank);
extern void cartridge_Write(word address, byte data);
extern bool cartridge_IsLoaded( );
extern void cartridge_Release( );
extern void bios_check_and_load(void);
extern void bios_Store(void);
extern char cartridge_title[256];
extern byte cartridge_digest[256];
extern char cartridge_filename[256];
extern bool cartridge_LoadHighScoreCart();
extern bool cartridge_SaveHighScoreSram();
extern char cartridge_title[128];
extern char cartridge_description[128];
extern char cartridge_year[128];
extern char cartridge_maker[128];
extern byte cartridge_digest[128];
extern char cartridge_filename[128];
extern byte cartridge_type;
extern byte cartridge_region;
extern bool cartridge_pokey;
extern bool cartridge_pokey450;
extern bool cartridge_hsc_enabled;
extern byte cartridge_controller[2];
extern byte cartridge_bank;
extern uint cartridge_flags;
extern int cartridge_yOffset;
extern int cartridge_xOffset;
extern bool cartridge_wsync;
extern bool cartridge_cycle_stealing;
#endif

View file

@ -22,471 +22,206 @@
// ----------------------------------------------------------------------------
// Database.cpp
// ----------------------------------------------------------------------------
#include <ctype.h>
#include "Database.h"
#include "ProSystem.h"
#include "../config.h"
Database_Entry myCartInfo __attribute__((section(".dtcm")));
extern uint cartridge_size;
#define DATABASE_SOURCE "Database.cpp"
// To get the md5sum of an .a78 file with header in Linux: dd bs=1 skip=128 if=somefile.a78 | md5sum
bool database_enabled = true;
typedef struct {
char digest[33];
uint cardtype;
bool pokey;
uint cardctrl1;
uint cardctrl2;
uint cardregion;
uint cardflags;
bool hsc;
int yOffset;
} Database_Entry;
Database_Entry game_list[] = {
// The original NTSC Commercial Games
{"0be996d25144966d", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Ace Of Aces
{"877dcc97a775ed55", CT_SUPLRG, POKEY_NONE, LGN, LGN, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 7, 22, 264, 230, 0}, // title=Alien Brigade
{"07342c78619ba6ff", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 17, 256, 230, 0}, // title=Asteroids
{"8fc3a695eaea3984", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 240, 6, 12, 262, 220, 0}, // title=Ballblazer
{"42682415906c21c6", CT_SUPCAR, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 155, 0, 12, 256, 220, 0}, // title=Barnyard Blaster
{"f5f6b69c5eb4b55f", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 2, 15, 262, 226, 0}, // title=Basketbrawl
{"5a09946e57dbe304", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 24, 16, 300, 230, 0}, // title=Centipede
{"93e4387864b014c1", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 210, 0, 15, 256, 226, 0}, // title=Choplifter
{"2e8e28f6ad8b9b92", CT_SUPCAR, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 218, 0}, // title=Commando
{"db691469128d9a42", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 18, 256, 229, 0}, // title=Crack'ed
{"a94e4560b6ad053a", CT_SUPLRG, POKEY_NONE, LGN, LGN, DIFF_A, DIFF_A, NTSC, HSC_NO, 150, 9, 17, 272, 234, 0}, // title=Crossbow
{"179b76ff729d4849", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 0, 13, 256, 219, 0}, // title=Dark Chambers
{"95ac811c7d27af00", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 240, 6, 19, 261, 234, 0}, // title=Desert Falcon
{"731879ea82fc0ca2", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 12, 256, 220, 0}, // title=Dig Dug
{"5e332fbfc1e0fc74", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 14, 256, 220, 0}, // title=Donkey Kong Jr
{"743c47f500d095f2", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 14, 256, 220, 0}, // title=Donkey Kong Jr (alt)
{"19f1ee292a23636b", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 14, 256, 220, 0}, // title=Donkey Kong
{"543484c00ba23373", CT_ACTVIS, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 0, 12, 256, 220, 0}, // title=Double Dragon
{"2251a6a0f3aec84c", CT_ABSOLU, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 12, 256, 220, 0}, // title=F-18 Hornet
{"d25d5d19188e9f14", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 155, 0, 12, 256, 220, 0}, // title=Fatal Run
{"07dbbfe612a0a28e", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 12, 14, 282, 226, 0}, // title=Fight Night
{"cf76b00244105b8e", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 17, 255, 227, 0}, // title=Food Fight
{"fb8d803b328b2e44", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 12, 256, 229, 0}, // title=Galaga
{"fd9e78e201b6baaf", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 250, 0, 17, 256, 227, 0}, // title=Hat Trick
{"c3672482ca93f70e", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 180, 0, 17, 256, 230, 0}, // title=Ikari Warriors
{"baebc9246c087e89", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 12, 256, 220, 0}, // title=Impossible Mission
{"045fd12050b7f2b8", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 3, 12, 261, 234, 1}, // title=Jinks
{"f18b3b897a25ab38", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 17, 256, 234, 0}, // title=Joust
{"c3a5a8692a423d43", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 250, 0, 12, 256, 220, 0}, // title=Karateka
{"f57d0af323d4e173", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 22, 17, 276, 225, 0}, // title=Kung Fu Master
{"f2f5e5841e4dda89", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Mean 18 Ultimate Golf
{"bc1e905db1008493", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 13, 256, 226, 0}, // title=Midnight Mutants
{"431ca060201ee1f9", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 14, 256, 220, 0}, // title=Mario Bros.
{"37b5692e33a98115", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 0, 12, 256, 220, 0}, // title=Mat Mania Challenge
{"bedc30ec43587e0c", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 12, 256, 220, 0}, // title=Meltdown
{"3bc8f554cf86f813", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Motor Psycho
{"fc0ea52a9fac5572", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 170, 0, 17, 256, 224, 0}, // title=Ms. Pac-Man
{"220121f771fc4b98", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 10, 20, 270, 234, 0}, // title=Ninja Golf
{"74569571a208f8b0", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 245, 0, 12, 256, 224, 0}, // title=One On One
{"1a5207870dec6fae", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 12, 256, 220, 0}, // title=Pete Rose Baseball
{"33aea1e2b6634a1d", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 175, 0, 15, 256, 226, 0}, // title=Planet Smashers
{"584582bb09ee8122", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 210, 39, 15, 320, 230, 0}, // title=Pole Position II
{"ac03806cef2558fc", CT_ACTVIS, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 1, 16, 259, 234, 0}, // title=Rampage
{"383ed9bd1efb9b6c", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 1}, // title=Realsports Baseball
{"66ecaafe1b82ae68", CT_NORMAL, POKEY_NONE, TWIN,TWIN, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 5, 13, 270, 234, 0}, // title=Robotron
{"980c35ae9625773a", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 8, 18, 265, 234, 0}, // title=Scrapyard Dog
{"cbb0746192540a13", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 13, 256, 220, 0}, // title=Summer Games
{"cc18e3b37a507c42", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 0, 12, 256, 220, 0}, // title=Super Huey UH-IX
{"59b5793bece1c80f", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 220, 0}, // title=Super Skatebordin'
{"5c4f752371a523f1", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 150, 0, 12, 256, 220, 0}, // title=Tank Command
{"1af475ff6429a160", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 0, 12, 256, 220, 0}, // title=Title Match Pro Wrestling
{"c3903ab01a51222a", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 12, 256, 220, 0}, // title=Tomcat F-14 Simulator
{"208ef955fa90a298", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Touchdown Football
{"8d64763db3100aad", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 8, 320, 234, 1}, // title=Tower Toppler
{"427cb05d0a1abb06", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 150, 0, 3, 256, 197, 0}, // title=Water Ski
{"3799d72f78dda2ee", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 170, 0, 13, 256, 220, 0}, // title=Winter Games
{"90fa275f9f2a65b3", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 170, 0, 13, 256, 220, 0}, // title=Winter Games (alt)
{"05fb699db9eef564", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 15, 13, 284, 234, 0}, // title=Xenophobe
{"d7dc17379aa25e5a", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 0, 16, 256, 220, 0}, // title=Xevious
{"4332c24e4f3bc72e7fe1b77adf66c2b7",0,false,1,1,0,0, false, 22}, // title=3D Asteroids
{"0be996d25144966d5541c9eb4919b289",4,false,1,1,0,0, false, 22}, // title=Ace Of Aces
{"aadde920b3aaba03bc10b40bd0619c94",4,false,1,1,1,0, false, 22}, // title=Ace Of Aces
{"877dcc97a775ed55081864b2dbf5f1e2",2,false,3,3,0,0, false, 22}, // title=Alien Brigade
{"de3e9496cb7341f865f27e5a72c7f2f5",2,false,3,3,1,0, false, 22}, // title=Alien Brigade
{"07342c78619ba6ffcc61c10e907e3b50",0,false,1,1,0,0, true, 25}, // title=Asteroids
{"a65f79ad4a0bbdecd59d5f7eb3623fd7",0,false,1,1,0,0, true, 22}, // title=Asteroids Deluxe
{"3d38281ed8a8d8c7cd457a18c92c8604",0,false,1,1,0,0, true, 21}, // title=Astro Blaster
{"a51e5df28a0fe8c52e9d28fb5f8e44a6",0,false,1,1,0,0, true, 21}, // title=Astro Fighter
{"7cdfbe37634e7dcd4dc67db7edbcd3ba",0,false,1,1,0,0, false, 22}, // title=Baby Pac Man
{"8fc3a695eaea3984912d98ed4a543376",0,true ,1,1,0,0, false, 22}, // title=Ballblazer
{"b558814d54904ce0582e2f6a801d03af",0,true ,1,1,1,0, false, 22}, // title=Ballblazer
{"42682415906c21c6af80e4198403ffda",1,true ,2,1,0,0, false, 22}, // title=Barnyard Blaster
{"babe2bc2976688bafb8b23c192658126",1,true, 2,1,1,0, false, 22}, // title=Barnyard Blaster
{"f5f6b69c5eb4b55fc163158d1a6b423e",4,false,1,1,0,0, false, 22}, // title=Basketbrawl
{"fba002089fcfa176454ab507e0eb76cb",4,false,1,1,1,0, false, 22}, // title=Basketbrawl
{"78b1061d651ef806becac1dd3fda29a0",0,true ,1,1,0,0, true, 16}, // title=Beef Drop (Final Atariage)
{"4e325918a8b3bbcf2f9405040abcfc6d",0,false,1,1,0,0, true, 26}, // title=BonQ (found on Atairage Age site ... no graphical glitches)
{"9fa7743a016c9b7015ee1d386326f88e",0,false,1,1,0,0, true, 26}, // title=BonQ (final Atariage ... some graphical glitches)
{"5a09946e57dbe30408a8f253a28d07db",0,false,1,1,0,0, true, 22}, // title=Centipede
{"38c056a48472d9a9e16ebda5ed91dae7",0,false,1,1,1,0, false, 22}, // title=Centipede
{"93e4387864b014c155d7c17877990d1e",0,false,1,1,0,0, false, 22}, // title=Choplifter
{"59d4edb0230b5acc918b94f6bc94779f",0,false,1,1,1,0, false, 22}, // title=Choplifter
{"2e8e28f6ad8b9b9267d518d880c73ebb",1,true ,1,1,0,0, false, 22}, // title=Commando
{"55da6c6c3974d013f517e725aa60f48e",1,true ,1,1,1,0, false, 22}, // title=Commando
{"db691469128d9a4217ec7e315930b646",1,false,1,1,0,0, false, 22}, // title=Crack'ed
{"7cbe78fa06f47ba6516a67a4b003c9ee",1,false,1,1,1,0, false, 22}, // title=Crack'ed
{"a94e4560b6ad053a1c24e096f1262ebf",2,false,3,3,0,0, false, 22}, // title=Crossbow
{"63db371d67a98daec547b2abd5e7aa95",2,false,3,3,1,0, false, 22}, // title=Crossbow
{"179b76ff729d4849b8f66a502398acae",1,false,1,1,0,0, false, 21}, // title=Dark Chambers
{"a2b8e2f159642c4b91de82e9a2928494",1,false,1,1,1,0, false, 21}, // title=Dark Chambers
{"77f4eea33705389a38c846081c7355fc",3,false,1,1,1,0, false, 22}, // title=Defender
{"95ac811c7d27af0032ba090f28c107bd",0,false,1,1,0,0, false, 22}, // title=Desert Falcon
{"2d5d99b993a885b063f9f22ce5e6523d",0,false,1,1,1,0, false, 22}, // title=Desert Falcon
{"731879ea82fc0ca245e39e036fe293e6",0,false,1,1,0,0, true, 22}, // title=Dig Dug
{"408dca9fc40e2b5d805f403fa0509436",0,false,1,1,1,0, false, 22}, // title=Dig Dug
{"5e332fbfc1e0fc74223d2e73271ce650",0,false,1,1,0,0, false, 22}, // title=Donkey Kong Jr
{"4dc5f88243250461bd61053b13777060",0,false,1,1,1,0, false, 22}, // title=Donkey Kong Jr
{"19f1ee292a23636bd57d408b62de79c7",0,false,1,1,0,0, false, 22}, // title=Donkey Kong
{"8e96ef14ce9b5d84bcbc996b66d6d4c7",0,false,1,1,1,0, false, 22}, // title=Donkey Kong
{"543484c00ba233736bcaba2da20eeea9",6,false,1,1,0,3, false, 22}, // title=Double Dragon
{"de2ebafcf0e37aaa9d0e9525a7f4dd62",6,false,1,1,1,3, false, 22}, // title=Double Dragon
{"b3143adbbb7d7d189e918e5b29d55a72",0,true ,1,1,0,0, true, 22}, // title=Dungeon Stalker (homebrew)
{"2251a6a0f3aec84cc0aff66fc9fa91e8",5,false,1,1,0,0, false, 22}, // title=F-18 Hornet
{"e7709da8e49d3767301947a0a0b9d2e6",5,false,1,1,1,0, false, 22}, // title=F-18 Hornet
{"6287727ab36391a62f728bbdee88675c",0,false,1,1,0,0, true, 22}, // title=Failsafe (homebrew)
{"d25d5d19188e9f149977c49eb0367cd1",4,false,1,1,0,0, false, 22}, // title=Fatal Run
{"23505651ac2e47f3637152066c3aa62f",4,false,1,1,1,0, false, 22}, // title=Fatal Run
{"07dbbfe612a0a28e283c01545e59f25e",4,false,1,1,0,0, false, 22}, // title=Fight Night
{"e80f24e953563e6b61556737d67d3836",4,false,1,1,1,0, false, 22}, // title=Fight Night
{"cf76b00244105b8e03cdc37677ec1073",0,false,1,1,0,0, true, 22}, // title=Food Fight
{"de0d4f5a9bf1c1bddee3ed2f7ec51209",0,false,1,1,1,0, false, 22}, // title=Food Fight
{"e7d89669a7f92ec2cc99d9663a28671c",0,false,1,1,0,0, true, 18}, // title=Frenzy (with Berzerk) (homebrew)
{"6053233cb59c0b4ca633623fd76c4576",0,true, 1,1,0,0, true, 13}, // title=Froggie (homebrew)
{"fb8d803b328b2e442548f7799cfa9a4a",0,false,1,1,0,0, true, 22}, // title=Galaga
{"f5dc7dc8e38072d3d65bd90a660148ce",0,false,1,1,1,0, false, 22}, // title=Galaga
{"06204dadc975be5e5e37e7cc66f984cf",0,false,1,1,0,0, false, 22}, // title=Gato
{"fd9e78e201b6baafddfd3e1fbfe6ba31",0,false,1,1,0,0, false, 22}, // title=Hat Trick
{"0baec96787ce17f390e204de1a136e59",0,false,1,1,1,0, false, 22}, // title=Hat Trick
{"c3672482ca93f70eafd9134b936c3feb",4,false,1,1,0,0, false, 22}, // title=Ikari Warriors
{"8c2c2a1ea6e9a928a44c3151ba5c1ce3",4,false,1,1,1,0, false, 22}, // title=Ikari Warriors
{"baebc9246c087e893dfa489632157180",3,false,1,1,0,0, false, 22}, // title=Impossible Mission
{"1745feadabb24e7cefc375904c73fa4c",3,false,1,1,0,0, false, 22}, // title=Impossible Mission
{"80dead01ea2db5045f6f4443faa6fce8",3,false,1,1,1,0, false, 22}, // title=Impossible Mission
{"045fd12050b7f2b842d5970f2414e912",3,false,1,1,0,0, false, 22}, // title=Jinks
{"dfb86f4d06f05ad00cf418f0a59a24f7",3,false,1,1,1,0, false, 22}, // title=Jinks
{"f18b3b897a25ab3885b43b4bd141b396",0,false,1,1,0,0, true, 22}, // title=Joust
{"f2dae0264a4b4a73762b9d7177e989f6",0,false,1,1,1,0, false, 22}, // title=Joust
{"c3a5a8692a423d43d9d28dd5b7d109d9",0,false,1,1,0,0, false, 22}, // title=Karateka
{"5e0a1e832bbcea6facb832fde23a440a",1,false,1,1,1,0, false, 22}, // title=Karateka
{"17b3b764d33eae9b5260f01df7bb9d2f",4,false,1,1,0,0, false, 22}, // title=Klax
{"f57d0af323d4e173fb49ed447f0563d7",0,false,1,1,0,3, false, 22}, // title=Kung Fu Master
{"2931b75811ad03f3ac9330838f3d231b",0,false,1,1,1,3, false, 22}, // title=Kung Fu Master
{"431ca060201ee1f9eb49d44962874049",0,false,1,1,0,0, false, 22}, // title=Mario Bros.
{"d2e861306be78e44248bb71d7475d8a3",0,false,1,1,1,0, false, 22}, // title=Mario Bros.
{"37b5692e33a98115e574185fa8398c22",4,false,1,1,0,0, false, 22}, // title=Mat Mania Challenge
{"6819c37b96063b024898a19dbae2df54",4,false,1,1,1,0, false, 22}, // title=Mat Mania Challenge
{"f2f5e5841e4dda89a2faf8933dc33ea6",4,false,1,1,0,0, false, 22}, // title=Mean 18 Ultimate Golf
{"2e9dbad6c0fa381a6cd1bb9abf98a104",4,false,1,1,1,0, false, 22}, // title=Mean 18 Ultimate Golf
{"bedc30ec43587e0c98fc38c39c1ef9d0",4,false,2,2,0,0, false, 22}, // title=Meltdown
{"c80155d7eec9e3dcb79aa6b83c9ccd1e",4,false,2,2,1,0, false, 22}, // title=Meltdown
{"c3f6201d6a9388e860328c963a3301cc",0,false,1,1,0,0, true, 21}, // title=Meteor Shower
{"bc1e905db1008493a9632aa83ab4682b",4,false,1,1,0,0, false, 22}, // title=Midnight Mutants
{"6794ea31570eba0b88a0bf1ead3f3f1b",4,false,1,1,1,0, false, 22}, // title=Midnight Mutants
{"017066f522908081ec3ee624f5e4a8aa",2,false,1,1,0,3, false, 22}, // title=Missing in Action
{"3bc8f554cf86f8132a623cc2201a564b",4,false,1,1,0,0, false, 22}, // title=Motor Psycho
{"5330bfe428a6b601b7e76c2cfc4cd049",4,false,1,1,1,0, false, 22}, // title=Motor Psycho
{"fc0ea52a9fac557251b65ee680d951e5",0,false,1,1,0,0, true, 22}, // title=Ms. Pac-Man
{"56469e8c5ff8983c6cb8dadc64eb0363",0,false,1,1,1,0, false, 22}, // title=Ms. Pac-Man
{"220121f771fc4b98cef97dc040e8d378",4,false,1,1,0,0, false, 22}, // title=Ninja Golf
{"ea0c859aa54fe5eaf4c1f327fab06221",4,false,1,1,1,0, false, 22}, // title=Ninja Golf
{"74569571a208f8b0b1ccfb22d7c914e1",0,false,1,1,0,0, false, 12}, // title=One On One
{"8dba0425f0262e5704581d8757a1a6e3",0,false,1,1,1,0, false, 12}, // title=One On One
{"5013b69cb05b21a1194ce48517df7bfc",0,true, 1,1,0,0, true, 19}, // title=Pac-Man Collection (homebrew)
{"044657294450c869c45e7ef61f4870de",1,true, 1,1,0,0, true, 27}, // title=Pac-Man Collection 40th Anniversary Edition (homebrew)
{"1a5207870dec6fae9111cb747e20d8e3",0,false,1,1,0,0, false, 22}, // title=Pete Rose Baseball
{"386bded4a944bae455fedf56206dd1dd",0,false,1,1,1,0, false, 22}, // title=Pete Rose Baseball
{"ec206c8db4316eb1ebce9fc960da7d8f",4,false,1,1,0,0, false, 22}, // title=Pit Fighter
{"33aea1e2b6634a1dec8c7006d9afda22",4,false,1,1,0,0, false, 18}, // title=Planet Smashers
{"2837a8fd49b7fc7ccd70fd45b69c5099",4,false,1,1,1,0, false, 18}, // title=Planet Smashers
{"584582bb09ee8122e7fc09dc7d1ed813",0,false,1,1,0,0, false, 22}, // title=Pole Position II
{"865457e0e0f48253b08f77b9e18f93b2",0,false,1,1,1,0, false, 22}, // title=Pole Position II
{"1745feadabb24e7cefc375904c73fa4c",3,false,1,1,0,0, false, 22}, // title=Possible Mission
{"ac03806cef2558fc795a7d5d8dba7bc0",6,false,1,1,0,0, false, 22}, // title=Rampage
{"bfad016d6e77eaccec74c0340aded8b9",1,false,1,1,0,0, false, 22}, // title=Realsports Baseball
{"8f7eb10ad0bd75474abf0c6c36c08486",0,false,1,1,0,0, false, 22}, // title=Rescue On Fractalus
{"66ecaafe1b82ae68ffc96267aaf7a4d7",0,false,1,1,0,0, true, 22}, // title=Robotron
{"a3a85e507d6f718972b1464ce1aaf8a4",0,false,1,1,0,0, true, 13}, // title=Scramble (homebrew)
{"980c35ae9625773a450aa7ef51751c04",4,false,1,1,0,0, false, 22}, // title=Scrapyard Dog
{"53db322c201323fe2ca8f074c0a2bf86",4,false,1,1,1,0, false, 22}, // title=Scrapyard Dog
{"b697d9c2d1b9f6cb21041286d1bbfa7f",4,true ,2,2,0,0, false, 22}, // title=Sentinel
{"5469b4de0608f23a5c4f98f331c9e75f",4,true ,2,2,1,0, false, 22}, // title=Sentinel
{"771cb4609347657f63e6f0eb26036e35",0,false,1,1,0,0, true, 22}, // title=Space Duel (homebrew)
{"6adf79558a3d7f5beca1bb8d34337417",0,false,1,1,0,0, true, 99}, // title=Space Invaders (Homebrew) Special 99=340 pixel mode...
{"cbb0746192540a13b4c7775c7ce2021f",3,false,1,1,0,0, false, 22}, // title=Summer Games
{"81cee326b99d6831de10a566e338bd25",0,true, 1,1,0,0, true, 21}, // title=Super Circus Atariage (Pokey 4000)
{"cc18e3b37a507c4217eb6cb1de8c8538",0,false,1,1,0,0, false, 22}, // title=Super Huey UH-IX
{"162f9c953f0657689cc74ab20b40280f",0,false,1,1,1,0, false, 22}, // title=Super Huey UH-IX
{"59b5793bece1c80f77b55d60fb39cb94",0,false,1,1,0,0, false, 22}, // title=Super Skatebordin'
{"95d7c321dce8f57623a9c5b4947bb375",0,false,1,1,1,0, false, 22}, // title=Super Skatebordin'
{"44f862bca77d68b56b32534eda5c198d",1,false,1,1,0,0, false, 22}, // title=Tank Command
{"1af475ff6429a160752b592f0f92b287",0,false,1,1,0,0, false, 22}, // title=Title Match Pro Wrestling
{"3bb9c8d9adc912dd7f8471c97445cd8d",0,false,1,1,1,0, false, 22}, // title=Title Match Pro Wrestling
{"c3903ab01a51222a52197dbfe6538ecf",0,false,1,1,0,0, false, 22}, // title=Tomcat F-14 Simulator
{"682338364243b023ecc9d24f0abfc9a7",0,false,1,1,1,0, false, 22}, // title=Tomcat F-14 Simulator
{"208ef955fa90a29815eb097bce89bace",4,false,1,1,0,0, false, 22}, // title=Touchdown Football
{"d12e665347f354048b9d13092f7868c9",3,false,1,1,0,0, false, 22}, // title=Tower Toppler
{"32a37244a9c6cc928dcdf02b45365aa8",3,false,1,1,1,0, false, 22}, // title=Tower Toppler
{"acf63758ecf3f3dd03e9d654ae6b69b7",1,false,1,1,0,0, false, 22}, // title=Water Ski
{"3799d72f78dda2ee87b0ef8bf7b91186",3,false,1,1,0,0, false, 22}, // title=Winter Games
{"05fb699db9eef564e2fe45c568746dbc",4,false,1,1,0,0, false, 22}, // title=Xenophobe
{"70937c3184f0be33d06f7f4382ca54de",4,false,1,1,1,0, false, 22}, // title=Xenophobe
{"d7dc17379aa25e5ae3c14b9e780c6f6d",0,false,1,1,0,0, true, 22}, // title=Xevious
{"b1a9f196ce5f47ca8caf8fa7bc4ca46c",0,false,1,1,1,0, false, 22}, // title=Xevious
// Prototypes and Hacks
{"4332c24e4f3bc72e", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=3D Asteroids
{"1745feadabb24e7c", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Impossible Mission
{"20660b667df538ec", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 24, 16, 300, 230, 0}, // title=Centipede - Frameless Hack
{"8f7eb10ad0bd7547", CT_FRACTALUS, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 180, 0, 12, 256, 220, 0}, // title=Rescue On Fractalus
{"06204dadc975be5e", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Gato
{"17b3b764d33eae9b", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 0, 20, 256, 234, 0}, // title=Klax (fixed)
{"5fb805f2b69820a9", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 0, 20, 256, 234, 0}, // title=Klax
{"017066f522908081", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 145, 0, 12, 256, 220, 0}, // title=Missing in Action
{"ec206c8db4316eb1", CT_SUPROM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Pit Fighter
{"74f0283c566bdee8", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 180, 0, 17, 256, 234, 0}, // title=Plutos XM
{"86546808dc60961c", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 180, 0, 17, 256, 234, 0}, // title=Plutos (non-XM)
{"1745feadabb24e7c", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 12, 256, 220, 0}, // title=Possible Mission
{"b697d9c2d1b9f6cb", CT_SUPROM, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 5, 15, 258, 220, 0}, // title=Sentinel
// Bob (pacmanplus) Games
{"89b8b3df46733e0c", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 165, 0, 12, 256, 220, 0}, // title=Armor Attack II
{"eea04359df6770d6", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 165, 0, 12, 256, 220, 0}, // title=Armor Attack II (20230627)
{"a65f79ad4a0bbdec", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 0, 17, 256, 230, 0}, // title=Asteroids Deluxe (NTSC) (20071014)
{"3d38281ed8a8d8c7", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 245, 30, 9, 320, 210, 0}, // title=Astro Blaster
{"55ffe535897c368b", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 245, 30, 9, 320, 210, 0}, // title=Astro Blaster (20230627)
{"a51e5df28a0fe8c5", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 32, 9, 320, 213, 0}, // title=Astro Fighter
{"8feb090fb1aee5cc", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 32, 9, 320, 213, 0}, // title=Astro Fighter (v1.1)
{"7cdfbe37634e7dcd", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 250, 32, 12, 320, 222, 0}, // title=Baby Pac Man
{"2b31dfab41dce110", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 250, 32, 12, 320, 222, 0}, // title=Baby Pac Man (20230627)
{"34483432b92f565f", CT_SUPLRG, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 165, 3, 14, 256, 220, 0}, // title=Bentley Bear's Crystal Quest
{"299d31c8e181fdd0", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 5, 256, 203, 0}, // title=Crazy Brix
{"2d2fe4da9f1bae10", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 9, 256, 232, 0}, // title=Crazy Otto
{"100551363027dc5f", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 165, 0, 9, 256, 232, 0}, // title=Crazy Otto (20230627)
{"6287727ab36391a6", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 250, 0, 14, 257, 220, 0}, // title=FailSafe (NTSC) (20100227)
{"e7d89669a7f92ec2", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 255, 30, 6, 320, 206, 0}, // title=Frenzy (with Berzerk) (homebrew)
{"26031dea7251fb86", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 255, 30, 6, 320, 206, 0}, // title=Frenzy (with Berzerk) (20211025)
{"2f4ae1015a345652", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 14, 17, 283, 227, 0}, // title=Galaxian
{"686a4e4dde0eca5c", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 14, 17, 283, 227, 0}, // title=Galaxian (v1.1)
{"e54edc299e72d22d", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 4, 14, 268, 234, 0}, // title=Jr Pac-Man
{"bde3abe40d302d8c", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 4, 14, 268, 234, 0}, // title=Jr Pac-Man (20230627)
{"6b8600aabd11f834", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 3, 12, 256, 225, 0}, // title=KC Munchkin
{"aa0b9560d6610378", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 3, 12, 256, 225, 0}, // title=KC Munchkin (20230627)
{"927edf157f88b8f5", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 3, 12, 256, 225, 0}, // title=KC Munchkin (Alt Movement) (20170409)
{"c3f6201d6a9388e8", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 13, 256, 220, 0}, // title=Meteor Shower
{"a44241d782ee14b5", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 13, 256, 220, 0}, // title=Meteor Shower (v1.1)
{"9ff38ea62004201d", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 30, 20, 320, 234, 0}, // title=Moon Cresta
{"a56f26e6d21b2ae4", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 30, 20, 320, 234, 0}, // title=Moon Cresta (v1.1)
{"cf007563fe94cacf", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 215, 0, 9, 256, 217, 0}, // title=Ms. Pac-Man (Bob's Enhancements)
{"2a17dc5a61be342d", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 5, 16, 265, 230, 0}, // title=Ms Pac-Man 320
{"60982f430b762343", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 220, 6, 17, 264, 233, 0}, // title=Pac-Man 320
{"5013b69cb05b21a1", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 210, 10, 11, 281, 231, 0}, // title=Pac-Man Collection (homebrew)
{"6a432fd1e9d42a29", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 210, 10, 11, 281, 231, 0}, // title=Pac-Man Collection - Ultimate Edition (POKEY) (4000)
{"ce1cb2f5d2238449", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 210, 10, 11, 281, 231, 0}, // title=Pac-Man Collection - Ultimate Edition (POKEY) (4000)
{"200ef9c7b36afd3b", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_YES, 210, 10, 11, 281, 231, 0}, // title=Pac-Man Collection - Remastered (TIA)
{"f2512870a8abc82d", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 9, 10, 278, 221, 0}, // title=Pac-Man Collection 40th Anniversary Edition (homebrew) - Newest
{"a59d362e3a391ff1", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 220, 9, 10, 278, 221, 0}, // title=Pac-Man Collection 40th Anniversary Edition (homebrew) - Older
{"1330d23ebad9b5de", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 220, 9, 10, 278, 221, 0}, // title=Pac-Man Collection 40th Anniversary Edition (homebrew) - PMC_XM Newest
{"2b60de20a55056a1", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 11, 17, 279, 233, 0}, // title=Pac-Man Collection 40th - Short Mazes (2022) - Newest
{"c80edcd555cd3d81", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 11, 17, 279, 233, 0}, // title=Pac-Man Collection 40th - Short Mazes (2022)
{"39dc7f6f39f9b3e3", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 9, 10, 278, 221, 0}, // title=Pac-Man Collection - 40th Anniversary Edition (20230627)
{"2686f20449c339f7", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 11, 17, 279, 233, 0}, // title=Pac-Man Collection - 40th Anniversary Edition (Short Mazes) (20230627)
{"2b51ebf2f371d079", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 10, 18, 271, 234, 0}, // title=Pac-Man - Energy Drink Edition (20230707)
{"d0bf3b841ad4bbd3", CT_NORMAL, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 10, 12, 274, 233, 0}, // title=Pac-Man Plus 320
{"43525a0405184875", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 17, 256, 233, 0}, // title=Rip-Off
{"803743fe18600f29", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 17, 256, 233, 0}, // title=Rip-Off (20230627)
{"a3a85e507d6f7189", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 250, 30, 5, 320, 205, 0}, // title=Scramble (homebrew)
{"31b20a4710e69130", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 250, 30, 5, 320, 205, 0}, // title=Scramble (20230627)
{"771cb4609347657f", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 0, 12, 256, 220, 0}, // title=Space Duel (homebrew)
{"6adf79558a3d7f5b", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 165, 30, 8, 320, 210, 0}, // title=Space Invaders (Homebrew)
{"6a898d52ef050cdb", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 165, 30, 8, 320, 210, 0}, // title=Space Invaders (v1.1)
{"7ab539bb0e99e1e5", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 0, 5, 256, 225, 0}, // title=Super Pac-Man
{"88b9de0eba37ba51", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 205, 0, 5, 256, 225, 0}, // title=Super Pac-Man (20230627)
{"79df20ee86a989e6", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 9, 18, 282, 230, 0}, // title=UniWarS
{"0db69825c81171e6", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 9, 18, 282, 230, 0}, // title=UniWarS (v1.1)
{"f41f651417c23410", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 240, 26, 12, 320, 225, 0}, // title=Super Cobra
{"fd9353d42cca5f81", CT_SUPRAMX2,POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 190, 0, 6, 256, 203, 1}, // title=1942 (Standard Banking RAM)
{"e1b290ee690c0cd6", CT_SUPRAMX2,POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 190, 0, 6, 256, 203, 1}, // title=1942 (Standard Banking RAM)
{"0fec9c1f5973c7a1", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 190, 0, 6, 256, 203, 1}, // title=1942 (Dragonfly Banking RAM)
{"6f157f421c7ed5d9", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 22, 14, 299, 230, 0}, // title=2048 (RC1a) (20211113)
{"a837a34f540fd137", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 14, 16, 286, 234, 0}, // title=7iX (20220305)
{"ff056f2858f14fc4", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 3, 15, 261, 234, 0}, // title=A Roach In Space - Part II - Electric Bugaloo (20201119)
{"d99bff88cd3cce19", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 9, 256, 200, 0}, // title=Arkanoid 78b Demo (purposely set HSC to false - game HSC is buggy)
{"212ee2a6e66d8bb7", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 9, 256, 200, 0}, // title=Arkanoid 78b Demo (purposely set HSC to false - game HSC is buggy)
{"e1da4c3ea0d26ae0", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 9, 256, 200, 0}, // title=Arkanoid 78b Demo (purposely set HSC to false - game HSC is buggy)
{"0d05659a7d0eef02", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 1, 16, 268, 234, 0}, // title=ARTI Public Demo
{"4a8a22cff154f479", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 7, 256, 220, 0}, // title=Boom!
{"9fa7743a016c9b70", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 27, 256, 234, 0}, // title=BonQ (Final Atariage)
{"78b1061d651ef806", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 135, 0, 16, 256, 234, 0}, // title=Beef Drop (Final Atariage)
{"b11b1a2bae8a1d0c", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 3, 13, 264, 227, 0}, // title=Bernie and the Cubic Conundrum (Alpha 10)
{"a34cd425d0c087d0", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 6, 16, 264, 233, 0}, // title=Bernie and the Tower of Doom (RC1) (Demo)
{"000b5888d2489f7e", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 0, 12, 256, 223, 0}, // title=Cannon in D for Defense (demo 03)
{"825c03c049306c16", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 0, 16, 260, 234, 0}, // title=Cartesian Chaos (v11) (20221218)
{"a4b5d742860beb25", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 8, 19, 269, 233, 0}, // title=Chase (20201231)
{"0c2f248a1ae9bfd1", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 14, 256, 234, 0}, // title=Danger Zone (RC-4C) (NTSC Demo) (20201231)
{"fab7b59dd580dce0", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 2, 17, 260, 229, 0}, // title=Death Merchant (v1_30)
{"dd1cfc933d2bfacc", CT_SUPLRG, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 185, 0, 12, 256, 210, 0}, // title=Donkey Kong PK-XM (NTSC) (Demo) (v1.2)
{"c3107d3e3e17d67e", CT_SUPLRG, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 185, 0, 20, 256, 223, 0}, // title=Donkey Kong XM DEMO
{"312363c7691fa51e", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 180, 0, 17, 256, 216, 0}, // title=Donkey Kong Remix DEMO
{"77164df89ae49b4d", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 0, 16, 256, 234, 0}, // title=Dragon's Descent (20210731)
{"8c2798f929a43317", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 125, 6, 15, 256, 232, 0}, // title=Dragon's Havoc (Demo Dec 2022)
{"7b7825ca2c79148f", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 6, 15, 256, 232, 0}, // title=Dragon's Cache (20210207)
{"a9f29004412621f2", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 16, 256, 230, 0}, // title=Draker Quest II
{"fab1290f9a4c4f2b", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 120, 0, 17, 256, 230, 0}, // title=Draker Quest (Beta 4)
{"b3143adbbb7d7d18", CT_NORMAL, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 9, 256, 231, 0}, // title=Dungeon Stalker (20151022)
{"a44e8b7b7881beb0", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 135, 0, 16, 256, 234, 0}, // title=E.X.O. (RC Demo A)
{"6053233cb59c0b4c", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 210, 34, 4, 320, 216, 0}, // title=Froggie (NTSC) (Final Release)
{"9daaac9b25783a7e", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 16, 256, 224, 0}, // title=Frogus (20221020)
{"c2e131a091ceed2e", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 15, 256, 234, 0}, // title=Game of the Bear - Polar Opposites (RC1) (20230211)
{"e443f7fb5be3283d", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 13, 12, 280, 234, 0}, // title=GoSub
{"1e21bf1d9d7b3c0c", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 160, 0, 11, 256, 220, 0}, // title=Graze Suit Alpha (20170910)
{"1c9deabc48f07d1b", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 115, 0, 12, 256, 220, 0}, // title=Keystone Koppers (Demo Dec 22)
{"d41d8cd98f00b204", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 115, 0, 12, 256, 220, 0}, // title=Keystone Koppers (RC4 Demo)
{"1d47c3802135d864", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 233, 0}, // title=Knight Guy On Board - 30 Squares Of Fate (20210116)
{"0916973898e3b6b8", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 233, 0}, // title=Knight Guy On Board - 30 Squares Of Fate (Demo 3)
{"33dbb58f9ee73e9f", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 233, 0}, // title=Knight Guy In Low Res World - Castle Days (RC 01-1)
{"3ec728e116017be8", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 233, 0}, // title=Knight Guy - Quest For Something (20210423)
{"7abd9e0a6321e813", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_B, DIFF_B, NTSC, HSC_NO, 130, 0, 12, 256, 233, 0}, // title=Knight Guy - In Another Castle (RC1b)
{"271864e0978278a3", CT_SUPCAR, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 7, 256, 201, 0}, // title=Legend of Silverpeak (1.01)
{"7abd9e0a6321e813", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 135, 6, 16, 264, 234, 0}, // title=Lunar Patrol (v83) (20241231) (2354A1FF)
{"23ac803eabfb8c61", CT_NORMAL, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 12, 256, 234, 0}, // title=Lyra the Tenrec (20240104)
{"181a9978d9da7a7e", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 17, 320, 234, 0}, // title=Merlain
{"3f80432f156088bf", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 14, 256, 220, 0}, // title=Millie And Molly (Demo) (POKEY 450) (20230305)
{"1c860298a8966cc8", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 14, 256, 220, 0}, // title=Monster Maze (20220306)
{"d1b56eae7227c12d", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 0, 17, 256, 224, 0}, // title=Morf (20220314)
{"ac5c99ac01c96ad9", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 130, 0, 16, 256, 234, 0}, // title=Ninjish Guy - Perilous Island (20211107)
{"3d9c52142f9e53f5", CT_SUPLRG, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 17, 256, 234, 0}, // title=Oozy The Goo - Gaiden (20231001)
{"6ac5a7f8b6a3198e", CT_SUPLRG, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 125, 2, 17, 260, 234, 0}, // title=PentaGo (Demo) (20230422)
{"a662862f20362fc5", CT_BANKSHALT,POKEY_AT_800,SNES,JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 10, 256, 214, 0}, // title=Attack of the Petscii Robots (Demo) (POKEY 800)
{"0254afa887fcfc8c", CT_SUPRAM, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 16, 17, 289, 220, 0}, // title=Plumb Luck DX (RC2) (20230410)
{"61e6a16889b62216", CT_SUPLRG, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 17, 256, 220, 0}, // title=Popeye 2.40 Demo
{"fab49206f4b041fa", CT_SUPLRG, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 140, 0, 17, 256, 220, 0}, // title=Popeye 2.40 j7800 Demo
{"b6561537290e6e25", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 12, 256, 220, 0}, // title=Robbo (20160513)
{"fc525819ec2bdc4a", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 140, 0, 11, 256, 217, 0}, // title=Robots Rumble (20220217)
{"9bd70c06d3386f76", CT_SUPRAM, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 12, 256, 220, 0}, // title=Serpentine (20161029)
{"96f69b85e0b43bbe", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 120, 0, 12, 256, 233, 0}, // title=Sick Pickles (20171202)
{"40567f50c569a60c", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 16, 256, 230, 0}, // title=Slide Boy in Maze Land (RC1) (20210515)
{"91f4cb1f642ff1de", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 110, 0, 16, 256, 230, 0}, // title=Space Peril (NTSC) (v8) (20210907)
{"19844117863cd38d", CT_SUPLRG, POKEY_NONE, SOTA,SOTA, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 31, 17, 320, 230, 0}, // title=Spire of the Ancients (NTSC) (20201223)
{"81cee326b99d6831", CT_NORMAL, POKEY_AT_4000, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 0, 13, 256, 220, 0}, // title=Super Circus Atari Age (NTSC) (Joystick) (POKEY 4000)
{"02508e6df5e173b4", CT_NORMAL, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 200, 0, 13, 256, 220, 0}, // title=Super Circus Atari Age (NTSC) (Joystick) (POKEY 0450)
{"a60e4b608505d1fb", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 16, 256, 230, 0}, // title=Time Salvo
{"ff825fcbed9bf699", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 17, 256, 220, 0}, // title=Touchdown Challenge (v2_21) (20230225)
{"0d7e2674d802b412", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_NO, 120, 0, 13, 256, 233, 0}, // title=Tunnels of Hyperion
{"f5150c0fc1948832", CT_NORMAL, POKEY_AT_450, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 160, 0, 12, 256, 240, 0}, // title=7800 Utility Cart
{"846751861993b907", CT_NORMAL, POKEY_NONE, JOY, JOY, DIFF_A, DIFF_A, NTSC, HSC_YES, 130, 0, 16, 256, 231, 0}, // title=Wizards Dungeon (20211111)
{"",CT_NORMAL,0,0,0,0,0,0,0,0,0,0,0},
{"",0,false,0,0,0,0},
};
NameMap_t NameMap[] =
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
bool database_Load(byte *digest)
{
{"POPEYE", "POPEYE", "61e6a16889b62216"},
{"EXO", "EXO", "a44e8b7b7881beb0"},
{"KOPPERS", "KOPPERS", "d41d8cd98f00b204"},
{"TIME", "SALVO", "a60e4b608505d1fb"},
{"CHRISTMAS", "SALVO", "a60e4b608505d1fb"},
{"MERLAIN", "MERLAIN", "181a9978d9da7a7e"},
{"TOUCHDOWN", "CHALLENGE", "ff825fcbed9bf699"},
{"OOZY", "GAIDEN", "3d9c52142f9e53f5"},
{"MILLIE", "MOLLY", "3f80432f156088bf"},
{"SILVERPEAK", "SILVERPEAK", "271864e0978278a3"},
{"LUNAR", "PATROL", "7abd9e0a6321e813"},
{"ATTACK", "PETSCII", "a662862f20362fc5"},
{"KNIGHT", "BOARD", "0916973898e3b6b8"},
{"KNIGHT", "WORLD", "33dbb58f9ee73e9f"},
{"KNIGHT", "SOMETHING", "3ec728e116017be8"},
{"KNIGHT", "ANOTHER", "7abd9e0a6321e813"},
{"DRAGON", "DESCENT", "77164df89ae49b4d"},
{"DRAGON", "HAVOC", "8c2798f929a43317"},
{"DRAGON", "CACHE", "7b7825ca2c79148f"},
{"ARKANOID", "ARKANOID", "d99bff88cd3cce19"},
{"ARTI", "ATRI", "0d05659a7d0eef02"},
{"CANNON", "DEFENSE", "000b5888d2489f7e"},
{"1942", "1942", "fd9353d42cca5f81"},
{"WIZARD", "DUNGEON", "846751861993b907"},
{"UTILITY", "CART", "f5150c0fc1948832"},
{"BONQ", "BONQ", "9fa7743a016c9b70"},
{"BEEF", "DROP", "78b1061d651ef806"},
{"BERNIE", "CUBIC", "b11b1a2bae8a1d0c"},
{"BERNIE", "TOWER", "a34cd425d0c087d0"},
{"DEATH", "MERCHANT", "fab7b59dd580dce0"},
{"TUNNELS", "HYPERION", "0d7e2674d802b412"},
{"SLIDE", "MAZE", "40567f50c569a60c"},
{"CARTESIAN", "CHAOS", "825c03c049306c16"},
{"DANGER", "ZONE", "0c2f248a1ae9bfd1"},
{"SCRAMBLE", "SCRAMBLE", "a3a85e507d6f7189"},
{"KLAX", "KLAX", "17b3b764d33eae9b"},
{"PENTAGO", "PENTAGO", "6ac5a7f8b6a3198e"},
{"","",""}
};
// -------------------------------------------------------------------------
// This happens AFTER The rom is loaded and the header info (if any) has
// been read out. Here we can adjust based on the hash table above... which
// is mainly used for headerless roms and a few special cases were we want
// to correct the Y-offsets to make the game well centered/scaled on screen.
// -------------------------------------------------------------------------
bool database_Load(byte * digest)
{
extern u8 bNoDatabase;
bool bFound = false;
uint16 i;
// Uppercase the filename... to make searching easier.
for(int j = 0; j < strlen(cartridge_filename); j++) cartridge_filename[j] = toupper(cartridge_filename[j]);
// See if we've been asked to skip the internal database
if(!bNoDatabase)
bool bFound = false;
uint i;
// -------------------------------------------------------------------------
// This happens AFTER The rom is loaded and the header info (if any) has
// been read out. Here we can adjust based on the hash table above... which
// is mainly used for headerless roms and a few special cases were we want
// to correct the Y-offsets to make the game well centered/scaled on screen.
// -------------------------------------------------------------------------
if(database_enabled)
{
/* Look up mapper in game list */
for(i = 0; strlen(game_list[i].digest); i++)
{
// --------------------------------------------------------------------------------------
// First see if we've got a match in our external A7800DS.DAT configuration database...
// --------------------------------------------------------------------------------------
for(i = 0; i < MAX_CONFIGS; i++)
{
if(!strncmp(allConfigs.cart[i].half_digest, (char *) digest, 16))
{
memcpy( & myCartInfo, & allConfigs.cart[i], sizeof(myCartInfo));
bFound = true;
break;
}
}
if (!strcmp(game_list[i].digest,(char *) digest))
{
cartridge_type = game_list[i].cardtype;
cartridge_pokey = game_list[i].pokey;
cartridge_controller[0] = game_list[i].cardctrl1;
cartridge_controller[1] = game_list[i].cardctrl2;
cartridge_region = game_list[i].cardregion;
cartridge_flags = game_list[i].cardflags;
cartridge_hsc_enabled = game_list[i].hsc;
cartridge_yOffset = game_list[i].yOffset;
cartridge_wsync = !( cartridge_flags & CARTRIDGE_WSYNC_MASK );
cartridge_cycle_stealing = !( cartridge_flags & CARTRIDGE_CYCLE_STEALING_MASK );
bFound = true;
break;
}
}
}
if (!bFound)
{
cartridge_yOffset = 22;
}
cartridge_xOffset = 0;
// ---------------------------------------------------------------------------------------------
// If we didn't find it in the config database, we can look in the internal database table...
// ---------------------------------------------------------------------------------------------
if(!bFound)
{
/* Look up mapper in game list by md5sum */
for(i = 0; strlen(game_list[i].half_digest); i++)
{
if(!strncmp(game_list[i].half_digest, (char *) digest, 16))
{
memcpy( & myCartInfo, & game_list[i], sizeof(myCartInfo));
if(!isDSiMode()) myCartInfo.frameSkip = ((cartridge_size <= (48 * 1024)) ? FRAMESKIP_MEDIUM : FRAMESKIP_AGGRESSIVE); // Older DS-Lite/Phat needs help
myCartInfo.palette = 1; // Force this if not specifically found by md5
myCartInfo.xJiggle = 64;
myCartInfo.yJiggle = 16;
bFound = true;
break;
}
}
}
// -----------------------------------------------------------------------------------------------
// If we didn't find a definitive md5 match above, look up game by name in our name mapping table.
// -----------------------------------------------------------------------------------------------
if(!bFound)
{
for(int k = 0; strlen(NameMap[k].name1); k++)
{
if(myCartInfo.region == NTSC)
{
if((strstr(cartridge_filename, NameMap[k].name1)) && (strstr(cartridge_filename, NameMap[k].name2))) // If both names are found in the filename...
{
/* Look up mapper in game list by md5sum from the Name Mapper table */
for(i = 0; strlen(game_list[i].half_digest); i++)
{
if(!strncmp(game_list[i].half_digest, (char *) NameMap[k].half_digest, 16))
{
memcpy( & myCartInfo, & game_list[i], sizeof(myCartInfo));
if(!isDSiMode()) myCartInfo.frameSkip = ((cartridge_size <= (48 * 1024)) ? FRAMESKIP_MEDIUM : FRAMESKIP_AGGRESSIVE); // Older DS-Lite/Phat needs help
myCartInfo.palette = 1; // Force this if not specifically found by md5
myCartInfo.xJiggle = 64;
myCartInfo.yJiggle = 16;
bFound = true;
break;
}
}
break;
}
}
}
}
}
// No matter what... override for Tower Toppler to make it playable...
if(strcmp((char *) digest, (char *) "8d64763db3100aadc552db5e6868506a") == 0) // Tower Toppler
{
use_composite_filtering = 76;
myCartInfo.frameSkip = FRAMESKIP_AGGRESSIVE; // It's the only way we stand a chance.
myCartInfo.cardctrl1 = SOTA;
myCartInfo.xOffset = 32;
myCartInfo.yOffset = 8;
myCartInfo.xScale = 320;
myCartInfo.yScale = 234;
bFound = 1;
}
else if(strcmp((char *) digest, (char *) "f5150c0fc1948832211e57852abb0c6e") == 0) // 7800 Utility Cart
{
use_composite_filtering = 1;
bFound = 1;
}
// Override for Jinks to enable composite filtering
else if(strcmp((char *) digest, (char *) "045fd12050b7f2b842d5970f2414e912") == 0) // Jinks
{
use_composite_filtering = 1;
bFound = 1;
}
else use_composite_filtering = 0;
// --------------------------------------------------------------------------
// Default scaling options below if not found... these are close enough...
// We can make some educated guesses on cart and frameskip...
// --------------------------------------------------------------------------
if(!bFound)
{
strncpy(myCartInfo.half_digest, (char *) digest, 16);
myCartInfo.half_digest[16] = 0;
myCartInfo.xOffset = 0;
myCartInfo.yOffset = 13;
myCartInfo.xScale = 256;
myCartInfo.yScale = 220;
myCartInfo.diff1 = DIFF_A;
myCartInfo.diff2 = DIFF_A;
myCartInfo.xButton = KEY_MAP_DEFAULT;
myCartInfo.yButton = KEY_MAP_DEFAULT;
myCartInfo.spare2 = 0;
myCartInfo.spare3 = 0;
myCartInfo.spare4 = 1;
myCartInfo.spare5 = 0;
myCartInfo.palette = 1;
myCartInfo.xJiggle = 64;
myCartInfo.yJiggle = 16;
// -------------------------------------------------------------------
// If the game has no .a78 header, do our best to guess these...
// -------------------------------------------------------------------
if(myCartInfo.hasHeader == false)
{
myCartInfo.region = NTSC;
if(cartridge_size == (144 * 1024)) myCartInfo.cardtype = CT_SUPLRG;
else myCartInfo.cardtype = (cartridge_size <= (52 * 1024)) ? CT_NORMAL : CT_SUPROM;
myCartInfo.pokeyType = POKEY_NONE;
myCartInfo.cardctrl1 = JOY;
myCartInfo.cardctrl2 = JOY;
myCartInfo.hsc = false;
}
// --------------------------------------------------------
// Do our best guess as to whether we should frameskip...
// --------------------------------------------------------
if(isDSiMode()) // DSi can handle most games in full framerate... default to disable frameskip for the DSi
{
myCartInfo.frameSkip = FRAMESKIP_DISABLE;
}
else // DS-Lite defaults to some level of frame skipping
{
myCartInfo.frameSkip = ((cartridge_size <= (48 * 1024)) ? FRAMESKIP_MEDIUM : FRAMESKIP_AGGRESSIVE); // Non-banked carts get light frameskip... otherwise agressive
}
}
// Lastly - use the internal database to always try and find a BIOS timeout value... we don't let the user override this one...
myCartInfo.biosTimeout = 160;
bFound = 0;
for(i = 0; strlen(game_list[i].half_digest); i++) // Search through entire internal database...
{
if(!strncmp(game_list[i].half_digest, (char *) digest, 16)) // Search by md5sum
{
myCartInfo.biosTimeout = game_list[i].biosTimeout;
bFound = 1;
break;
}
}
if(!bFound) // And if not found - search by name to find a reasonable bios timeout value
{
for(int k = 0; strlen(NameMap[k].name1); k++)
{
if(myCartInfo.region == NTSC)
{
if((strstr(cartridge_filename, NameMap[k].name1)) && (strstr(cartridge_filename, NameMap[k].name2))) // If both names are found in the filename...
{
/* Look up bios timeout in game list by md5sum from the Name Mapper table */
for(i = 0; strlen(game_list[i].half_digest); i++)
{
if(!strncmp(game_list[i].half_digest, (char *) NameMap[k].half_digest, 16))
{
myCartInfo.biosTimeout = game_list[i].biosTimeout;
bFound = true;
break;
}
}
break;
}
}
}
}
return true;
return true;
}
// End of file

View file

@ -27,61 +27,9 @@
#include "Cartridge.h"
typedef struct {
char half_digest[17];
u8 cardtype;
u8 pokeyType;
u8 cardctrl1;
u8 cardctrl2;
u8 diff1;
u8 diff2;
u8 region;
u8 hsc;
u8 biosTimeout;
s16 xOffset;
s16 yOffset;
s16 xScale;
s16 yScale;
u8 frameSkip;
u8 spare0;
u8 spare1;
u8 hasHeader;
u8 palette;
u8 xJiggle;
u8 yJiggle;
u8 xButton;
u8 yButton;
u8 spare2;
u8 spare3;
u8 spare4;
u8 spare5;
u8 spare6;
u8 spare7;
} Database_Entry;
typedef struct {
char *name1;
char *name2;
char *half_digest;
} NameMap_t;
extern Database_Entry myCartInfo;
#define KEY_MAP_DEFAULT 0
#define KEY_MAP_PANUP 1
#define KEY_MAP_PANDN 2
#define KEY_MAP_JOYUP 3
#define KEY_MAP_JOYDN 4
#define KEY_MAP_JOYLEFT 5
#define KEY_MAP_JOYRIGHT 6
#define KEY_MAP_JOYB1 7
#define KEY_MAP_JOYB2 8
#define KEY_MAP_PAUSE 9
extern void database_Initialize( );
extern bool database_Load(byte *digest);
extern bool database_enabled;
//extern std::string database_filename;
#endif

View file

@ -25,7 +25,6 @@
#include <string.h>
#include <stdio.h>
#include "Hash.h"
#include "../printf.h"
// ----------------------------------------------------------------------------
// Step1
@ -232,7 +231,9 @@ void hash_Compute(const byte* source, uint length, byte * dest) {
for(index = 0; index < 16; index++) {
digest[index] = bufferptr[index];
}
//char buffer[33] = {0};
sprintf((char *)dest, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
//return buffer;
}

View file

@ -1,316 +0,0 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// HighScore.cpp
//
// The HSC hardware uses the Toshiba TC5516APL chip which is 2048 x 8bit (2K)
// and is maintained by a battery CR2032 at 3V
//
// With an SRAM of this vintage, the contents of an uninitialized / freshly
// powered up chip would likely be random values. For emulation purposes, we
// are initializing the SRAM contents on a fresh board as if they were zeros.
//
// With this emulation, each game gets their own private 2K SRAM for the
// HSC memory. Further, to avoid problems with some games that do not initialize
// the SRAM, we are going to use a fresh snapshot of the full 2K of SRAM right
// after a known good cart (Asteroids - NTSC) has initialized the memory.
// ----------------------------------------------------------------------------
#include <fat.h>
#include <dirent.h>
#include <ctype.h>
#include "HighScore.h"
#include "Cartridge.h"
#include "Database.h"
#define HS_SRAM_START 0x1000 // The 7800 RAM memory location of the high score cartridge SRAM
#define HS_SRAM_SIZE 2048 // The size of the high score cartridge SRAM and gets loaded at 7800 memory address 0x1000
#define HSC_CART_ROM_SIZE 4096 // The highscore.rom is exactly 4K in size and gets loaded at 7800 memory address 0x3000
static byte high_score_sram[HS_SRAM_SIZE]; // Buffer for the actual 2K of HSC data
static byte high_score_rom[HSC_CART_ROM_SIZE]; // Buffer for the 4K of high score ROM (highscore.rom)
byte high_score_cart_loaded = false; // Flips to true if the High Score Cart is loaded in memory
// -----------------------------------------------------------------------------------------------------
// This is a snapshot of an initialized HSC after Asteroids (NTSC) initialized it with the name "HSC"
// A few of the modern homebrews don't do a good job of initializing the HSC and so we use this as
// as default starting SRAM (of 0x00 before init) which is squeaky clean and ready for use by the game.
// -----------------------------------------------------------------------------------------------------
unsigned char A7800DS_00_sram[HS_SRAM_SIZE] = {
0x00, 0x00, 0x68, 0x83, 0xaa, 0x55, 0x9c, 0x02, 0x07, 0x12, 0x02, 0x1f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*
* Saves the high score cartridge SRAM
*
* return Whether the save was successful (false if game is not supporting HSC)
*/
static char szName[256+4];
static void make_hsc_name(void)
{
// Init HSC filename is same as base filename with .hsc
DIR* dir = opendir("sav");
if (dir) closedir(dir); // Directory exists... close it out and move on.
else mkdir("sav", 0777); // Otherwise create the directory...
sprintf(szName,"sav/%s", cartridge_filename);
int len = strlen(szName);
szName[len-3] = 'h';
szName[len-2] = 's';
szName[len-1] = 'c';
szName[len-0] = 0;
}
// ------------------------------------------------------------------------------------
// Write the full 2K of HSC - a bit wasteful for a single game but we've got plenty
// of space and it turns out to be more flexibile for each game to have their own HSC.
// ------------------------------------------------------------------------------------
bool cartridge_SaveHighScoreSram(void)
{
if(!high_score_cart_loaded || !myCartInfo.hsc)
{
return false; // If we didn't load the high score cartridge, or don't have an HSC enabled cart: don't save.
}
// Make sure something actually changed before writing...
if (memcmp(high_score_sram, memory_ram+HS_SRAM_START, HS_SRAM_SIZE) != 0)
{
memcpy(high_score_sram, memory_ram+HS_SRAM_START, HS_SRAM_SIZE); // Copy from main memory to SRAM buffer
make_hsc_name(); // HSC filename is same as base filename with .hsc extension
// Write out the .hsc file
FILE *handle = fopen(szName, "wb");
if (handle != NULL)
{
fwrite(high_score_sram, HS_SRAM_SIZE, 1, handle);
fclose(handle);
}
}
return true; // We at least made the attempt to write out the .hsc save file
}
/*
* Loads the high score cartridge SRAM
*
* return Whether the load was successful
*/
static bool cartridge_LoadHighScoreSram(void)
{
if(!high_score_cart_loaded || !myCartInfo.hsc)
{
return false; // If we didn't load the high score cartridge, or don't have an HSC enabled cart: don't save.
}
make_hsc_name(); // HSC filename is same as base filename with .hsc extension
// Read back the .hsc file
FILE *handle = fopen(szName, "rb");
if (handle != NULL)
{
fread(high_score_sram, HS_SRAM_SIZE, 1, handle);
fclose(handle);
}
else
{
// No .hsc file was available... so set the SRAM to a known good init value
memcpy(high_score_sram, A7800DS_00_sram, HS_SRAM_SIZE);
}
// Copy from SRAM buffer to main memory for use by the game
for(uint i = 0; i < HS_SRAM_SIZE; i++)
{
memory_Write(HS_SRAM_START + i, high_score_sram[i]);
}
bHSC_dirty = 0; // We don't consider the init of SRAM directly above to be a 'write' (no need to persist)
return true; // HSC SRAM is ready to go!
}
/*
* Loads the high score cartridge
*
* return Whether the load was successful
*/
bool cartridge_LoadHighScoreCart(void)
{
if( !myCartInfo.hsc || myCartInfo.region != 0 )
{
return false; // Only load the cart if it is enabled and the region is NTSC
}
FILE* file = fopen("highscore.rom", "rb" );
// If we don't find it in the current directory, always try /roms/bios and /data/bios
if (file == NULL) file = fopen("/roms/bios/highscore.rom", "rb" );
if (file == NULL) file = fopen("/data/bios/highscore.rom", "rb" );
if(file != NULL)
{
fread(high_score_rom, 1, HSC_CART_ROM_SIZE, file);
for( uint i = 0; i < HSC_CART_ROM_SIZE; i++ )
{
memory_Write(0x3000 + i, high_score_rom[i]);
}
high_score_cart_loaded = true;
// Now read in the associated .hsc SRAM file (or set SRAM to defaults)
cartridge_LoadHighScoreSram();
}
else
{
high_score_cart_loaded = false;
}
return high_score_cart_loaded;
}
// End of file

154
arm9/source/emu/Logger.c Normal file
View file

@ -0,0 +1,154 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Logger.cpp
// ----------------------------------------------------------------------------
#include "Logger.h"
#define LOGGER_FILENAME "ProSystem.log"
#if 0
byte logger_level = LOGGER_LEVEL_DEBUG;
# if 0 //LUDO:
static FILE* logger_file = NULL;
# else
# include <stdio.h>
# define logger_file stdout
# endif
#ifdef DEBUG
// ----------------------------------------------------------------------------
// GetTime
// ----------------------------------------------------------------------------
static char* logger_GetTime( ) {
time_t current;
time(&current);
char* timestring = ctime(&current);
return timestring.erase(timestring.find_first_of("\n"), 1);
}
// ----------------------------------------------------------------------------
// Log
// ----------------------------------------------------------------------------
static void logger_Log(char* message, byte level, char* source) {
#if 0
if(logger_file != NULL) {
char* entry = "[" + logger_GetTime( ) + "]";
switch(level) {
case LOGGER_LEVEL_ERROR:
entry += "[ERROR]";
break;
case LOGGER_LEVEL_INFO:
entry += "[INFO ]";
break;
default:
entry += "[DEBUG]";
break;
}
entry += " " + message;
if(source.length( ) > 0) {
entry += " {" + source + "}";
}
entry += "\n";
fwrite(entry.c_str( ), 1, entry.length( ), logger_file);
fflush(logger_file);
}
#endif
}
// ----------------------------------------------------------------------------
// Initialize
// ----------------------------------------------------------------------------
bool logger_Initialize( ) {
logger_file = fopen(LOGGER_FILENAME, "w");
return (logger_file != NULL);
}
// ----------------------------------------------------------------------------
// Initialize
// ----------------------------------------------------------------------------
bool logger_Initialize(char* filename) {
logger_file = fopen(filename.c_str( ), "w");
return (logger_file != NULL);
}
// ----------------------------------------------------------------------------
// LogError
// ----------------------------------------------------------------------------
void logger_LogError(char* message) {
logger_LogError(message, "");
}
// ----------------------------------------------------------------------------
// LogError
// ----------------------------------------------------------------------------
void logger_LogError(char* message, char* source) {
if(logger_level == LOGGER_LEVEL_ERROR || logger_level == LOGGER_LEVEL_INFO || logger_level == LOGGER_LEVEL_DEBUG) {
logger_Log(message, LOGGER_LEVEL_ERROR, source);
}
}
// ----------------------------------------------------------------------------
// LogInfo
// ----------------------------------------------------------------------------
void logger_LogInfo(char* message) {
logger_LogInfo(message, "");
}
// ----------------------------------------------------------------------------
// LogInfo
// ----------------------------------------------------------------------------
void logger_LogInfo(char* message, char* source) {
if(logger_level == LOGGER_LEVEL_INFO || logger_level == LOGGER_LEVEL_DEBUG) {
logger_Log(message, LOGGER_LEVEL_INFO, source);
}
}
// ----------------------------------------------------------------------------
// LogDebug
// ----------------------------------------------------------------------------
void logger_LogDebug(char* message) {
logger_LogDebug(message, "");
}
// ----------------------------------------------------------------------------
// LogDebug
// ----------------------------------------------------------------------------
void logger_LogDebug(char* message, char* source) {
if(logger_level == LOGGER_LEVEL_DEBUG) {
logger_Log(message, LOGGER_LEVEL_DEBUG, source);
}
}
// ----------------------------------------------------------------------------
// Release
// ----------------------------------------------------------------------------
void logger_Release( ) {
if(logger_file != NULL) {
fclose(logger_file);
}
}
#endif
#endif

65
arm9/source/emu/Logger.h Normal file
View file

@ -0,0 +1,65 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Logger.h
// ----------------------------------------------------------------------------
#ifndef LOGGER_H
#define LOGGER_H
#define LOGGER_LEVEL_DEBUG 0
#define LOGGER_LEVEL_INFO 1
#define LOGGER_LEVEL_ERROR 2
#if 0
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "shared.h"
#ifdef DEBUG
extern bool logger_Initialize( );
extern bool logger_Initialize(char* filename);
extern void logger_LogError(char* message);
extern void logger_LogError(char* message, char* source);
extern void logger_LogInfo(char* message);
extern void logger_LogInfo(char* message, char* source);
extern void logger_LogDebug(char* message);
extern void logger_LogDebug(char* message, char* source);
extern void logger_Release( );
#else
static inline bool logger_Initialize() {}
static inline bool logger_Initialize(char* filename) {}
static inline void logger_LogError(char* message) {}
static inline void logger_LogError(char* message, char* source) {}
static inline void logger_LogInfo(char* message) {}
static inline void logger_LogInfo(char* message, char* source) {}
static inline void logger_LogDebug(char* message) {}
static inline void logger_LogDebug(char* message, char* source) {}
static inline void logger_Release( ) {}
#endif
extern byte logger_level;
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -24,21 +24,30 @@
// ----------------------------------------------------------------------------
#ifndef MARIA_H
#define MARIA_H
# if 0 //LUDO:
#define MARIA_SURFACE_SIZE 93440
# else
#define MARIA_SURFACE_SIZE 77440
# endif
#define MARIA_SURFACE_SIZE (128*1024) // DS screen buffer size
// 93440 = 320 x 292
// 77440 = 320 x 242
#include "Equates.h"
#include "Pair.h"
#include "Memory.h"
#include "Rect.h"
#include "Sally.h"
#include "shared.h"
extern void maria_Reset( );
extern void maria_RenderScanline(void);
extern void maria_RenderScanlineTOP(void);
extern ITCM_CODE uint maria_RenderScanline( );
extern void maria_Clear( );
extern rect maria_displayArea;
extern rect maria_visibleArea;
extern word* maria_surface;
extern uint maria_scanline;
extern word maria_scanline;
#endif

View file

@ -0,0 +1,530 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Maria.c
// ----------------------------------------------------------------------------
#include "Maria.h"
#include "ProSystem.h"
union ColorUnion
{
int32 color32;
struct {
byte color0;
byte color1;
byte color2;
byte color3;
} by;
struct {
word color0;
word color1;
} wo;
};
union ColorUnion colors;
#define MARIA_LINERAM_SIZE 160
rect maria_displayArea = {0, 16, 319, 258};
rect maria_visibleArea = {0, 26, 319, 248};
word* maria_surface = 0;
word maria_scanline = 1;
static byte maria_lineRAM[MARIA_LINERAM_SIZE+4];
static uint maria_cycles;
static pair maria_dpp;
static pair maria_dp;
static pair maria_pp;
static byte maria_horizontal;
static byte maria_palette;
static char maria_offset;
static byte maria_h08;
static byte maria_h16;
static byte maria_wmode;
static inline void _maria_ClearCells(void)
{
if(maria_horizontal < MARIA_LINERAM_SIZE)
{
if (memory_ram[CTRL] & 4)
{
*((u16 *)&maria_lineRAM[maria_horizontal]) = 0;
}
}
maria_horizontal += 2;
}
static inline void _maria_ClearCells4(void)
{
if(maria_horizontal < MARIA_LINERAM_SIZE)
{
if (memory_ram[CTRL] & 4)
{
*((u32 *)&maria_lineRAM[maria_horizontal]) = 0;
}
}
maria_horizontal += 4;
}
// ----------------------------------------------------------------------------
// StoreCell
// ----------------------------------------------------------------------------
static inline void _maria_StoreCells4(byte data)
{
if((maria_horizontal+3) < MARIA_LINERAM_SIZE)
{
byte *ptr = &(maria_lineRAM[maria_horizontal+3]);
if (memory_ram[CTRL] & 4)
{
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else *ptr-- = 0;
data = data >> 2;
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else *ptr-- = 0;
data = data >> 2;
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else *ptr-- = 0;
data = data >> 2;
if (data) *ptr = maria_palette | (data); else *ptr = 0;
}
else
{
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else ptr--;
data = data >> 2;
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else ptr--;
data = data >> 2;
if (data & 0x03) *ptr-- = maria_palette | (data & 0x03); else ptr--;
data = data >> 2;
if (data) *ptr = maria_palette | (data);
}
}
maria_horizontal += 4;
}
static inline void maria_StoreCellWide(byte data)
{
if((maria_horizontal+1) < MARIA_LINERAM_SIZE)
{
byte mp = (maria_palette & 16);
maria_lineRAM[maria_horizontal++] = mp | (data >> 4);
maria_lineRAM[maria_horizontal++] = mp | (data & 0x0F);
} else maria_horizontal += 2;
}
// ----------------------------------------------------------------------------
// StoreCell
// ----------------------------------------------------------------------------
static inline void maria_ClearCellWide(void)
{
if(memory_ram[CTRL] & 4)
{
byte *ptr = (byte *)&maria_lineRAM[maria_horizontal];
if(maria_horizontal < MARIA_LINERAM_SIZE) *ptr++ = 0;
maria_horizontal++;
if(maria_horizontal < MARIA_LINERAM_SIZE) *ptr = 0;
maria_horizontal++;
}
else maria_horizontal += 2;
}
// ----------------------------------------------------------------------------
// IsHolyDMA
// ----------------------------------------------------------------------------
static inline bool maria_IsHolyDMA( )
{
if(maria_pp.w & 0x8000)
{
if(maria_h16 && (maria_pp.w & 4096)) {
return true;
}
if(maria_h08 && (maria_pp.w & 2048)) {
return true;
}
}
return false;
}
// ----------------------------------------------------------------------------
// GetColor
// ----------------------------------------------------------------------------
static inline byte maria_GetColor(byte data)
{
return (data & 3) ? memory_ram[BACKGRND + data] : memory_ram[BACKGRND];
}
static u8 wide_lookup[256] =
{
0x00, 0x04, 0x08, 0x0C, 0x40, 0x44, 0x48, 0x4C, 0x80, 0x84, 0x88, 0x8C, 0xC0, 0xC4, 0xC8, 0xCC,
0x01, 0x05, 0x09, 0x0D, 0x41, 0x45, 0x49, 0x4D, 0x81, 0x85, 0x89, 0x8D, 0xC1, 0xC5, 0xC9, 0xCD,
0x02, 0x06, 0x0A, 0x0E, 0x42, 0x46, 0x4A, 0x4E, 0x82, 0x86, 0x8A, 0x8E, 0xC2, 0xC6, 0xCA, 0xCE,
0x03, 0x07, 0x0B, 0x0F, 0x43, 0x47, 0x4B, 0x4F, 0x83, 0x87, 0x8B, 0x8F, 0xC3, 0xC7, 0xCB, 0xCF,
0x10, 0x14, 0x18, 0x1C, 0x50, 0x54, 0x58, 0x5C, 0x90, 0x94, 0x98, 0x9C, 0xD0, 0xD4, 0xD8, 0xDC,
0x11, 0x15, 0x19, 0x1D, 0x51, 0x55, 0x59, 0x5D, 0x91, 0x95, 0x99, 0x9D, 0xD1, 0xD5, 0xD9, 0xDD,
0x12, 0x16, 0x1A, 0x1E, 0x52, 0x56, 0x5A, 0x5E, 0x92, 0x96, 0x9A, 0x9E, 0xD2, 0xD6, 0xDA, 0xDE,
0x13, 0x17, 0x1B, 0x1F, 0x53, 0x57, 0x5B, 0x5F, 0x93, 0x97, 0x9B, 0x9F, 0xD3, 0xD7, 0xDB, 0xDF,
0x20, 0x24, 0x28, 0x2C, 0x60, 0x64, 0x68, 0x6C, 0xA0, 0xA4, 0xA8, 0xAC, 0xE0, 0xE4, 0xE8, 0xEC,
0x21, 0x25, 0x29, 0x2D, 0x61, 0x65, 0x69, 0x6D, 0xA1, 0xA5, 0xA9, 0xAD, 0xE1, 0xE5, 0xE9, 0xED,
0x22, 0x26, 0x2A, 0x2E, 0x62, 0x66, 0x6A, 0x6E, 0xA2, 0xA6, 0xAA, 0xAE, 0xE2, 0xE6, 0xEA, 0xEE,
0x23, 0x27, 0x2B, 0x2F, 0x63, 0x67, 0x6B, 0x6F, 0xA3, 0xA7, 0xAB, 0xAF, 0xE3, 0xE7, 0xEB, 0xEF,
0x30, 0x34, 0x38, 0x3C, 0x70, 0x74, 0x78, 0x7C, 0xB0, 0xB4, 0xB8, 0xBC, 0xF0, 0xF4, 0xF8, 0xFC,
0x31, 0x35, 0x39, 0x3D, 0x71, 0x75, 0x79, 0x7D, 0xB1, 0xB5, 0xB9, 0xBD, 0xF1, 0xF5, 0xF9, 0xFD,
0x32, 0x36, 0x3A, 0x3E, 0x72, 0x76, 0x7A, 0x7E, 0xB2, 0xB6, 0xBA, 0xBE, 0xF2, 0xF6, 0xFA, 0xFE,
0x33, 0x37, 0x3B, 0x3F, 0x73, 0x77, 0x7B, 0x7F, 0xB3, 0xB7, 0xBB, 0xBF, 0xF3, 0xF7, 0xFB, 0xFF
};
// ----------------------------------------------------------------------------
// StoreGraphic
// ----------------------------------------------------------------------------
static inline void maria_StoreGraphic( )
{
byte data = memory_ram[maria_pp.w];
if(maria_wmode)
{
if(maria_IsHolyDMA() || !data)
{
maria_ClearCellWide();
}
else
{
maria_StoreCellWide(wide_lookup[data]);
}
}
else
{
if(maria_IsHolyDMA() || !data)
{
_maria_ClearCells4();
}
else
{
_maria_StoreCells4(data);
}
}
maria_pp.w++;
}
static u8 wide_lookup_mode2A[] =
{
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13,
0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03,
0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x11, 0x11, 0x13, 0x13, 0x11, 0x11, 0x13, 0x13
};
static u8 wide_lookup_mode2B[] =
{
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13,
0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x02, 0x01, 0x03, 0x01, 0x03,
0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13, 0x10, 0x12, 0x10, 0x12, 0x11, 0x13, 0x11, 0x13
};
// ----------------------------------------------------------------------------
// WriteLineRAM
// ----------------------------------------------------------------------------
static inline void maria_WriteLineRAM(word* buffer)
{
extern uint32 bg32;
uint index;
unsigned int *pix=(unsigned int *) buffer;
uint32 *ptr = (uint32 *)&maria_lineRAM[0];
byte rmode = memory_ram[CTRL] & 3;
if(rmode == 0)
{
for(index = 0; index < MARIA_LINERAM_SIZE/4; index++)
{
colors.color32 = *ptr++;
if ((colors.wo.color0) == 0)
{
*pix++ = bg32;
}
else
{
word color, color1;
color = maria_GetColor(colors.by.color0);
color1 = maria_GetColor(colors.by.color1);
*pix++ = color | (color<<8) | (color1<<16) | (color1<<24);
}
if ((colors.wo.color1) == 0)
{
*pix++ = bg32;
}
else
{
word color, color1;
color = maria_GetColor(colors.by.color2);
color1 = maria_GetColor(colors.by.color3);
*pix++ = color | (color<<8) | (color1<<16) | (color1<<24);
}
}
}
else if(rmode == 2)
{
for(index = 0; index < MARIA_LINERAM_SIZE/4; index++)
{
colors.color32 = *ptr++;
if (colors.color32 == 0)
{
*pix++ = bg32;
*pix++ = bg32;
}
else
{
*pix++ = maria_GetColor(wide_lookup_mode2A[colors.by.color0]) |
maria_GetColor(wide_lookup_mode2B[colors.by.color0]) << 8 |
maria_GetColor(wide_lookup_mode2A[colors.by.color1]) << 16 |
maria_GetColor(wide_lookup_mode2B[colors.by.color1]) << 24;
*pix++ = maria_GetColor(wide_lookup_mode2A[colors.by.color2]) |
maria_GetColor(wide_lookup_mode2B[colors.by.color2]) << 8 |
maria_GetColor(wide_lookup_mode2A[colors.by.color3]) << 16 |
maria_GetColor(wide_lookup_mode2B[colors.by.color3]) << 24;
}
}
}
else if(rmode == 3)
{
for(index = 0; index < MARIA_LINERAM_SIZE/4; index++)
{
colors.color32 = *ptr++;
if (colors.color32 == 0)
{
*pix++ = bg32;
*pix++ = bg32;
}
else
{
*pix++ = maria_GetColor((colors.by.color0 & 30)) |
(maria_GetColor((colors.by.color0 & 28) | ((colors.by.color0 & 1) << 1)) <<8) |
(maria_GetColor((colors.by.color1 & 30))<<16) |
(maria_GetColor((colors.by.color1 & 28) | ((colors.by.color1 & 1) << 1)) <<24);
*pix++ = maria_GetColor((colors.by.color2 & 30)) |
(maria_GetColor((colors.by.color2 & 28) | ((colors.by.color2 & 1) << 1)) <<8) |
(maria_GetColor((colors.by.color3 & 30))<<16) |
(maria_GetColor((colors.by.color3 & 28) | ((colors.by.color3 & 1) << 1)) <<24);
}
}
}
}
// ----------------------------------------------------------------------------
// StoreLineRAM
// ----------------------------------------------------------------------------
static inline void maria_StoreLineRAM( )
{
uint index;
u32 *ptr=(u32*)maria_lineRAM;
//memset(maria_lineRAM, 0, MARIA_LINERAM_SIZE);
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;
*ptr++ = 0;*ptr++ = 0;*ptr++ = 0;*ptr = 0;
byte mode = memory_ram[maria_dp.w + 1];
while(mode & 0x5f)
{
byte width;
byte indirect = 0;
maria_pp.b.l = memory_ram[maria_dp.w];
maria_pp.b.h = memory_ram[maria_dp.w + 2];
if(mode & 31)
{
maria_cycles += 8; // Maria cycles (Header 4 byte)
maria_palette = (memory_ram[maria_dp.w + 1] & 224) >> 3;
maria_horizontal = memory_ram[maria_dp.w + 3];
width = memory_ram[maria_dp.w + 1] & 31;
width = ((~width) & 31) + 1;
maria_dp.w += 4;
}
else
{
maria_cycles += 12; // Maria cycles (Header 5 byte)
maria_palette = (memory_ram[maria_dp.w + 3] & 224) >> 3;
maria_horizontal = memory_ram[maria_dp.w + 4];
indirect = memory_ram[maria_dp.w + 1] & 32;
maria_wmode = memory_ram[maria_dp.w + 1] & 128;
width = memory_ram[maria_dp.w + 3] & 31;
width = (width == 0)? 32: ((~width) & 31) + 1;
maria_dp.w += 5;
}
if(!indirect)
{
maria_pp.b.h += maria_offset;
for(index = 0; index < width; index++)
{
maria_cycles += 3; // Maria cycles (Direct graphic read)
maria_StoreGraphic();
}
}
else {
byte cwidth = memory_ram[CTRL] & 16;
pair basePP = maria_pp;
for(index = 0; index < width; index++) {
//maria_cycles += 3; // Maria cycles (Indirect)
maria_pp.b.l = memory_ram[basePP.w++];
maria_pp.b.h = memory_ram[CHARBASE] + maria_offset;
maria_cycles += 6; // Maria cycles (Indirect, 1 byte)
maria_StoreGraphic( );
if(cwidth) {
maria_cycles += 3; // Maria cycles (Indirect, 2 bytes)
maria_StoreGraphic( );
}
}
}
mode = memory_ram[maria_dp.w + 1];
}
}
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void maria_Reset( ) {
maria_surface = bufVideo;
maria_scanline = 1;
memset(maria_surface, 0, MARIA_SURFACE_SIZE);
// These values need to be reset to allow switching between carts.
// This appears to be a bug in the ProSystem emulator.
//
maria_cycles = 0;
maria_dpp.w = 0;
maria_dp.w = 0;
maria_pp.w = 0;
maria_horizontal = 0;
maria_palette = 0;
maria_offset = 0;
maria_h08 = 0;
maria_h16 = 0;
maria_wmode = 0;
}
// ----------------------------------------------------------------------------
// RenderScanline
// ----------------------------------------------------------------------------
word *framePtr = (word *)0;
ITCM_CODE uint maria_RenderScanline( )
{
extern int gTotalAtariFrames;
maria_cycles = 0;
if(((memory_ram[CTRL] & 0x60) == 0x40))
{
maria_cycles += 5; // Maria cycles (DMA Startup)
if(maria_scanline == maria_displayArea.top)
{
maria_cycles += 10; // Maria cycles (End of VBLANK)
maria_dpp.b.l = memory_ram[DPPL];
maria_dpp.b.h = memory_ram[DPPH];
maria_h08 = memory_ram[maria_dpp.w] & 32;
maria_h16 = memory_ram[maria_dpp.w] & 64;
maria_offset = memory_ram[maria_dpp.w] & 15;
maria_dp.b.l = memory_ram[maria_dpp.w + 2];
maria_dp.b.h = memory_ram[maria_dpp.w + 1];
if(memory_ram[maria_dpp.w] & 128)
{
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
sally_ExecuteNMI( );
}
}
else
{
// This is where we render the video memory...
if (gTotalAtariFrames & 1) // Skip every other frame...
{
maria_WriteLineRAM(framePtr);
framePtr += 256;
}
}
if(maria_scanline != maria_displayArea.bottom)
{
maria_dp.b.l = memory_ram[maria_dpp.w + 2];
maria_dp.b.h = memory_ram[maria_dpp.w + 1];
maria_StoreLineRAM( );
maria_offset--;
if(maria_offset < 0)
{
maria_cycles += 10; // Maria cycles (Last line of zone) ( /*20*/
maria_dpp.w += 3;
maria_h08 = memory_ram[maria_dpp.w] & 32;
maria_h16 = memory_ram[maria_dpp.w] & 64;
maria_offset = memory_ram[maria_dpp.w] & 15;
if(memory_ram[maria_dpp.w] & 128)
{
maria_cycles += 20; // Maria cycles (NMI) /*29, 16, 20*/
//ALEK Fst6502_Cause_Interrupt(IRQ_NMI);
sally_ExecuteNMI( );
}
}
else
{
maria_cycles += 4; // Maria cycles (Other lines of zone)
}
}
}
return maria_cycles;
}
// ----------------------------------------------------------------------------
// Clear
// ----------------------------------------------------------------------------
void maria_Clear( )
{
maria_surface = bufVideo;
memset(maria_surface, 0x00, MARIA_SURFACE_SIZE);
}

View file

@ -5,7 +5,7 @@
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
//
// 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
@ -22,348 +22,187 @@
// ----------------------------------------------------------------------------
// Memory.cpp
// ----------------------------------------------------------------------------
#include "ProSystem.h"
#include "Memory.h"
#include "Maria.h"
#include "Database.h"
byte memory_ram[MEMORY_SIZE] ALIGN(32) = {0};
u8 is_memory_writable[256] __attribute__((section(".dtcm")));
u32 snes_bit_pos = 0;
u8 bHSC_dirty = 0;
u8 bINPTCTRL_locked = 0;
byte memory_ram[MEMORY_SIZE] = {0};
byte memory_rom[MEMORY_SIZE] = {0};
//ALEK byte *memory_rom = memory_ram;
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void memory_Reset()
{
uint index;
for(index = 0x4000; index < MEMORY_SIZE; index++)
{
memory_ram[index] = 0xff;
is_memory_writable[index >> 8] = 0;
}
for(index = 0; index < 0x4000; index++)
{
memory_ram[index] = 0x00;
is_memory_writable[index >> 8] = 1;
}
bHSC_dirty = 0;
snes_bit_pos = 0;
bINPTCTRL_locked = 0;
void memory_Reset( ) {
uint index;
for(index = 0; index < MEMORY_SIZE; index++) {
memory_ram[index] = 0;
memory_rom[index] = 1;
}
for(index = 0; index < 16384; index++) {
memory_rom[index] = 0;
}
}
// AM_RANGE(0x0020, 0x003f) AM_MIRROR(0x300) AM_READWRITE(a7800_MARIA_r, a7800_MARIA_w)
// ----------------------------------------------------------------------------
// Read
// ----------------------------------------------------------------------------
ITCM_CODE byte memory_Read_Slower(word address)
{
extern u8 write_only_pokey_at_4000;
ITCM_CODE byte memory_Read(word address) {
byte tmp_byte;
if((address & 0xFFFC) == 0x284)
{
if(address & 0x1)
{
byte tmp_byte = memory_ram[INTFLG];
memory_ram[INTFLG] &= 0x7f;
return tmp_byte;
}
else
{
memory_ram[INTFLG] &= 0x7f;
return memory_ram[INTIM];
}
}
else if(myCartInfo.pokeyType)
{
if(myCartInfo.pokeyType == POKEY_AT_4000)
{
if(((address & 0xFFF0) == 0x4000) && (!write_only_pokey_at_4000)) return pokey_GetRegister(address);
}
else
{
// Not quite accurate as it will catch anything from 0x440 to 0x4C0 but that's
// good enough as nothing else should be mapped in this region except POKEY.
if((address & 0xFFC0) == 0x440) return pokey_GetRegister(0x4000 | (address & 0xF));
if((address & 0xFFF0) == 0x800) return pokey_GetRegister(0x4000 | (address & 0xF));
}
}
switch ( address ) {
case INTIM:
case INTIM | 0x2:
memory_ram[INTFLG] &= 0x7f;
return memory_ram[INTIM];
break;
case INTFLG:
case INTFLG | 0x2:
tmp_byte = memory_ram[INTFLG];
memory_ram[INTFLG] &= 0x7f;
return tmp_byte;
break;
default:
return memory_ram[address];
break;
}
}
// ----------------------------------------------------------------------------
// Write
// ----------------------------------------------------------------------------
ITCM_CODE void memory_Write(word address, byte data)
{
extern u32 bg32, maria_charbase;
extern u8 bg8;
ITCM_CODE void memory_Write(word address, byte data) {
//ALEK void memory_Write(byte data,word address) {
if(unlikely(myCartInfo.pokeyType))
{
if(myCartInfo.pokeyType == POKEY_AT_4000)
{
if((address & 0xFFF0) == 0x4000)
{
pokey_SetRegister(address, data);
return;
}
if(!memory_rom[address]) {
switch(address) {
case INPTCTRL:
if(data == 22 && cartridge_IsLoaded( )) {
cartridge_Store( );
}
else
{
// Not quite accurate as it will catch anything from 0x440 to 0x4C0 but that's
// good enough as nothing else should be mapped in this region except POKEY.
if((address & 0xFFC0) == 0x440)
{
pokey_SetRegister(0x4000 | (address & 0x0F), data);
return;
}
if((address & 0xFFF0) == 0x800) // Pokey @800
{
pokey_SetRegister(0x4000 | (address & 0x0F), data);
return;
}
else if(data == 2 && bios_enabled) {
bios_Store( );
}
break;
case INPT0:
break;
case INPT1:
break;
case INPT2:
break;
case INPT3:
break;
case INPT4:
break;
case INPT5:
break;
case AUDC0:
tia_audc[0] = data & 15;
tia_MemoryChannel(0);
break;
case AUDC1:
tia_audc[1] = data & 15;
tia_MemoryChannel(1);
break;
case AUDF0:
tia_audf[0] = data & 31;
tia_MemoryChannel(0);
break;
case AUDF1:
tia_audf[1] = data & 31;
tia_MemoryChannel(1);
break;
case AUDV0:
tia_audv[0] = (data & 15) << 2;
tia_MemoryChannel(0);
break;
case AUDV1:
tia_audv[1] = (data & 15) << 2;
tia_MemoryChannel(1);
break;
//#define WSYNC 36 -> 0x24
case WSYNC:
if(!(cartridge_flags & 128)) {
memory_ram[WSYNC] = true;
}
break;
// #define SWCHB 642 -> 0x282
//#define CTLSWB 643
case SWCHB:
/*gdement: Writing here actually writes to DRB inside the RIOT chip.
This value only indirectly affects output of SWCHB.*/
riot_SetDRB(data);
break;
case SWCHA:
riot_SetDRA(data);
// case CTLSWB:
break;
// #define TIM1T 660
case TIM1T:
case TIM1T | 0x8:
riot_SetTimer(TIM1T, data);
break;
case TIM8T:
case TIM8T | 0x8:
riot_SetTimer(TIM8T, data);
break;
case TIM64T:
case TIM64T | 0x8:
riot_SetTimer(TIM64T, data);
break;
case T1024T:
case T1024T | 0x8:
riot_SetTimer(T1024T, data);
break;
default:
memory_ram[address] = data;
// 0x2040 -> 0x20ff (0x2000)
if(address >= 8256 && address <= 8447) {
memory_ram[address - 8192] = data;
}
// 0x2140 -> 0x21fe (0x2000)
else if(address >= 8512 && address <= 8702) {
memory_ram[address - 8192] = data;
}
// 0x40 -> 0xff (0x2000)
else if(address >= 64 && address <= 255) {
memory_ram[address + 8192] = data;
}
// 0x140 -> 0x1ff (0x2000)
else if(address >= 320 && address <= 511) {
memory_ram[address + 8192] = data;
}
cartridge_Write(address, data);
break;
}
if(is_memory_writable[address >> 8])
{
// ---------------------------------------------------------------------------------------
// If this write would be in normal (non bankset) memory, we need to keep the bankset
// memory up to date as well... This speeds up processing in Maria for banksets handling.
// ---------------------------------------------------------------------------------------
extern byte banksets_memory[];
extern u16 banksets_mask;
if(!(address & banksets_mask)) banksets_memory[address] = data;
if((address & 0x5000)) // This will catch RAM at 0x4000 and HSC at 0x1000
{
// For banking RAM we need to keep the shadow up to date.
if((address & 0x5000) == 0x4000)
{
extern u8 * shadow_ram;
shadow_ram[address] = data;
if(myCartInfo.cardtype == CARTRIDGE_TYPE_FRACTALUS)
{
// Special EXRAM/A8 handling... mirror ram
memory_ram[address ^ 0x0100] = data;
}
memory_ram[address] = data;
return;
}
else if((address & 0xF800) == 0x1000) // HSC RAM - set the dirty bit so we persist the .hsc file in the main loop
{
if(memory_ram[address] != data)
{
memory_ram[address] = data;
if(address != 0x1007 && (address < 0x17FA)) // Don't count the 'function' address nor the temp score...
{
bHSC_dirty = 1;
}
}
return;
}
}
else if((address & 0xFFE0) == 0x460) return; // XM/Yamaha is mapped into 460 - 47F... do not respond to it as we are not XM capable (yet)
// ---------------------------------------------------------------------
// Until we are 'locked' into a mode, address range 0x00 to 0x1f
// (overlapping the TIA) will respond as write-only register INPTCTRL
// ---------------------------------------------------------------------
if((address & 0xFCFF) <= 0x1f)
{
if(!bINPTCTRL_locked)
{
if(data & 0x04) cartridge_Store();
else bios_Store();
}
if(data & 0x01) bINPTCTRL_locked = 1;
}
switch(address)
{
case INPT0:
break;
case INPT1:
break;
case INPT2:
break;
case INPT3:
break;
case INPT4:
break;
case INPT5:
break;
case BACKGRND:
memory_ram[BACKGRND] = data;
bg8 = data;
bg32 = data | (data << 8) | (data << 16) | (data << 24);
break;
case CHARBASE:
memory_ram[CHARBASE] = data;
maria_charbase = data;
break;
case AUDC0:
tia_audc[0] = data & 15;
tia_MemoryChannel(0);
break;
case AUDC1:
tia_audc[1] = data & 15;
tia_MemoryChannel(1);
break;
case AUDF0:
tia_audf[0] = data & 31;
tia_MemoryChannel(0);
break;
case AUDF1:
tia_audf[1] = data & 31;
tia_MemoryChannel(1);
break;
case AUDV0:
tia_audv[0] = (data & 15) << 2;
tia_MemoryChannel(0);
break;
case AUDV1:
tia_audv[1] = (data & 15) << 2;
tia_MemoryChannel(1);
break;
case WSYNC:
memory_ram[WSYNC] = true;
riot_and_wsync |= 0x01;
break;
case SWCHB:
/*gdement: Writing here actually writes to DRB inside the RIOT chip.
This value only indirectly affects output of SWCHB.*/
riot_SetDRB(data);
break;
case SWCHA:
if(myCartInfo.cardctrl1 == SNES)
{
extern byte riot_dra;
if((data & 0x20) != (riot_dra & 0x20)) // Change of Latch state
{
snes_bit_pos = 0;
if(snes_adaptor & (1 << snes_bit_pos)) memory_ram[INPT4] |= 0x80;
else memory_ram[INPT4] &= 0x7F;
}
if((data & 0x10) != (riot_dra & 0x10)) // Change of Clock state
{
if(data & 0x10) // Clock going High
{
snes_bit_pos++;
}
else // Clock going low
{
if(snes_bit_pos >= 17) snes_bit_pos = 0;
if(snes_adaptor & (1 << snes_bit_pos)) memory_ram[INPT4] |= 0x80;
else memory_ram[INPT4] &= 0x7F;
}
}
}
riot_SetDRA(data);
break;
case TIM1T:
case TIM1T | 0x8:
riot_SetTimer(TIM1T, data);
break;
case TIM8T:
case TIM8T | 0x8:
riot_SetTimer(TIM8T, data);
break;
case TIM64T:
case TIM64T | 0x8:
riot_SetTimer(TIM64T, data);
break;
case T1024T:
case T1024T | 0x8:
riot_SetTimer(T1024T, data);
break;
default:
memory_ram[address] = data;
#ifdef RAM_MIRRORS_ENABLED
// ------------------------------------------------------
// Handle the RAM mirrors that the 7800 presents...
//
// 0x2040 - 0x20FF RAM block 0 (mirror of 0x0040-00FF)
// 0x2140 - 0x21FF RAM block 1 (mirror of 0x0140-01FF)
// ------------------------------------------------------
if(address >= 0x2040)
{
// 0x2040 -> 0x20ff (0x2000)
if(address <= 0x20FF)
{
memory_ram[address & 0x00FF] = data;
}
// 0x2140 -> 0x21ff (0x2100)
else if(address >= 0x2140 && address <= 0x21FF)
{
memory_ram[address & 0x01FF] = data;
}
}
else if(address < 0x200)
{
// 0x40 -> 0xff (0x2000)
if(address >= 0x40 && address <= 0xFF)
{
memory_ram[address | 0x2000] = data;
}
// 0x140 -> 0x1ff (0x2100)
else if(address >= 0x140 && address <= 0x1FF)
{
memory_ram[address | 0x2000] = data;
}
}
#endif
break;
}
}
else
{
cartridge_Write(address, data);
}
}
else {
cartridge_Write(address, data);
}
}
// ----------------------------------------------------------------------------
// WriteROM
// ----------------------------------------------------------------------------
ITCM_CODE void memory_WriteROM(word address, u32 size, const byte * data)
{
memcpy( & memory_ram[address], data, size);
memset( & is_memory_writable[address >> 8], 0x00, size >> 8);
}
// ----------------------------------------------------------------------------
// WriteROMFast (assumes is_memory_writable[] already set properly)
// size is already in multiples of 8x u32 dwords (32 bytes)
// ----------------------------------------------------------------------------
ITCM_CODE void memory_WriteROMFast(word address, u32 size, const u32 * data)
{
u32 * ramPtr = (u32 * ) & memory_ram[address];
u32 * dataPtr = (u32 * ) data;
u32 size2 = size;
do {
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
* ramPtr++ = * dataPtr++;
void memory_WriteROM(word address, word size, const byte* data) {
uint index;
if((address + size) <= MEMORY_SIZE && data != NULL) {
for(index = 0; index < size; index++) {
memory_ram[address + index] = data[index];
memory_rom[address + index] = 1;
}
while(--size2);
}
}
// ----------------------------------------------------------------------------
// ClearROM
// ----------------------------------------------------------------------------
void memory_ClearROM(word address, word size)
{
memset( & memory_ram[address], 0x00, size);
memset( & is_memory_writable[address >> 8], 0xFF, size >> 8);
void memory_ClearROM(word address, word size) {
uint index;
if((address + size) <= MEMORY_SIZE) {
for(index = 0; index < size; index++) {
memory_ram[address + index] = 0;
memory_rom[address + index] = 0;
}
}
}

View file

@ -27,31 +27,23 @@
#define MEMORY_SIZE 65536
#include "Equates.h"
#include "Bios.h"
#include "Cartridge.h"
#include "Tia.h"
#include "Riot.h"
#include "shared.h"
extern u8 bHSC_dirty;
extern byte memory_ram[MEMORY_SIZE];
extern void memory_Reset( );
extern ITCM_CODE byte memory_Read(word address);
extern ITCM_CODE void memory_Write(word address, byte data);
//ALEK extern void memory_Write(byte data,word address);
extern byte memory_Read_Slower(word address);
extern void memory_Write(word address, byte data);
extern void memory_WriteZP(word address, byte data);
inline byte memory_Read(word address)
{
if (address & 0x4E00) return memory_Read_Slower(address); // If these bits are set, might be POKEY access... or RIOT read
else return memory_ram[address];
}
extern void memory_WriteROM(word address, u32 size, const byte* data);
extern void memory_WriteROMFast(word address, u32 size, const u32* data);
extern void memory_WriteROM(word address, word size, const byte* data);
extern void memory_ClearROM(word address, word size);
extern byte memory_ram[MEMORY_SIZE];
extern byte memory_rom[MEMORY_SIZE];
//ALEK extern byte *memory_rom;
extern byte* get_memory_ram();

View file

@ -37,17 +37,4 @@ typedef union {
} Pair;
typedef Pair pair;
typedef union {
u32 w;
struct {
byte l;
byte h;
byte b2;
byte b3;
} b;
} LPair;
typedef LPair lpair;
#endif

View file

@ -26,8 +26,8 @@
#define PALETTE_SOURCE "Palette.cpp"
char * palette_filename;
// Taken from Wii Port 0.5
bool palette_default = true;
// 1.3
byte palette_data[PALETTE_SIZE] = {
0x00,0x00,0x00,0x25,0x25,0x25,0x34,0x34,0x34,0x4F,0x4F,0x4F,
0x5B,0x5B,0x5B,0x69,0x69,0x69,0x7B,0x7B,0x7B,0x8A,0x8A,0x8A,
@ -69,12 +69,12 @@ byte palette_data[PALETTE_SIZE] = {
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
0x00,0x38,0x39,0x00,0x3C,0x48,0x00,0x3D,0x5B,0x02,0x66,0x7F,
0x03,0x73,0x83,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
0x03,0xBB,0xFF,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x8B,0x00,
0x00,0xA9,0x00,0x00,0xBB,0x05,0x00,0xBD,0x00,0x02,0xD0,0x05,
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
@ -94,21 +94,115 @@ byte palette_data[PALETTE_SIZE] = {
0xE6,0xA4,0x40,0xF4,0xB1,0x4B,0xFD,0xC1,0x58,0xFF,0xCC,0x55,
0xFF,0xD4,0x61,0xFF,0xDD,0x69,0xFF,0xE6,0x79,0xFF,0xEA,0x98
};
#if 0
// 1.2
byte palette_data[PALETTE_SIZE] = {
0x00,0x00,0x00,0x25,0x25,0x25,0x34,0x34,0x34,0x4F,0x4F,0x4F,
0x5B,0x5B,0x5B,0x69,0x69,0x69,0x7B,0x7B,0x7B,0x8A,0x8A,0x8A,
0xA7,0xA7,0xA7,0xB9,0xB9,0xB9,0xC5,0xC5,0xC5,0xD0,0xD0,0xD0,
0xD7,0xD7,0xD7,0xE1,0xE1,0xE1,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,
0x4C,0x32,0x00,0x62,0x3A,0x00,0x7B,0x4A,0x00,0x9A,0x60,0x00,
0xB5,0x74,0x00,0xCC,0x85,0x00,0xE7,0x9E,0x08,0xF7,0xAF,0x10,
0xFF,0xC3,0x18,0xFF,0xD0,0x20,0xFF,0xD8,0x28,0xFF,0xDF,0x30,
0xFF,0xE6,0x3B,0xFF,0xF4,0x40,0xFF,0xFA,0x4B,0xFF,0xFF,0x50,
0x99,0x25,0x00,0xAA,0x25,0x00,0xB4,0x25,0x00,0xD3,0x30,0x00,
0xDD,0x48,0x02,0xE2,0x50,0x09,0xF4,0x67,0x00,0xF4,0x71,0x00,
0xFF,0x9E,0x10,0xFF,0xAC,0x20,0xFF,0xBA,0x3A,0xFF,0xBF,0x50,
0xFF,0xC6,0x6D,0xFF,0xD5,0x80,0xFF,0xE4,0x90,0xFF,0xE6,0x99,
0x99,0x00,0x00,0xA9,0x00,0x00,0xC6,0x13,0x00,0xD8,0x04,0x00,
0xE2,0x35,0x00,0xE4,0x40,0x00,0xE3,0x50,0x15,0xE3,0x52,0x25,
0xFD,0x78,0x54,0xFF,0x8A,0x6A,0xFF,0x98,0x7C,0xFF,0xA4,0x8B,
0xFF,0xB3,0x9E,0xFF,0xC2,0xB2,0xFF,0xD0,0xBA,0xFF,0xD7,0xC0,
0x98,0x0C,0x0C,0xA7,0x0D,0x0D,0xAA,0x15,0x10,0xAA,0x15,0x15,
0xD2,0x04,0x00,0xD3,0x08,0x00,0xD5,0x10,0x10,0xD6,0x10,0x30,
0xFB,0x70,0x70,0xFB,0x7E,0x7E,0xFB,0x8F,0x8F,0xFF,0x9F,0x9F,
0xFF,0xAB,0xAB,0xFF,0xB9,0xB9,0xFF,0xC9,0xC9,0xFF,0xCF,0xCF,
0x7E,0x00,0x50,0x80,0x00,0x50,0x80,0x00,0x5F,0x95,0x0B,0x74,
0xAA,0x22,0x88,0xBB,0x2F,0x9A,0xCE,0x3F,0xAD,0xD7,0x5A,0xB6,
0xE4,0x67,0xC3,0xEF,0x72,0xCE,0xFB,0x7E,0xDA,0xFF,0x8D,0xE1,
0xFF,0x9D,0xE5,0xFF,0xA5,0xE7,0xFF,0xAF,0xEA,0xFF,0xB8,0xEC,
0x48,0x00,0x6C,0x5C,0x04,0x88,0x65,0x0D,0x90,0x7B,0x23,0xA7,
0x93,0x3B,0xBF,0x9D,0x45,0xC9,0xA7,0x4F,0xD3,0xB2,0x5A,0xDE,
0xBD,0x65,0xE9,0xC5,0x6D,0xF1,0xCE,0x76,0xFA,0xD5,0x83,0xFF,
0xDA,0x90,0xFF,0xDE,0x9C,0xFF,0xE2,0xA9,0xFF,0xE6,0xB6,0xFF,
0x1B,0x00,0x70,0x22,0x1B,0x8D,0x37,0x30,0xA2,0x48,0x41,0xB3,
0x59,0x52,0xC4,0x63,0x5C,0xCE,0x6F,0x68,0xDA,0x7D,0x76,0xE8,
0x87,0x80,0xF8,0x93,0x8C,0xFF,0x9D,0x97,0xFF,0xA8,0xA3,0xFF,
0xB3,0xAF,0xFF,0xBC,0xB8,0xFF,0xC4,0xC1,0xFF,0xDA,0xD1,0xFF,
0x00,0x0D,0x7F,0x00,0x12,0xA7,0x00,0x18,0xC0,0x0A,0x2B,0xD1,
0x1B,0x4A,0xE3,0x2F,0x58,0xF0,0x37,0x68,0xFF,0x49,0x79,0xFF,
0x5B,0x85,0xFF,0x6D,0x96,0xFF,0x7F,0xA3,0xFF,0x8C,0xAD,0xFF,
0x96,0xB4,0xFF,0xA8,0xC0,0xFF,0xB7,0xCB,0xFF,0xC6,0xD6,0xFF,
0x00,0x29,0x5A,0x00,0x38,0x76,0x00,0x48,0x92,0x00,0x5C,0xAC,
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
0x45,0x8C,0x11,0x5A,0xA5,0x13,0x1B,0xD2,0x09,0x1F,0xDD,0x00,
0x3D,0xCD,0x2D,0x3D,0xCD,0x30,0x58,0xCC,0x40,0x60,0xD3,0x50,
0xA2,0xEC,0x55,0xB3,0xF2,0x4A,0xBB,0xF6,0x5D,0xC4,0xF8,0x70,
0x2E,0x3F,0x0C,0x36,0x4A,0x0F,0x40,0x56,0x15,0x46,0x5F,0x17,
0x57,0x77,0x1A,0x65,0x85,0x1C,0x74,0x93,0x1D,0x8F,0xA5,0x25,
0xAD,0xB7,0x2C,0xBC,0xC7,0x30,0xC9,0xD5,0x33,0xD4,0xE0,0x3B,
0xE0,0xEC,0x42,0xEA,0xF6,0x45,0xF0,0xFD,0x47,0xF4,0xFF,0x6F,
0x5A,0x24,0x00,0x55,0x24,0x00,0x64,0x2D,0x06,0x92,0x55,0x2B,
0x9F,0x66,0x20,0xBB,0x85,0x00,0xC1,0xA1,0x20,0xD0,0xB0,0x2F,
0xDE,0xBE,0x3F,0xE6,0xC6,0x45,0xED,0xCD,0x57,0xF5,0xDB,0x62,
0xFB,0xE5,0x69,0xFC,0xEE,0x6F,0xFD,0xF3,0x77,0xFD,0xF3,0x7F,
0x5C,0x27,0x00,0x5C,0x27,0x00,0x75,0x2D,0x06,0x92,0x48,0x08,
0x92,0x50,0x18,0xBB,0x72,0x20,0xC5,0x86,0x29,0xD7,0x96,0x33,
0xE6,0xA4,0x40,0xF4,0xB1,0x4B,0xFD,0xC1,0x58,0xFF,0xCC,0x55,
0xFF,0xD4,0x61,0xFF,0xDD,0x69,0xFF,0xE6,0x79,0xFF,0xEA,0x98
};
#endif
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
#if 0
bool palette_Load(char * filename) {
#if 0
if(strlen(filename ) == 0) {
logger_LogError("Palette filename is invalid.", PALETTE_SOURCE);
return false;
}
logger_LogInfo("Opening palette file " + filename + ".");
#endif
FILE* file = fopen(filename.c_str( ), "rb");
if(file == NULL) {
logger_LogError("Failed to open the palette file " + filename + " for reading.", PALETTE_SOURCE);
return false;
}
if(fread(palette_data, 1, PALETTE_SIZE, file) != PALETTE_SIZE) {
fclose(file);
logger_LogError("Failed to read the palette data.", PALETTE_SOURCE);
return false;
}
fclose(file);
palette_filename = filename;
return true;
}
#endif
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
void palette_Load(const byte* data) {
u16 index;
uint index;
for(index = 0; index < PALETTE_SIZE; index++) {
palette_data[index] = data[index];
}
for(index = 0; index < 256; index++) {
word r = palette_data[(index * 3) + 0];
word g = palette_data[(index * 3) + 1];
word b = palette_data[(index * 3) + 2];
BG_PALETTE[index] = RGB8(r, g, b);
}
}

View file

@ -27,11 +27,15 @@
#define PALETTE_SIZE 768
#include <string.h>
#include "Logger.h"
#include "shared.h"
//extern bool palette_Load(char *filename);
extern void palette_Load(const byte* data);
extern char *palette_filename;
extern byte palette_data[PALETTE_SIZE];
extern bool palette_default;
#endif

View file

@ -40,8 +40,6 @@
// ----------------------------------------------------------------------------
#include <stdlib.h>
#include "Pokey.h"
#include "ProSystem.h"
#define POKEY_NOTPOLY5 0x80
#define POKEY_POLY4 0x40
#define POKEY_PURE 0x20
@ -67,68 +65,35 @@
#define POKEY_CHANNEL4 3
#define POKEY_SAMPLE 4
#define SK_RESET 0x03
extern byte TIA_POLY4[];
extern byte TIA_POLY5[];
u32 pokeyBufIdx __attribute__((section(".dtcm"))) = 0;
byte pokey_buffer[POKEY_BUFFER_SIZE] = {0};
uint pokey_size = 524;
static uint pokey_frequency = 1787520;
static uint pokey_sampleRate = (31440/2);
static uint pokey_audf[4];
static uint pokey_audc[4];
static uint pokey_audctl __attribute__((section(".dtcm")));
static uint pokey_sampleRate = 31440;
static uint pokey_soundCntr = 0;
static byte pokey_audf[4];
static byte pokey_audc[4];
static byte pokey_audctl;
static byte pokey_output[4];
static byte pokey_outVol[4];
#define pokey_poly04 TIA_POLY4
#define pokey_poly05 TIA_POLY5
static byte pokey_poly04[POKEY_POLY4_SIZE] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
static byte pokey_poly05[POKEY_POLY5_SIZE] = {0,0,1,1,0,0,0,1,1,1,1,0,0,1,0,1,0,1,1,0,1,1,1,0,1,0,0,0,0,0,1};
static byte pokey_poly17[POKEY_POLY17_SIZE];
static uint pokey_poly17Size;
static uint pokey_polyAdjust __attribute__((section(".dtcm")));
static uint pokey_poly04Cntr __attribute__((section(".dtcm")));
static uint pokey_poly05Cntr __attribute__((section(".dtcm")));
static uint pokey_poly17Cntr __attribute__((section(".dtcm")));
static uint pokey_polyAdjust;
static uint pokey_poly04Cntr;
static uint pokey_poly05Cntr;
static uint pokey_poly17Cntr;
static uint pokey_divideMax[4];
static uint pokey_divideCount[4];
static uint pokey_sampleMax __attribute__((section(".dtcm")));
static uint pokey_sampleMax;
static uint pokey_sampleCount[2];
static uint pokey_baseMultiplier;
static byte rand9[0x1ff];
static byte rand17[0x1ffff];
static uint r9;
static uint r17;
static byte SKCTL;
byte POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228};
static int pot_scanline;
uint32 random_scanline_counter __attribute__((section(".dtcm")));
uint32 prev_random_scanline_counter __attribute__((section(".dtcm")));
static void rand_init(byte *rng, int size, int left, int right, int add)
{
int mask = (1 << size) - 1;
int i, x = 0;
for( i = 0; i < mask; i++ )
{
if (size == 17)
*rng = x >> 6; /* use bits 6..13 */
else
*rng = x; /* use bits 0..7 */
rng++;
/* calculate next bit */
x = ((x << left) + (x >> right) + add) & mask;
}
}
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void pokey_Reset( )
{
void pokey_Reset( ) {
uint index, channel;
for(index = 0; index < POKEY_POLY17_SIZE; index++) {
pokey_poly17[index] = rand( ) & 1;
@ -154,87 +119,18 @@ void pokey_Reset( )
pokey_audf[channel] = 0;
}
for(int i = 0; i < 8; i++) {
POT_input[i] = 228;
}
pokey_audctl = 0;
pokey_baseMultiplier = POKEY_DIV_64;
/* initialize the random arrays */
rand_init(rand9, 9, 8, 1, 0x00180);
rand_init(rand17, 17,16, 1, 0x1c000);
SKCTL = SK_RESET;
r9 = 0;
r17 = 0;
random_scanline_counter = 0;
prev_random_scanline_counter = 0;
pokeyBufIdx=0;
}
byte pokey_GetRegister(word address)
{
byte data = 0;
if (address == POKEY_RANDOM)
{
uint32 curr_scanline_counter = ( random_scanline_counter + prosystem_cycles );
if( SKCTL & SK_RESET )
{
uint32 adjust = ( ( curr_scanline_counter - prev_random_scanline_counter ) >> 2 );
r9 = (uint)((adjust + r9) % 0x001ff);
r17 = (uint)((adjust + r17) % 0x1ffff);
}
else
{
r9 = 0;
r17 = 0;
}
byte RANDOM;
if( pokey_audctl & POKEY_POLY9 )
{
RANDOM = rand9[r9];
}
else
{
RANDOM = rand17[r17];
}
prev_random_scanline_counter = curr_scanline_counter;
RANDOM = RANDOM ^ 0xff;
data = RANDOM;
}
return data;
}
// ----------------------------------------------------------------------------
// SetRegister
// ----------------------------------------------------------------------------
ITCM_CODE void pokey_SetRegister(word address, byte value) {
uint channelMask;
void pokey_SetRegister(word address, byte value) {
byte channelMask;
uint channel;
switch(address) {
case POKEY_POTGO:
if (!(SKCTL & 4))
pot_scanline = 0; /* slow pot mode */
return;
case POKEY_SKCTLS:
SKCTL = value;
if (value & 4)
pot_scanline = 228; /* fast pot mode - return results immediately */
return;
case POKEY_AUDF1:
pokey_audf[POKEY_CHANNEL1] = value;
channelMask = 1 << POKEY_CHANNEL1;
@ -304,8 +200,6 @@ ITCM_CODE void pokey_SetRegister(word address, byte value) {
break;
}
if (!channelMask) return;
uint newValue = 0;
if(channelMask & (1 << POKEY_CHANNEL1)) {
@ -397,174 +291,90 @@ static inline uint loc_get_int(byte *p)
static inline void loc_set_byte(byte *p, uint v)
{
*((u32 *)p) = v;
u32 *zz = (u32 *)p;
*zz = v;
}
extern u32 tiaBufIdx;
// ----------------------------------------------------------------------------
// Process
// ----------------------------------------------------------------------------
ITCM_CODE void pokey_Process(void)
void pokey_Process(uint length)
{
if (tia_wait) return;
byte* buffer = pokey_buffer + pokey_soundCntr;
byte* sampleCntrPtrB = ((byte*)&pokey_sampleCount[0]) + 1;
uint size = length;
byte* sampleCntrPtrB = ((byte*)&pokey_sampleCount[0]) + 1;
while(length)
{
byte currentValue;
byte nextEvent = POKEY_SAMPLE;
uint eventMin = loc_get_int(sampleCntrPtrB);
byte channel;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
if(pokey_divideCount[channel] <= eventMin) {
eventMin = pokey_divideCount[channel];
nextEvent = channel;
}
}
while (1)
{
int currentValue;
uint nextEvent = POKEY_SAMPLE;
uint eventMin = loc_get_int(sampleCntrPtrB);
byte channel;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
if(pokey_divideCount[channel] <= eventMin) {
eventMin = pokey_divideCount[channel];
nextEvent = channel;
}
}
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
pokey_divideCount[channel] -= eventMin;
}
uint new_value = loc_get_int(sampleCntrPtrB) - eventMin;
loc_set_byte(sampleCntrPtrB, new_value);
pokey_polyAdjust += eventMin;
if(nextEvent != POKEY_SAMPLE)
{
pokey_poly04Cntr = (pokey_poly04Cntr + pokey_polyAdjust) % POKEY_POLY4_SIZE;
pokey_poly05Cntr = (pokey_poly05Cntr + pokey_polyAdjust) % POKEY_POLY5_SIZE;
pokey_poly17Cntr = (pokey_poly17Cntr + pokey_polyAdjust) % pokey_poly17Size;
pokey_polyAdjust = 0;
pokey_divideCount[nextEvent] += pokey_divideMax[nextEvent];
if((pokey_audc[nextEvent] & POKEY_NOTPOLY5) || pokey_poly05[pokey_poly05Cntr]) {
if(pokey_audc[nextEvent] & POKEY_PURE) {
pokey_output[nextEvent] = !pokey_output[nextEvent];
}
else if (pokey_audc[nextEvent] & POKEY_POLY4) {
pokey_output[nextEvent] = pokey_poly04[pokey_poly04Cntr];
}
else {
pokey_output[nextEvent] = pokey_poly17[pokey_poly17Cntr];
}
}
if(pokey_output[nextEvent]) {
pokey_outVol[nextEvent] = pokey_audc[nextEvent] & POKEY_VOLUME_MASK;
}
else {
pokey_outVol[nextEvent] = 0;
}
}
else
{
*pokey_sampleCount += pokey_sampleMax;
currentValue = 0;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++)
{
currentValue += pokey_outVol[channel];
}
extern int TIA_Sample(void);
currentValue = (currentValue << 2) + 8;
currentValue += TIA_Sample();
//currentValue = (currentValue >> 1);
if (currentValue > 127) {currentValue = 127;} // Clip
// We have filled the buffer... let the buffer drain a bit
if (((tiaBufIdx+1) & (SNDLENGTH-1)) == myTiaBufIdx)
{
tia_wait = (SNDLENGTH >> 2);
}
else
{
tia_buffer[tiaBufIdx++] = (u16)((currentValue<<8) | currentValue);
tiaBufIdx &= (SNDLENGTH-1);
}
return;
}
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
pokey_divideCount[channel] -= eventMin;
}
}
uint new_value = loc_get_int(sampleCntrPtrB) - eventMin;
loc_set_byte(sampleCntrPtrB, new_value);
u16 pokey_ProcessNow(void)
{
byte* sampleCntrPtrB = ((byte*)&pokey_sampleCount[0]) + 1;
pokey_polyAdjust += eventMin;
while (1)
if(nextEvent != POKEY_SAMPLE)
{
int currentValue;
uint nextEvent = POKEY_SAMPLE;
uint eventMin = loc_get_int(sampleCntrPtrB);
pokey_poly04Cntr = (pokey_poly04Cntr + pokey_polyAdjust) % POKEY_POLY4_SIZE;
pokey_poly05Cntr = (pokey_poly05Cntr + pokey_polyAdjust) % POKEY_POLY5_SIZE;
pokey_poly17Cntr = (pokey_poly17Cntr + pokey_polyAdjust) % pokey_poly17Size;
pokey_polyAdjust = 0;
pokey_divideCount[nextEvent] += pokey_divideMax[nextEvent];
byte channel;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
if(pokey_divideCount[channel] <= eventMin) {
eventMin = pokey_divideCount[channel];
nextEvent = channel;
}
if((pokey_audc[nextEvent] & POKEY_NOTPOLY5) || pokey_poly05[pokey_poly05Cntr]) {
if(pokey_audc[nextEvent] & POKEY_PURE) {
pokey_output[nextEvent] = !pokey_output[nextEvent];
}
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) {
pokey_divideCount[channel] -= eventMin;
else if (pokey_audc[nextEvent] & POKEY_POLY4) {
pokey_output[nextEvent] = pokey_poly04[pokey_poly04Cntr];
}
uint new_value = loc_get_int(sampleCntrPtrB) - eventMin;
loc_set_byte(sampleCntrPtrB, new_value);
pokey_polyAdjust += eventMin;
if(nextEvent != POKEY_SAMPLE)
{
pokey_poly04Cntr = (pokey_poly04Cntr + pokey_polyAdjust) % POKEY_POLY4_SIZE;
pokey_poly05Cntr = (pokey_poly05Cntr + pokey_polyAdjust) % POKEY_POLY5_SIZE;
pokey_poly17Cntr = (pokey_poly17Cntr + pokey_polyAdjust) % pokey_poly17Size;
pokey_polyAdjust = 0;
pokey_divideCount[nextEvent] += pokey_divideMax[nextEvent];
if((pokey_audc[nextEvent] & POKEY_NOTPOLY5) || pokey_poly05[pokey_poly05Cntr]) {
if(pokey_audc[nextEvent] & POKEY_PURE) {
pokey_output[nextEvent] = !pokey_output[nextEvent];
}
else if (pokey_audc[nextEvent] & POKEY_POLY4) {
pokey_output[nextEvent] = pokey_poly04[pokey_poly04Cntr];
}
else {
pokey_output[nextEvent] = pokey_poly17[pokey_poly17Cntr];
}
}
if(pokey_output[nextEvent]) {
pokey_outVol[nextEvent] = pokey_audc[nextEvent] & POKEY_VOLUME_MASK;
}
else {
pokey_outVol[nextEvent] = 0;
}
else {
pokey_output[nextEvent] = pokey_poly17[pokey_poly17Cntr];
}
else
{
*pokey_sampleCount += pokey_sampleMax;
currentValue = 0;
}
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++)
{
currentValue += pokey_outVol[channel];
}
extern int TIA_Sample(void);
currentValue = (currentValue << 2) + 8;
currentValue += TIA_Sample();
//currentValue = (currentValue >> 1);
if (currentValue > 127) {currentValue = 127;} // Clip
return (u16)((currentValue << 8) | currentValue);
}
if(pokey_output[nextEvent]) {
pokey_outVol[nextEvent] = pokey_audc[nextEvent] & POKEY_VOLUME_MASK;
}
else {
pokey_outVol[nextEvent] = 0;
}
}
else
{
*pokey_sampleCount += pokey_sampleMax;
currentValue = 0;
for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++)
{
currentValue += pokey_outVol[channel];
}
currentValue = (currentValue << 2) + 8;
*buffer++ = currentValue;
length--;
}
}
pokey_soundCntr += size;
if(pokey_soundCntr >= pokey_size)
{
pokey_soundCntr = 0;
}
}
// ----------------------------------------------------------------------------
@ -572,9 +382,8 @@ u16 pokey_ProcessNow(void)
// ----------------------------------------------------------------------------
void pokey_Clear( ) {
uint index;
for(index = 0; index < SNDLENGTH; index++) {
tia_buffer[index] = 0;
pokeyBufIdx=0;
for(index = 0; index < POKEY_BUFFER_SIZE; index++) {
pokey_buffer[index] = 0;
}
}

View file

@ -40,6 +40,7 @@
// ----------------------------------------------------------------------------
#ifndef POKEY_H
#define POKEY_H
#define POKEY_BUFFER_SIZE 624
#define POKEY_AUDF1 0x4000
#define POKEY_AUDC1 0x4001
#define POKEY_AUDF2 0x4002
@ -49,44 +50,15 @@
#define POKEY_AUDF4 0x4006
#define POKEY_AUDC4 0x4007
#define POKEY_AUDCTL 0x4008
#define POKEY_STIMER 0x4009
#define POKEY_SKRES 0x400a
#define POKEY_POTGO 0x400b
#define POKEY_SEROUT 0x400d
#define POKEY_IRQEN 0x400e
#define POKEY_SKCTLS 0x400f
#define POKEY_POT0 0x4000
#define POKEY_POT1 0x4001
#define POKEY_POT2 0x4002
#define POKEY_POT3 0x4003
#define POKEY_POT4 0x4004
#define POKEY_POT5 0x4005
#define POKEY_POT6 0x4006
#define POKEY_POT7 0x4007
#define POKEY_ALLPOT 0x4008
#define POKEY_KBCODE 0x4009
#define POKEY_RANDOM 0x400a
#define POKEY_SERIN 0x400d
#define POKEY_IRQST 0x400e
#define POKEY_SKSTAT 0x400f
#include "shared.h"
#define CYCLES_PER_SCANLINE 454
extern void pokey_Reset( );
extern void pokey_SetRegister(word address, byte value);
extern byte pokey_GetRegister(word address);
extern void pokey_Process(void);
extern u16 pokey_ProcessNow(void);
extern void pokey_Process(uint length);
extern void pokey_Clear( );
extern uint32 random_scanline_counter;
/* Called prior to each scanline */
inline void pokey_Scanline()
{
random_scanline_counter += CYCLES_PER_SCANLINE;
}
extern byte pokey_buffer[POKEY_BUFFER_SIZE];
extern uint pokey_size;
#endif

View file

@ -23,168 +23,357 @@
// ProSystem.cpp
// ----------------------------------------------------------------------------
#include <malloc.h>
#include "ProSystem.h"
#include "Database.h"
#include "Sound.h"
#define PRO_SYSTEM_SOURCE "ProSystem.cpp"
#define PRO_SYSTEM_STATE_HEADER "PRO-SYSTEM STATE"
extern u8 isDS_LITE;
extern u8 frameSkipMask;
#define CYCLES_PER_SCANLINE 454
uint prosystem_cycles __attribute__((section(".dtcm"))) = 0;
uint32 bg32 __attribute__((section(".dtcm"))) = 0;
uint bRenderFrame __attribute__((section(".dtcm"))) = 0;
#define CYCLES_BEFORE_DMA 28 // Number of cycles before DMA kicks in (really 7 CPU cycles)
#define CYCLES_PER_SCANLINE 454 // 454 Cycles per Scanline in an NTSC system (really 113.5 CPU cycles)
bool prosystem_active = false;
bool prosystem_paused = false;
word prosystem_frequency = 60;
word prosystem_scanlines = 262;
uint prosystem_cycles = 0;
// Whether the last CPU operation resulted in a half cycle (need to take it
// into consideration)
extern bool half_cycle;
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void prosystem_Reset()
{
if(cartridge_IsLoaded())
{
sally_Reset();
region_Reset();
tia_Clear();
tia_Reset();
pokey_Clear();
pokey_Reset();
memory_Reset();
maria_Clear();
maria_Reset();
riot_Reset();
cartridge_LoadHighScoreCart();
void prosystem_Reset( ) {
if(cartridge_IsLoaded( )) {
prosystem_paused = false;
cartridge_Store(); // Always call this - it may setup some RAM or other stuff below the BIOS region...
sally_Reset( ); // WII
// Load 7800 BIOS if available... otherwise direct load the CART
if(bios_available && !bSkipBIOS)
{
bios_Store();
bios_show_counter = myCartInfo.biosTimeout;
}
prosystem_cycles = sally_ExecuteRES();
region_Reset( );
tia_Clear( );
tia_Reset( );
pokey_Clear( );
pokey_Reset( );
memory_Reset( );
maria_Clear( );
maria_Reset( );
riot_Reset ( );
if(bios_enabled) {
bios_Store( );
}
else {
cartridge_Store( );
}
cartridge_LoadHighScoreCart();
prosystem_cycles = sally_ExecuteRES( );
prosystem_active = true;
}
}
uint32 bg32 = 0;
// ----------------------------------------------------------------------------
// ExecuteFrame
// ----------------------------------------------------------------------------
ITCM_CODE void prosystem_ExecuteFrame(const byte* input)
{
static byte last_background = 254;
extern int gTotalAtariFrames;
extern word *framePtr;
bool bRenderScanline = false;
gTotalAtariFrames++;
riot_SetInput(input);
for(maria_scanline = 1; maria_scanline <= prosystem_scanlines; maria_scanline++)
{
if(maria_scanline == maria_displayArea.top)
{
memory_ram[MSTAT] = 0;
framePtr = (word*)(maria_surface + ((maria_scanline - maria_displayArea.top) * 256));
bRenderScanline = true;
}
else if(maria_scanline == maria_displayArea.bottom)
{
memory_ram[MSTAT] = 128;
bRenderScanline = false;
}
uint cycles=0;
prosystem_cycles %= CYCLES_PER_SCANLINE;
sally_Execute(34);
if (bRenderScanline)
{
// If our background has changed... set our global 32-bit version of that now... speeds up scanline renders
if (memory_ram[BACKGRND] != last_background)
{
bg32 = memory_ram[BACKGRND] | (memory_ram[BACKGRND] << 8) | (memory_ram[BACKGRND]<<16) | (memory_ram[BACKGRND]<<24);
last_background = memory_ram[BACKGRND];
}
cycles = maria_RenderScanline( );
}
if(cartridge_cycle_stealing)
{
prosystem_cycles += cycles;
if(riot_timing) riot_UpdateTimer( cycles >> 2 );
}
sally_Execute(CYCLES_PER_SCANLINE);
tia_Process(2);
if(cartridge_pokey) pokey_Process(2);
}
}
byte *loc_buffer = 0;
// ----------------------------------------------------------------------------
// ExecuteFrame - this is hand-tuned for NTSC output with hard-coded
// NTSC frame values ... this will not work properly if a PAL ROM is used.
// Save
// ----------------------------------------------------------------------------
ITCM_CODE void prosystem_ExecuteFrame(const byte * input)
bool prosystem_Save(char * filename, bool compress)
{
extern u16 gTotalAtariFrames;
extern word * framePtr;
extern uint maria_cycles;
gTotalAtariFrames++;
bRenderFrame = 0;
if(strlen(filename) == 0) {
#if 0
logger_LogError("Filename is invalid.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
riot_SetInput(input);
if (! loc_buffer) loc_buffer = (byte *)malloc(33000 * sizeof(byte));
// ---------------------------------------------------------------------
// Handle the VERTICAL BLANK area first... speeds up processing below...
// ---------------------------------------------------------------------
memory_ram[MSTAT] = 128; // Into the Vertical Blank...
#if 0
logger_LogInfo("Saving game state to file " + filename + ".");
#endif
uint size = 0;
uint index;
for(index = 0; index < 16; index++) {
loc_buffer[size + index] = PRO_SYSTEM_STATE_HEADER[index];
}
size += 16;
loc_buffer[size++] = 1;
for(index = 0; index < 4; index++) {
loc_buffer[size + index] = 0;
}
size += 4;
// -------------------------------------------------------------------------------------------
// Note: this is not accurate. It should be 263 scanlines total but it doesn't work for all
// games at 263 so we've gone with 262 for maximum compatibility. This is likely due to some
// emulation cycle counting inaccuracies. At 263, some games run too fast (Asteroids, Deluxe)
// and some crash (Robotron) and some issues with Pole Position II and the joystick selection
// of a course to play. I've also seen graphical glitches in Crossbow when loaded via the
// BIOS and all kinds of graphical oddities in Xenophobe. Be very careful if you change this...
// be sure you understand the consequences (and this developer doesn't... so be warned!).
// -------------------------------------------------------------------------------------------
for(maria_scanline = 1; maria_scanline <= 21; maria_scanline++)
{
prosystem_cycles = 0;
for(index = 0; index < 32; index++) {
loc_buffer[size + index] = cartridge_digest[index];
}
size += 32;
if(maria_scanline == 21) // Maria can start to do her thing... We've had 20 VBLANK scanlines
{
memory_ram[MSTAT] = 0; // Out of the vertical blank
framePtr = (word * )(maria_surface);
sally_Execute(CYCLES_BEFORE_DMA);
loc_buffer[size++] = sally_a;
loc_buffer[size++] = sally_x;
loc_buffer[size++] = sally_y;
loc_buffer[size++] = sally_p;
loc_buffer[size++] = sally_s;
loc_buffer[size++] = sally_pc.b.l;
loc_buffer[size++] = sally_pc.b.h;
loc_buffer[size++] = cartridge_bank;
maria_RenderScanlineTOP();
for(index = 0; index < 16384; index++) {
loc_buffer[size + index] = memory_ram[index];
}
size += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
for(index = 0; index < 16384; index++) {
loc_buffer[size + index] = memory_ram[16384 + index];
}
size += 16384;
}
if(!compress) {
FILE* file = fopen(filename, "wb");
if(file == NULL) {
#if 0
logger_LogError("Failed to open the file " + filename + " for writing.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
if(fwrite(loc_buffer, 1, size, file) != size) {
fclose(file);
#if 0
logger_LogError("Failed to write the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
#endif
return false;
}
fclose(file);
}
else {
if(!archive_Compress(filename, "Save.sav", loc_buffer, size)) {
#if 0
logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE);
#endif
return false;
}
}
return true;
}
// Cycle Stealing happens here...
prosystem_cycles += ((maria_cycles + 3) >> 2) << 2; // Always a multiple of 4
if(riot_and_wsync & 2) riot_UpdateTimer(maria_cycles >> 2);
}
else
{
sally_Execute(CYCLES_BEFORE_DMA);
}
// ----------------------------------------------------------------------------
// Load
// ----------------------------------------------------------------------------
bool prosystem_Load(char * filename) {
sally_Execute(CYCLES_PER_SCANLINE);
if(strlen(filename) == 0) {
#if 0
logger_LogError("Filename is invalid.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
if(myCartInfo.pokeyType) // If pokey enabled, we process 1 pokey sample and 1 TIA sample. Good enough.
{
pokey_Process();
pokey_Scanline();
}
else tia_Process(); // If all we have to deal with is the TIA, we can do so at 31KHz
if (! loc_buffer) loc_buffer = (byte *)malloc(33000 * sizeof(byte));
#if 0
logger_LogInfo("Loading game state from file " + filename + ".");
#endif
uint size = archive_GetUncompressedFileSize(filename);
if(size == 0) {
FILE* file = fopen(filename, "rb");
if(file == NULL) {
#if 0
logger_LogError("Failed to open the file " + filename + " for reading.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
// ------------------------------------------------------------
// Now handle the Main display area...
// ------------------------------------------------------------
for(; maria_scanline < 263; maria_scanline++)
{
prosystem_cycles = 0;
if(maria_scanline >= 30)
{
// --------------------------------------------------------------------------
// We can start to render the scanlines if we are not skipping this frame.
// The DS/DSi only has 192 vertical pixels and we can perform some hardware
// scaling but there is a point at which we really can't show any more lines.
// To that end, we'll render ~223 lines which is good enough for most games.
// If a game uses more overscan area - those scanlines won't show on screen.
// ---------------------------------------------------------------------------
if(maria_scanline >= 253)
{
bRenderFrame = 0; // We can stop rendering frames... DS can't show it anyway with limited vertical resolution.
}
else
{
bRenderFrame = gTotalAtariFrames & frameSkipMask;
}
}
sally_Execute(CYCLES_BEFORE_DMA);
maria_RenderScanline();
// Cycle Stealing happens here...
prosystem_cycles += ((maria_cycles + 3) >> 2) << 2; // Always a multiple of 4
if(riot_and_wsync & 2) riot_UpdateTimer(maria_cycles >> 2);
sally_Execute(CYCLES_PER_SCANLINE);
if(myCartInfo.pokeyType) // If pokey enabled, we process 1 pokey sample and 1 TIA sample. Good enough.
{
pokey_Process();
pokey_Scanline();
}
else tia_Process(); // If all we have to deal with is the TIA, we can do so at 31KHz
fseek(file, 0, SEEK_END);
#if 0
if(fseek(file, 0, SEEK_END)) {
fclose(file);
logger_LogError("Failed to find the end of the file.", PRO_SYSTEM_SOURCE);
return false;
}
#endif
size = ftell(file);
fseek(file, 0, SEEK_SET);
#if 0
if(fseek(file, 0, SEEK_SET)) {
fclose(file);
logger_LogError("Failed to find the size of the file.", PRO_SYSTEM_SOURCE);
return false;
}
#endif
if(size != 16445 && size != 32829) {
fclose(file);
#if 0
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
fread(loc_buffer, 1, size, file);
#if 0
if(fread(loc_buffer, 1, size, file) != size && ferror(file)) {
fclose(file);
logger_LogError("Failed to read the file data.", PRO_SYSTEM_SOURCE);
return false;
}
#endif
fclose(file);
}
else if(size == 16445 || size == 32829) {
archive_Uncompress(filename, loc_buffer, size);
}
else {
#if 0
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
uint offset = 0;
uint index;
for(index = 0; index < 16; index++) {
if(loc_buffer[offset + index] != PRO_SYSTEM_STATE_HEADER[index]) {
#if 0
logger_LogError("File is not a valid ProSystem save state.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
}
offset += 16;
for(index = 0; index < 4; index++) {
}
offset += 4;
prosystem_Reset( );
char digest[33] = {0};
for(index = 0; index < 32; index++) {
digest[index] = loc_buffer[offset + index];
}
offset += 32;
if (strcmp((const char*)cartridge_digest,digest)) {
//if(cartridge_digest != std::string(digest)) {
#if 0
logger_LogError("Load state digest [" + std::string(digest) + "] does not match loaded cartridge digest [" + cartridge_digest + "].", PRO_SYSTEM_SOURCE);
#endif
return false;
}
sally_a = loc_buffer[offset++];
sally_x = loc_buffer[offset++];
sally_y = loc_buffer[offset++];
sally_p = loc_buffer[offset++];
sally_s = loc_buffer[offset++];
sally_pc.b.l = loc_buffer[offset++];
sally_pc.b.h = loc_buffer[offset++];
cartridge_StoreBank(loc_buffer[offset++]);
for(index = 0; index < 16384; index++) {
memory_ram[index] = loc_buffer[offset + index];
}
offset += 16384;
if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) {
if(size != 32829) {
#if 0
logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE);
#endif
return false;
}
for(index = 0; index < 16384; index++) {
memory_ram[16384 + index] = loc_buffer[offset + index];
}
offset += 16384;
}
return true;
}
// ----------------------------------------------------------------------------
// Pause
// ----------------------------------------------------------------------------
void prosystem_Pause(bool pause) {
if(prosystem_active) {
prosystem_paused = pause;
}
}
// ----------------------------------------------------------------------------
// Close
// ----------------------------------------------------------------------------
void prosystem_Close()
{
cartridge_Release();
maria_Reset();
maria_Clear();
memory_Reset();
tia_Reset();
tia_Clear();
void prosystem_Close( ) {
prosystem_active = false;
prosystem_paused = false;
cartridge_Release( );
maria_Reset( );
maria_Clear( );
memory_Reset( );
tia_Reset( );
tia_Clear( );
}

View file

@ -28,37 +28,35 @@
#include <string.h>
#include <stdio.h>
#include "Equates.h"
#include "Bios.h"
#include "Cartridge.h"
#include "HighScore.h"
#include "Maria.h"
#include "Memory.h"
#include "Region.h"
#include "Riot.h"
#include "Sally.h"
#include "Archive.h"
#include "Tia.h"
#include "Pokey.h"
#include "shared.h"
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define RAM_MIRRORS_ENABLED 1 // Uncomment if you want to have RAM mirrors handled (slower and no games need it as of this writing)
extern int debug[];
extern u8 isDS_LITE;
extern u8 bSkipBIOS;
// Difficulty switches...
#define DIFF_A 0
#define DIFF_B 1
// The number of cycles per scan line
#define CYCLES_PER_SCANLINE 454
extern void prosystem_Reset( );
extern void prosystem_ExecuteFrame(const byte* input);
extern bool prosystem_Save(char* filename, bool compress);
extern bool prosystem_Load(char* filename);
extern void prosystem_Pause(bool pause);
extern void prosystem_Close( );
extern bool prosystem_active;
extern bool prosystem_paused;
extern word prosystem_frequency;
extern byte prosystem_frame;
extern word prosystem_scanlines;
extern uint prosystem_cycles;
extern void Trace(word data);
extern void Trace2(word addr, u8 data);
#endif

55
arm9/source/emu/Rect.h Normal file
View file

@ -0,0 +1,55 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Rect.h
// ----------------------------------------------------------------------------
#ifndef RECT_H
#define RECT_H
typedef struct {
uint left;
uint top;
uint right;
uint bottom;
uint GetArea;
uint GetLength;
uint GetHeight;
/*
uint GetArea( ) {
return GetLength( ) * GetHeight( );
}
uint GetLength( ) {
return (right - left) + 1;
}
uint GetHeight( ) {
return (bottom - top) + 1;
}
*/
} Rect ;
typedef Rect rect;
#endif

View file

@ -20,223 +20,269 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Region.c
// Region.h
// ----------------------------------------------------------------------------
#include "Region.h"
#include "Database.h"
byte region_type = REGION_AUTO;
static const rect REGION_DISPLAY_AREA_NTSC = {0, 16, 319, 258};
static const rect REGION_VISIBLE_AREA_NTSC = {0, 26, 319, 250};
static const byte REGION_FREQUENCY_NTSC = 60;
static const word REGION_SCANLINES_NTSC = 262;
static const rect REGION_DISPLAY_AREA_PAL = {0, 16, 319, 308};
static const rect REGION_VISIBLE_AREA_PAL = {0, 26, 319, 297};
static const byte REGION_FREQUENCY_PAL = 50;
static const word REGION_SCANLINES_PAL = 312;
// ----------------------------------------------------------------------------
// PALETTE NTSC
// ----------------------------------------------------------------------------
const byte REGION_PALETTE_NTSC_CRT_COOL[ ] = {
0x00, 0x00, 0x00, 0x0d, 0x0d, 0x0d, 0x28, 0x28, 0x28, 0x3e, 0x3e, 0x3e,
0x52, 0x52, 0x52, 0x65, 0x65, 0x65, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88,
0x98, 0x98, 0x98, 0xa8, 0xa8, 0xa8, 0xb7, 0xb7, 0xb7, 0xc6, 0xc6, 0xc6,
0xd5, 0xd5, 0xd5, 0xe3, 0xe3, 0xe3, 0xf1, 0xf1, 0xf1, 0xff, 0xff, 0xff,
0x42, 0x28, 0x00, 0x54, 0x3d, 0x00, 0x65, 0x4f, 0x00, 0x75, 0x60, 0x00,
0x84, 0x70, 0x00, 0x93, 0x80, 0x00, 0xa2, 0x8f, 0x00, 0xb0, 0x9d, 0x00,
0xbe, 0xac, 0x00, 0xcb, 0xb9, 0x00, 0xd8, 0xc7, 0x00, 0xe5, 0xd4, 0x1a,
0xf2, 0xe1, 0x30, 0xfe, 0xee, 0x43, 0xff, 0xfb, 0x55, 0xff, 0xff, 0x66,
0x6c, 0x0f, 0x00, 0x7b, 0x28, 0x00, 0x8a, 0x3c, 0x00, 0x99, 0x4e, 0x00,
0xa7, 0x60, 0x00, 0xb5, 0x70, 0x00, 0xc3, 0x7f, 0x00, 0xd0, 0x8e, 0x00,
0xdd, 0x9d, 0x00, 0xea, 0xab, 0x1c, 0xf7, 0xb9, 0x32, 0xff, 0xc7, 0x45,
0xff, 0xd4, 0x57, 0xff, 0xe1, 0x68, 0xff, 0xee, 0x78, 0xff, 0xfa, 0x87,
0x84, 0x00, 0x00, 0x93, 0x11, 0x00, 0xa1, 0x29, 0x00, 0xaf, 0x3d, 0x00,
0xbd, 0x4f, 0x00, 0xca, 0x60, 0x18, 0xd7, 0x71, 0x2f, 0xe4, 0x80, 0x42,
0xf1, 0x8f, 0x54, 0xfe, 0x9e, 0x65, 0xff, 0xac, 0x75, 0xff, 0xba, 0x85,
0xff, 0xc7, 0x93, 0xff, 0xd4, 0xa2, 0xff, 0xe1, 0xb0, 0xff, 0xee, 0xbe,
0x89, 0x00, 0x14, 0x98, 0x00, 0x2c, 0xa6, 0x19, 0x40, 0xb4, 0x2f, 0x52,
0xc2, 0x43, 0x63, 0xcf, 0x55, 0x73, 0xdc, 0x65, 0x82, 0xe9, 0x75, 0x91,
0xf6, 0x85, 0xa0, 0xff, 0x94, 0xae, 0xff, 0xa2, 0xbc, 0xff, 0xb0, 0xc9,
0xff, 0xbe, 0xd6, 0xff, 0xcb, 0xe3, 0xff, 0xd8, 0xf0, 0xff, 0xe5, 0xfd,
0x7c, 0x00, 0x71, 0x8c, 0x00, 0x80, 0x9a, 0x11, 0x8f, 0xa8, 0x29, 0x9e,
0xb6, 0x3d, 0xac, 0xc4, 0x4f, 0xba, 0xd1, 0x61, 0xc7, 0xde, 0x71, 0xd5,
0xeb, 0x80, 0xe2, 0xf8, 0x8f, 0xee, 0xff, 0x9e, 0xfb, 0xff, 0xac, 0xff,
0xff, 0xba, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xd5, 0xff, 0xff, 0xe2, 0xff,
0x5d, 0x00, 0xac, 0x6e, 0x00, 0xb9, 0x7e, 0x15, 0xc7, 0x8d, 0x2d, 0xd4,
0x9b, 0x40, 0xe1, 0xa9, 0x52, 0xee, 0xb7, 0x63, 0xfb, 0xc5, 0x73, 0xff,
0xd2, 0x83, 0xff, 0xdf, 0x92, 0xff, 0xec, 0xa0, 0xff, 0xf9, 0xae, 0xff,
0xff, 0xbc, 0xff, 0xff, 0xca, 0xff, 0xff, 0xd7, 0xff, 0xff, 0xe4, 0xff,
0x2d, 0x00, 0xca, 0x41, 0x0a, 0xd7, 0x53, 0x24, 0xe4, 0x64, 0x39, 0xf1,
0x74, 0x4b, 0xfe, 0x83, 0x5d, 0xff, 0x92, 0x6d, 0xff, 0xa1, 0x7d, 0xff,
0xaf, 0x8c, 0xff, 0xbd, 0x9a, 0xff, 0xca, 0xa9, 0xff, 0xd7, 0xb7, 0xff,
0xe4, 0xc4, 0xff, 0xf1, 0xd1, 0xff, 0xfd, 0xdf, 0xff, 0xff, 0xeb, 0xff,
0x00, 0x06, 0xcc, 0x00, 0x21, 0xd9, 0x1c, 0x37, 0xe6, 0x32, 0x49, 0xf2,
0x45, 0x5b, 0xff, 0x57, 0x6b, 0xff, 0x67, 0x7b, 0xff, 0x77, 0x8a, 0xff,
0x87, 0x99, 0xff, 0x95, 0xa7, 0xff, 0xa4, 0xb5, 0xff, 0xb2, 0xc3, 0xff,
0xbf, 0xd0, 0xff, 0xcd, 0xdd, 0xff, 0xda, 0xea, 0xff, 0xe7, 0xf7, 0xff,
0x00, 0x22, 0xb0, 0x00, 0x37, 0xbd, 0x00, 0x4a, 0xcb, 0x00, 0x5b, 0xd8,
0x11, 0x6c, 0xe5, 0x29, 0x7c, 0xf2, 0x3d, 0x8b, 0xfe, 0x4f, 0x99, 0xff,
0x61, 0xa8, 0xff, 0x71, 0xb6, 0xff, 0x80, 0xc3, 0xff, 0x8f, 0xd1, 0xff,
0x9e, 0xde, 0xff, 0xac, 0xea, 0xff, 0xba, 0xf7, 0xff, 0xc7, 0xff, 0xff,
0x00, 0x36, 0x77, 0x00, 0x49, 0x87, 0x00, 0x5b, 0x96, 0x00, 0x6b, 0xa4,
0x00, 0x7b, 0xb2, 0x00, 0x8a, 0xc0, 0x1c, 0x99, 0xcd, 0x32, 0xa7, 0xda,
0x45, 0xb5, 0xe7, 0x57, 0xc3, 0xf4, 0x68, 0xd0, 0xff, 0x78, 0xdd, 0xff,
0x87, 0xea, 0xff, 0x96, 0xf7, 0xff, 0xa4, 0xff, 0xff, 0xb2, 0xff, 0xff,
0x00, 0x44, 0x20, 0x00, 0x55, 0x35, 0x00, 0x66, 0x48, 0x00, 0x76, 0x5a,
0x00, 0x86, 0x6a, 0x00, 0x94, 0x7a, 0x12, 0xa3, 0x89, 0x2a, 0xb1, 0x98,
0x3e, 0xbf, 0xa6, 0x50, 0xcc, 0xb4, 0x61, 0xd9, 0xc2, 0x71, 0xe6, 0xcf,
0x81, 0xf3, 0xdc, 0x90, 0xff, 0xe9, 0x9f, 0xff, 0xf6, 0xad, 0xff, 0xff,
0x00, 0x49, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x7b, 0x00,
0x00, 0x8a, 0x08, 0x0e, 0x99, 0x22, 0x26, 0xa7, 0x37, 0x3b, 0xb5, 0x4a,
0x4d, 0xc3, 0x5b, 0x5f, 0xd0, 0x6c, 0x6f, 0xdd, 0x7c, 0x7f, 0xea, 0x8b,
0x8e, 0xf7, 0x9a, 0x9c, 0xff, 0xa8, 0xaa, 0xff, 0xb6, 0xb8, 0xff, 0xc3,
0x00, 0x46, 0x00, 0x00, 0x58, 0x00, 0x00, 0x68, 0x00, 0x0b, 0x78, 0x00,
0x25, 0x88, 0x00, 0x39, 0x96, 0x00, 0x4c, 0xa5, 0x00, 0x5d, 0xb3, 0x00,
0x6e, 0xc0, 0x08, 0x7d, 0xce, 0x23, 0x8c, 0xdb, 0x38, 0x9b, 0xe8, 0x4a,
0xa9, 0xf5, 0x5c, 0xb7, 0xff, 0x6c, 0xc5, 0xff, 0x7c, 0xd2, 0xff, 0x8b,
0x00, 0x3b, 0x00, 0x1c, 0x4e, 0x00, 0x32, 0x5f, 0x00, 0x45, 0x6f, 0x00,
0x57, 0x7f, 0x00, 0x67, 0x8e, 0x00, 0x77, 0x9c, 0x00, 0x87, 0xab, 0x00,
0x95, 0xb8, 0x00, 0xa4, 0xc6, 0x00, 0xb2, 0xd3, 0x00, 0xbf, 0xe0, 0x1c,
0xcd, 0xed, 0x32, 0xda, 0xfa, 0x45, 0xe7, 0xff, 0x57, 0xf4, 0xff, 0x68,
0x41, 0x29, 0x00, 0x53, 0x3d, 0x00, 0x64, 0x4f, 0x00, 0x74, 0x61, 0x00,
0x83, 0x71, 0x00, 0x92, 0x80, 0x00, 0xa1, 0x8f, 0x00, 0xaf, 0x9e, 0x00,
0xbd, 0xac, 0x00, 0xca, 0xba, 0x00, 0xd7, 0xc7, 0x00, 0xe4, 0xd5, 0x19,
0xf1, 0xe2, 0x30, 0xfd, 0xee, 0x43, 0xff, 0xfb, 0x55, 0xff, 0xff, 0x66
const byte REGION_PALETTE_NTSC[ ] = {
0x00,0x00,0x00,0x25,0x25,0x25,0x34,0x34,0x34,0x4F,0x4F,0x4F,
0x5B,0x5B,0x5B,0x69,0x69,0x69,0x7B,0x7B,0x7B,0x8A,0x8A,0x8A,
0xA7,0xA7,0xA7,0xB9,0xB9,0xB9,0xC5,0xC5,0xC5,0xD0,0xD0,0xD0,
0xD7,0xD7,0xD7,0xE1,0xE1,0xE1,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,
0x4C,0x32,0x00,0x62,0x3A,0x00,0x7B,0x4A,0x00,0x9A,0x60,0x00,
0xB5,0x74,0x00,0xCC,0x85,0x00,0xE7,0x9E,0x08,0xF7,0xAF,0x10,
0xFF,0xC3,0x18,0xFF,0xD0,0x20,0xFF,0xD8,0x28,0xFF,0xDF,0x30,
0xFF,0xE6,0x3B,0xFF,0xF4,0x40,0xFF,0xFA,0x4B,0xFF,0xFF,0x50,
0x99,0x25,0x00,0xAA,0x25,0x00,0xB4,0x25,0x00,0xD3,0x30,0x00,
0xDD,0x48,0x02,0xE2,0x50,0x09,0xF4,0x67,0x00,0xF4,0x75,0x10,
0xFF,0x9E,0x10,0xFF,0xAC,0x20,0xFF,0xBA,0x3A,0xFF,0xBF,0x50,
0xFF,0xC6,0x6D,0xFF,0xD5,0x80,0xFF,0xE4,0x90,0xFF,0xE6,0x99,
0x98,0x0C,0x0C,0x99,0x0C,0x0C,0xC2,0x13,0x00,0xD3,0x13,0x00,
0xE2,0x35,0x00,0xE3,0x40,0x00,0xE4,0x40,0x20,0xE5,0x52,0x30,
0xFD,0x78,0x54,0xFF,0x8A,0x6A,0xFF,0x98,0x7C,0xFF,0xA4,0x8B,
0xFF,0xB3,0x9E,0xFF,0xC2,0xB2,0xFF,0xD0,0xBA,0xFF,0xD7,0xC0,
0x99,0x00,0x00,0xA9,0x00,0x00,0xC2,0x04,0x00,0xD3,0x04,0x00,
0xDA,0x04,0x00,0xDB,0x08,0x00,0xE4,0x20,0x20,0xF6,0x40,0x40,
0xFB,0x70,0x70,0xFB,0x7E,0x7E,0xFB,0x8F,0x8F,0xFF,0x9F,0x9F,
0xFF,0xAB,0xAB,0xFF,0xB9,0xB9,0xFF,0xC9,0xC9,0xFF,0xCF,0xCF,
0x7E,0x00,0x50,0x80,0x00,0x50,0x80,0x00,0x5F,0x95,0x0B,0x74,
0xAA,0x22,0x88,0xBB,0x2F,0x9A,0xCE,0x3F,0xAD,0xD7,0x5A,0xB6,
0xE4,0x67,0xC3,0xEF,0x72,0xCE,0xFB,0x7E,0xDA,0xFF,0x8D,0xE1,
0xFF,0x9D,0xE5,0xFF,0xA5,0xE7,0xFF,0xAF,0xEA,0xFF,0xB8,0xEC,
0x48,0x00,0x6C,0x5C,0x04,0x88,0x65,0x0D,0x90,0x7B,0x23,0xA7,
0x93,0x3B,0xBF,0x9D,0x45,0xC9,0xA7,0x4F,0xD3,0xB2,0x5A,0xDE,
0xBD,0x65,0xE9,0xC5,0x6D,0xF1,0xCE,0x76,0xFA,0xD5,0x83,0xFF,
0xDA,0x90,0xFF,0xDE,0x9C,0xFF,0xE2,0xA9,0xFF,0xE6,0xB6,0xFF,
0x1B,0x00,0x70,0x22,0x1B,0x8D,0x37,0x30,0xA2,0x48,0x41,0xB3,
0x59,0x52,0xC4,0x63,0x5C,0xCE,0x6F,0x68,0xDA,0x7D,0x76,0xE8,
0x87,0x80,0xF8,0x93,0x8C,0xFF,0x9D,0x97,0xFF,0xA8,0xA3,0xFF,
0xB3,0xAF,0xFF,0xBC,0xB8,0xFF,0xC4,0xC1,0xFF,0xDA,0xD1,0xFF,
0x00,0x0D,0x7F,0x00,0x12,0xA7,0x00,0x18,0xC0,0x0A,0x2B,0xD1,
0x1B,0x4A,0xE3,0x2F,0x58,0xF0,0x37,0x68,0xFF,0x49,0x79,0xFF,
0x5B,0x85,0xFF,0x6D,0x96,0xFF,0x7F,0xA3,0xFF,0x8C,0xAD,0xFF,
0x96,0xB4,0xFF,0xA8,0xC0,0xFF,0xB7,0xCB,0xFF,0xC6,0xD6,0xFF,
0x00,0x29,0x5A,0x00,0x38,0x76,0x00,0x48,0x92,0x00,0x5C,0xAC,
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
0x45,0x8C,0x11,0x5A,0xA5,0x13,0x1B,0xD2,0x09,0x1F,0xDD,0x00,
0x3D,0xCD,0x2D,0x3D,0xCD,0x30,0x58,0xCC,0x40,0x60,0xD3,0x50,
0xA2,0xEC,0x55,0xB3,0xF2,0x4A,0xBB,0xF6,0x5D,0xC4,0xF8,0x70,
0x2E,0x3F,0x0C,0x36,0x4A,0x0F,0x40,0x56,0x15,0x46,0x5F,0x17,
0x57,0x77,0x1A,0x65,0x85,0x1C,0x74,0x93,0x1D,0x8F,0xA5,0x25,
0xAD,0xB7,0x2C,0xBC,0xC7,0x30,0xC9,0xD5,0x33,0xD4,0xE0,0x3B,
0xE0,0xEC,0x42,0xEA,0xF6,0x45,0xF0,0xFD,0x47,0xF4,0xFF,0x6F,
0x55,0x24,0x00,0x5A,0x2C,0x00,0x6C,0x3B,0x00,0x79,0x4B,0x00,
0xB9,0x75,0x00,0xBB,0x85,0x00,0xC1,0xA1,0x20,0xD0,0xB0,0x2F,
0xDE,0xBE,0x3F,0xE6,0xC6,0x45,0xED,0xCD,0x57,0xF5,0xDB,0x62,
0xFB,0xE5,0x69,0xFC,0xEE,0x6F,0xFD,0xF3,0x77,0xFD,0xF3,0x7F,
0x5C,0x27,0x00,0x5C,0x2F,0x00,0x71,0x3B,0x00,0x7B,0x48,0x00,
0xB9,0x68,0x20,0xBB,0x72,0x20,0xC5,0x86,0x29,0xD7,0x96,0x33,
0xE6,0xA4,0x40,0xF4,0xB1,0x4B,0xFD,0xC1,0x58,0xFF,0xCC,0x55,
0xFF,0xD4,0x61,0xFF,0xDD,0x69,0xFF,0xE6,0x79,0xFF,0xEA,0x98
};
const byte REGION_PALETTE_NTSC_CRT_WARM[ ] = {
0x00, 0x00, 0x00, 0x0d, 0x0d, 0x0d, 0x28, 0x28, 0x28, 0x3e, 0x3e, 0x3e,
0x52, 0x52, 0x52, 0x65, 0x65, 0x65, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88,
0x98, 0x98, 0x98, 0xa8, 0xa8, 0xa8, 0xb7, 0xb7, 0xb7, 0xc6, 0xc6, 0xc6,
0xd5, 0xd5, 0xd5, 0xe3, 0xe3, 0xe3, 0xf1, 0xf1, 0xf1, 0xff, 0xff, 0xff,
0x42, 0x28, 0x00, 0x54, 0x3d, 0x00, 0x65, 0x4f, 0x00, 0x75, 0x60, 0x00,
0x84, 0x70, 0x00, 0x93, 0x80, 0x00, 0xa2, 0x8f, 0x00, 0xb0, 0x9d, 0x00,
0xbe, 0xac, 0x00, 0xcb, 0xb9, 0x00, 0xd8, 0xc7, 0x00, 0xe5, 0xd4, 0x1a,
0xf2, 0xe1, 0x30, 0xfe, 0xee, 0x43, 0xff, 0xfb, 0x55, 0xff, 0xff, 0x66,
0x6d, 0x0e, 0x00, 0x7d, 0x27, 0x00, 0x8c, 0x3b, 0x00, 0x9a, 0x4e, 0x00,
0xa9, 0x5f, 0x00, 0xb7, 0x6f, 0x00, 0xc4, 0x7f, 0x00, 0xd1, 0x8e, 0x00,
0xde, 0x9c, 0x02, 0xeb, 0xab, 0x1f, 0xf8, 0xb8, 0x35, 0xff, 0xc6, 0x48,
0xff, 0xd3, 0x59, 0xff, 0xe0, 0x6a, 0xff, 0xed, 0x7a, 0xff, 0xfa, 0x89,
0x85, 0x00, 0x00, 0x94, 0x0f, 0x00, 0xa2, 0x27, 0x00, 0xb0, 0x3b, 0x00,
0xbe, 0x4e, 0x06, 0xcb, 0x5f, 0x21, 0xd8, 0x6f, 0x37, 0xe5, 0x7f, 0x49,
0xf2, 0x8e, 0x5b, 0xff, 0x9d, 0x6b, 0xff, 0xab, 0x7b, 0xff, 0xb9, 0x8a,
0xff, 0xc6, 0x99, 0xff, 0xd3, 0xa7, 0xff, 0xe1, 0xb5, 0xff, 0xed, 0xc3,
0x89, 0x00, 0x24, 0x98, 0x00, 0x38, 0xa6, 0x17, 0x4b, 0xb4, 0x2e, 0x5c,
0xc1, 0x42, 0x6d, 0xcf, 0x53, 0x7d, 0xdc, 0x64, 0x8c, 0xe9, 0x74, 0x9a,
0xf5, 0x84, 0xa9, 0xff, 0x93, 0xb6, 0xff, 0xa1, 0xc4, 0xff, 0xaf, 0xd1,
0xff, 0xbd, 0xde, 0xff, 0xca, 0xeb, 0xff, 0xd8, 0xf8, 0xff, 0xe5, 0xff,
0x78, 0x00, 0x7d, 0x88, 0x00, 0x8c, 0x96, 0x11, 0x9a, 0xa5, 0x29, 0xa9,
0xb3, 0x3d, 0xb6, 0xc0, 0x4f, 0xc4, 0xce, 0x60, 0xd1, 0xdb, 0x71, 0xde,
0xe8, 0x80, 0xeb, 0xf5, 0x8f, 0xf8, 0xff, 0x9e, 0xff, 0xff, 0xac, 0xff,
0xff, 0xba, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xd5, 0xff, 0xff, 0xe2, 0xff,
0x55, 0x00, 0xb4, 0x66, 0x00, 0xc2, 0x76, 0x18, 0xcf, 0x85, 0x2e, 0xdc,
0x94, 0x42, 0xe9, 0xa2, 0x54, 0xf6, 0xb0, 0x65, 0xff, 0xbe, 0x75, 0xff,
0xcc, 0x84, 0xff, 0xd9, 0x93, 0xff, 0xe6, 0xa2, 0xff, 0xf2, 0xb0, 0xff,
0xff, 0xbd, 0xff, 0xff, 0xcb, 0xff, 0xff, 0xd8, 0xff, 0xff, 0xe5, 0xff,
0x1e, 0x00, 0xcd, 0x33, 0x10, 0xdb, 0x46, 0x28, 0xe7, 0x58, 0x3c, 0xf4,
0x69, 0x4f, 0xff, 0x79, 0x60, 0xff, 0x88, 0x70, 0xff, 0x97, 0x80, 0xff,
0xa5, 0x8f, 0xff, 0xb3, 0x9d, 0xff, 0xc1, 0xac, 0xff, 0xce, 0xb9, 0xff,
0xdb, 0xc7, 0xff, 0xe8, 0xd4, 0xff, 0xf5, 0xe1, 0xff, 0xff, 0xee, 0xff,
0x00, 0x10, 0xc6, 0x00, 0x28, 0xd4, 0x06, 0x3c, 0xe1, 0x21, 0x4f, 0xee,
0x36, 0x60, 0xfa, 0x49, 0x70, 0xff, 0x5b, 0x80, 0xff, 0x6b, 0x8f, 0xff,
0x7b, 0x9d, 0xff, 0x8a, 0xab, 0xff, 0x99, 0xb9, 0xff, 0xa7, 0xc7, 0xff,
0xb5, 0xd4, 0xff, 0xc3, 0xe1, 0xff, 0xd0, 0xee, 0xff, 0xdd, 0xfa, 0xff,
0x00, 0x2a, 0xa0, 0x00, 0x3e, 0xae, 0x00, 0x50, 0xbc, 0x00, 0x61, 0xc9,
0x00, 0x71, 0xd7, 0x1b, 0x81, 0xe3, 0x31, 0x90, 0xf0, 0x44, 0x9e, 0xfd,
0x56, 0xac, 0xff, 0x67, 0xba, 0xff, 0x77, 0xc8, 0xff, 0x86, 0xd5, 0xff,
0x95, 0xe2, 0xff, 0xa3, 0xef, 0xff, 0xb1, 0xfb, 0xff, 0xbf, 0xff, 0xff,
0x00, 0x3c, 0x5b, 0x00, 0x4f, 0x6c, 0x00, 0x60, 0x7b, 0x00, 0x70, 0x8b,
0x00, 0x80, 0x99, 0x00, 0x8f, 0xa8, 0x15, 0x9d, 0xb6, 0x2c, 0xab, 0xc3,
0x40, 0xb9, 0xd0, 0x52, 0xc7, 0xde, 0x63, 0xd4, 0xea, 0x73, 0xe1, 0xf7,
0x83, 0xee, 0xff, 0x92, 0xfa, 0xff, 0xa0, 0xff, 0xff, 0xae, 0xff, 0xff,
0x00, 0x47, 0x00, 0x00, 0x59, 0x00, 0x00, 0x69, 0x1e, 0x00, 0x79, 0x33,
0x00, 0x88, 0x47, 0x00, 0x97, 0x58, 0x18, 0xa5, 0x69, 0x2e, 0xb3, 0x79,
0x42, 0xc1, 0x88, 0x54, 0xce, 0x97, 0x65, 0xdb, 0xa5, 0x75, 0xe8, 0xb3,
0x84, 0xf5, 0xc1, 0x93, 0xff, 0xce, 0xa1, 0xff, 0xdb, 0xaf, 0xff, 0xe8,
0x00, 0x49, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x7b, 0x00,
0x06, 0x8a, 0x00, 0x21, 0x99, 0x00, 0x36, 0xa7, 0x08, 0x49, 0xb5, 0x23,
0x5b, 0xc2, 0x38, 0x6b, 0xd0, 0x4a, 0x7b, 0xdd, 0x5c, 0x8a, 0xea, 0x6c,
0x99, 0xf6, 0x7c, 0xa7, 0xff, 0x8b, 0xb5, 0xff, 0x9a, 0xc3, 0xff, 0xa8,
0x00, 0x42, 0x00, 0x00, 0x54, 0x00, 0x12, 0x64, 0x00, 0x2a, 0x75, 0x00,
0x3e, 0x84, 0x00, 0x50, 0x93, 0x00, 0x61, 0xa1, 0x00, 0x71, 0xaf, 0x00,
0x81, 0xbd, 0x00, 0x90, 0xcb, 0x00, 0x9f, 0xd8, 0x1a, 0xad, 0xe5, 0x30,
0xba, 0xf1, 0x43, 0xc8, 0xfe, 0x55, 0xd5, 0xff, 0x66, 0xe2, 0xff, 0x76,
0x27, 0x32, 0x00, 0x3c, 0x45, 0x00, 0x4e, 0x57, 0x00, 0x5f, 0x68, 0x00,
0x70, 0x78, 0x00, 0x7f, 0x87, 0x00, 0x8e, 0x96, 0x00, 0x9d, 0xa4, 0x00,
0xab, 0xb2, 0x00, 0xb9, 0xc0, 0x00, 0xc6, 0xcd, 0x00, 0xd4, 0xda, 0x14,
0xe1, 0xe7, 0x2b, 0xee, 0xf4, 0x3f, 0xfa, 0xff, 0x51, 0xff, 0xff, 0x62,
0x5b, 0x1b, 0x00, 0x6c, 0x31, 0x00, 0x7b, 0x45, 0x00, 0x8b, 0x56, 0x00,
0x99, 0x67, 0x00, 0xa8, 0x77, 0x00, 0xb6, 0x86, 0x00, 0xc3, 0x95, 0x00,
0xd0, 0xa4, 0x00, 0xde, 0xb2, 0x00, 0xea, 0xbf, 0x18, 0xf7, 0xcd, 0x2e,
0xff, 0xda, 0x42, 0xff, 0xe7, 0x54, 0xff, 0xf3, 0x65, 0xff, 0xff, 0x75
#if 0
// 1.2
static const byte REGION_PALETTE_NTSC[ ] = {
0x00,0x00,0x00,0x25,0x25,0x25,0x34,0x34,0x34,0x4F,0x4F,0x4F,
0x5B,0x5B,0x5B,0x69,0x69,0x69,0x7B,0x7B,0x7B,0x8A,0x8A,0x8A,
0xA7,0xA7,0xA7,0xB9,0xB9,0xB9,0xC5,0xC5,0xC5,0xD0,0xD0,0xD0,
0xD7,0xD7,0xD7,0xE1,0xE1,0xE1,0xF4,0xF4,0xF4,0xFF,0xFF,0xFF,
0x4C,0x32,0x00,0x62,0x3A,0x00,0x7B,0x4A,0x00,0x9A,0x60,0x00,
0xB5,0x74,0x00,0xCC,0x85,0x00,0xE7,0x9E,0x08,0xF7,0xAF,0x10,
0xFF,0xC3,0x18,0xFF,0xD0,0x20,0xFF,0xD8,0x28,0xFF,0xDF,0x30,
0xFF,0xE6,0x3B,0xFF,0xF4,0x40,0xFF,0xFA,0x4B,0xFF,0xFF,0x50,
0x99,0x25,0x00,0xAA,0x25,0x00,0xB4,0x25,0x00,0xD3,0x30,0x00,
0xDD,0x48,0x02,0xE2,0x50,0x09,0xF4,0x67,0x00,0xF4,0x71,0x00,
0xFF,0x9E,0x10,0xFF,0xAC,0x20,0xFF,0xBA,0x3A,0xFF,0xBF,0x50,
0xFF,0xC6,0x6D,0xFF,0xD5,0x80,0xFF,0xE4,0x90,0xFF,0xE6,0x99,
0x99,0x00,0x00,0xA9,0x00,0x00,0xC6,0x13,0x00,0xD8,0x04,0x00,
0xE2,0x35,0x00,0xE4,0x40,0x00,0xE3,0x50,0x15,0xE3,0x52,0x25,
0xFD,0x78,0x54,0xFF,0x8A,0x6A,0xFF,0x98,0x7C,0xFF,0xA4,0x8B,
0xFF,0xB3,0x9E,0xFF,0xC2,0xB2,0xFF,0xD0,0xBA,0xFF,0xD7,0xC0,
0x98,0x0C,0x0C,0xA7,0x0D,0x0D,0xAA,0x15,0x15,0xAA,0x20,0x25,
0xD2,0x1A,0x30,0xD3,0x28,0x00,0xD5,0x27,0x10,0xD6,0x27,0x30,
0xFB,0x70,0x70,0xFB,0x7E,0x7E,0xFB,0x8F,0x8F,0xFF,0x9F,0x9F,
0xFF,0xAB,0xAB,0xFF,0xB9,0xB9,0xFF,0xC9,0xC9,0xFF,0xCF,0xCF,
0x7E,0x00,0x50,0x80,0x00,0x50,0x80,0x00,0x5F,0x95,0x0B,0x74,
0xAA,0x22,0x88,0xBB,0x2F,0x9A,0xCE,0x3F,0xAD,0xD7,0x5A,0xB6,
0xE4,0x67,0xC3,0xEF,0x72,0xCE,0xFB,0x7E,0xDA,0xFF,0x8D,0xE1,
0xFF,0x9D,0xE5,0xFF,0xA5,0xE7,0xFF,0xAF,0xEA,0xFF,0xB8,0xEC,
0x48,0x00,0x6C,0x5C,0x04,0x88,0x65,0x0D,0x90,0x7B,0x23,0xA7,
0x93,0x3B,0xBF,0x9D,0x45,0xC9,0xA7,0x4F,0xD3,0xB2,0x5A,0xDE,
0xBD,0x65,0xE9,0xC5,0x6D,0xF1,0xCE,0x76,0xFA,0xD5,0x83,0xFF,
0xDA,0x90,0xFF,0xDE,0x9C,0xFF,0xE2,0xA9,0xFF,0xE6,0xB6,0xFF,
0x1B,0x00,0x70,0x22,0x1B,0x8D,0x37,0x30,0xA2,0x48,0x41,0xB3,
0x59,0x52,0xC4,0x63,0x5C,0xCE,0x6F,0x68,0xDA,0x7D,0x76,0xE8,
0x87,0x80,0xF8,0x93,0x8C,0xFF,0x9D,0x97,0xFF,0xA8,0xA3,0xFF,
0xB3,0xAF,0xFF,0xBC,0xB8,0xFF,0xC4,0xC1,0xFF,0xDA,0xD1,0xFF,
0x00,0x0D,0x7F,0x00,0x12,0xA7,0x00,0x18,0xC0,0x0A,0x2B,0xD1,
0x1B,0x4A,0xE3,0x2F,0x58,0xF0,0x37,0x68,0xFF,0x49,0x79,0xFF,
0x5B,0x85,0xFF,0x6D,0x96,0xFF,0x7F,0xA3,0xFF,0x8C,0xAD,0xFF,
0x96,0xB4,0xFF,0xA8,0xC0,0xFF,0xB7,0xCB,0xFF,0xC6,0xD6,0xFF,
0x00,0x29,0x5A,0x00,0x38,0x76,0x00,0x48,0x92,0x00,0x5C,0xAC,
0x00,0x71,0xC6,0x00,0x86,0xD0,0x0A,0x9B,0xDF,0x1A,0xA8,0xEC,
0x2B,0xB6,0xFF,0x3F,0xC2,0xFF,0x45,0xCB,0xFF,0x59,0xD3,0xFF,
0x7F,0xDA,0xFF,0x8F,0xDE,0xFF,0xA0,0xE2,0xFF,0xB0,0xEB,0xFF,
0x00,0x4A,0x00,0x00,0x4C,0x00,0x00,0x6A,0x20,0x50,0x8E,0x79,
0x40,0x99,0x99,0x00,0x9C,0xAA,0x00,0xA1,0xBB,0x01,0xA4,0xCC,
0x03,0xA5,0xD7,0x05,0xDA,0xE2,0x18,0xE5,0xFF,0x34,0xEA,0xFF,
0x49,0xEF,0xFF,0x66,0xF2,0xFF,0x84,0xF4,0xFF,0x9E,0xF9,0xFF,
0x00,0x4A,0x00,0x00,0x5D,0x00,0x00,0x70,0x00,0x00,0x83,0x00,
0x00,0x95,0x00,0x00,0xAB,0x00,0x07,0xBD,0x07,0x0A,0xD0,0x0A,
0x1A,0xD5,0x40,0x5A,0xF1,0x77,0x82,0xEF,0xA7,0x84,0xED,0xD1,
0x89,0xFF,0xED,0x7D,0xFF,0xFF,0x93,0xFF,0xFF,0x9B,0xFF,0xFF,
0x22,0x4A,0x03,0x27,0x53,0x04,0x30,0x64,0x05,0x3C,0x77,0x0C,
0x45,0x8C,0x11,0x5A,0xA5,0x13,0x1B,0xD2,0x09,0x1F,0xDD,0x00,
0x3D,0xCD,0x2D,0x3D,0xCD,0x30,0x58,0xCC,0x40,0x60,0xD3,0x50,
0xA2,0xEC,0x55,0xB3,0xF2,0x4A,0xBB,0xF6,0x5D,0xC4,0xF8,0x70,
0x2E,0x3F,0x0C,0x36,0x4A,0x0F,0x40,0x56,0x15,0x46,0x5F,0x17,
0x57,0x77,0x1A,0x65,0x85,0x1C,0x74,0x93,0x1D,0x8F,0xA5,0x25,
0xAD,0xB7,0x2C,0xBC,0xC7,0x30,0xC9,0xD5,0x33,0xD4,0xE0,0x3B,
0xE0,0xEC,0x42,0xEA,0xF6,0x45,0xF0,0xFD,0x47,0xF4,0xFF,0x6F,
0x5A,0x24,0x00,0x55,0x24,0x00,0x64,0x2D,0x06,0x92,0x55,0x2B,
0x9F,0x66,0x20,0xBB,0x85,0x00,0xC1,0xA1,0x20,0xD0,0xB0,0x2F,
0xDE,0xBE,0x3F,0xE6,0xC6,0x45,0xED,0xCD,0x57,0xF5,0xDB,0x62,
0xFB,0xE5,0x69,0xFC,0xEE,0x6F,0xFD,0xF3,0x77,0xFD,0xF3,0x7F,
0x5C,0x27,0x00,0x5C,0x27,0x00,0x75,0x2D,0x06,0x92,0x48,0x08,
0x92,0x50,0x18,0xBB,0x72,0x20,0xC5,0x86,0x29,0xD7,0x96,0x33,
0xE6,0xA4,0x40,0xF4,0xB1,0x4B,0xFD,0xC1,0x58,0xFF,0xCC,0x55,
0xFF,0xD4,0x61,0xFF,0xDD,0x69,0xFF,0xE6,0x79,0xFF,0xEA,0x98
};
#endif
// --------------------------------------------------------------------------------------
// PALETTE PAL
// --------------------------------------------------------------------------------------
const byte REGION_PALETTE_PAL[ ] = {
0x00,0x00,0x00,0x1c,0x1c,0x1c,0x39,0x39,0x39,0x59,0x59,0x59,
0x79,0x79,0x79,0x92,0x92,0x92,0xab,0xab,0xab,0xbc,0xbc,0xbc,
0xcd,0xcd,0xcd,0xd9,0xd9,0xd9,0xe6,0xe6,0xe6,0xec,0xec,0xec,
0xf2,0xf2,0xf2,0xf8,0xf8,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
0x26,0x30,0x01,0x24,0x38,0x03,0x23,0x40,0x05,0x51,0x54,0x1b,
0x80,0x69,0x31,0x97,0x81,0x35,0xaf,0x99,0x3a,0xc2,0xa7,0x3e,
0xd5,0xb5,0x43,0xdb,0xc0,0x3d,0xe1,0xcb,0x38,0xe2,0xd8,0x36,
0xe3,0xe5,0x34,0xef,0xf2,0x58,0xfb,0xff,0x7d,0xfb,0xff,0x7d,
0x39,0x17,0x01,0x5e,0x23,0x04,0x83,0x30,0x08,0xa5,0x47,0x16,
0xc8,0x5f,0x24,0xe3,0x78,0x20,0xff,0x91,0x1d,0xff,0xab,0x1d,
0xff,0xc5,0x1d,0xff,0xce,0x34,0xff,0xd8,0x4c,0xff,0xe6,0x51,
0xff,0xf4,0x56,0xff,0xf9,0x77,0xff,0xff,0x98,0xff,0xff,0x98,
0x45,0x19,0x04,0x72,0x1e,0x11,0x9f,0x24,0x1e,0xb3,0x3a,0x20,
0xc8,0x51,0x22,0xe3,0x69,0x20,0xff,0x81,0x1e,0xff,0x8c,0x25,
0xff,0x98,0x2c,0xff,0xae,0x38,0xff,0xc5,0x45,0xff,0xc5,0x59,
0xff,0xc6,0x6d,0xff,0xd5,0x87,0xff,0xe4,0xa1,0xff,0xe4,0xa1,
0x4a,0x17,0x04,0x7e,0x1a,0x0d,0xb2,0x1d,0x17,0xc8,0x21,0x19,
0xdf,0x25,0x1c,0xec,0x3b,0x38,0xfa,0x52,0x55,0xfc,0x61,0x61,
0xff,0x70,0x6e,0xff,0x7f,0x7e,0xff,0x8f,0x8f,0xff,0x9d,0x9e,
0xff,0xab,0xad,0xff,0xb9,0xbd,0xff,0xc7,0xce,0xff,0xc7,0xce,
0x05,0x05,0x68,0x3b,0x13,0x6d,0x71,0x22,0x72,0x8b,0x2a,0x8c,
0xa5,0x32,0xa6,0xb9,0x38,0xba,0xcd,0x3e,0xcf,0xdb,0x47,0xdd,
0xea,0x51,0xeb,0xf4,0x5f,0xf5,0xfe,0x6d,0xff,0xfe,0x7a,0xfd,
0xff,0x87,0xfb,0xff,0x95,0xfd,0xff,0xa4,0xff,0xff,0xa4,0xff,
0x28,0x04,0x79,0x40,0x09,0x84,0x59,0x0f,0x90,0x70,0x24,0x9d,
0x88,0x39,0xaa,0xa4,0x41,0xc3,0xc0,0x4a,0xdc,0xd0,0x54,0xed,
0xe0,0x5e,0xff,0xe9,0x6d,0xff,0xf2,0x7c,0xff,0xf8,0x8a,0xff,
0xff,0x98,0xff,0xfe,0xa1,0xff,0xfe,0xab,0xff,0xfe,0xab,0xff,
0x35,0x08,0x8a,0x42,0x0a,0xad,0x50,0x0c,0xd0,0x64,0x28,0xd0,
0x79,0x45,0xd0,0x8d,0x4b,0xd4,0xa2,0x51,0xd9,0xb0,0x58,0xec,
0xbe,0x60,0xff,0xc5,0x6b,0xff,0xcc,0x77,0xff,0xd1,0x83,0xff,
0xd7,0x90,0xff,0xdb,0x9d,0xff,0xdf,0xaa,0xff,0xdf,0xaa,0xff,
0x05,0x1e,0x81,0x06,0x26,0xa5,0x08,0x2f,0xca,0x26,0x3d,0xd4,
0x44,0x4c,0xde,0x4f,0x5a,0xee,0x5a,0x68,0xff,0x65,0x75,0xff,
0x71,0x83,0xff,0x80,0x91,0xff,0x90,0xa0,0xff,0x97,0xa9,0xff,
0x9f,0xb2,0xff,0xaf,0xbe,0xff,0xc0,0xcb,0xff,0xc0,0xcb,0xff,
0x05,0x1e,0x81,0x06,0x26,0xa5,0x08,0x2f,0xca,0x26,0x3d,0xd4,
0x44,0x4c,0xde,0x4f,0x5a,0xee,0x5a,0x68,0xff,0x65,0x75,0xff,
0x71,0x83,0xff,0x80,0x91,0xff,0x90,0xa0,0xff,0x97,0xa9,0xff,
0x9f,0xb2,0xff,0xaf,0xbe,0xff,0xc0,0xcb,0xff,0xc0,0xcb,0xff,
0x0c,0x04,0x8b,0x22,0x18,0xa0,0x38,0x2d,0xb5,0x48,0x3e,0xc7,
0x58,0x4f,0xda,0x61,0x59,0xec,0x6b,0x64,0xff,0x7a,0x74,0xff,
0x8a,0x84,0xff,0x91,0x8e,0xff,0x99,0x98,0xff,0xa5,0xa3,0xff,
0xb1,0xae,0xff,0xb8,0xb8,0xff,0xc0,0xc2,0xff,0xc0,0xc2,0xff,
0x1d,0x29,0x5a,0x1d,0x38,0x76,0x1d,0x48,0x92,0x1c,0x5c,0xac,
0x1c,0x71,0xc6,0x32,0x86,0xcf,0x48,0x9b,0xd9,0x4e,0xa8,0xec,
0x55,0xb6,0xff,0x70,0xc7,0xff,0x8c,0xd8,0xff,0x93,0xdb,0xff,
0x9b,0xdf,0xff,0xaf,0xe4,0xff,0xc3,0xe9,0xff,0xc3,0xe9,0xff,
0x2f,0x43,0x02,0x39,0x52,0x02,0x44,0x61,0x03,0x41,0x7a,0x12,
0x3e,0x94,0x21,0x4a,0x9f,0x2e,0x57,0xab,0x3b,0x5c,0xbd,0x55,
0x61,0xd0,0x70,0x69,0xe2,0x7a,0x72,0xf5,0x84,0x7c,0xfa,0x8d,
0x87,0xff,0x97,0x9a,0xff,0xa6,0xad,0xff,0xb6,0xad,0xff,0xb6,
0x0a,0x41,0x08,0x0d,0x54,0x0a,0x10,0x68,0x0d,0x13,0x7d,0x0f,
0x16,0x92,0x12,0x19,0xa5,0x14,0x1c,0xb9,0x17,0x1e,0xc9,0x19,
0x21,0xd9,0x1b,0x47,0xe4,0x2d,0x6e,0xf0,0x40,0x78,0xf7,0x4d,
0x83,0xff,0x5b,0x9a,0xff,0x7a,0xb2,0xff,0x9a,0xb2,0xff,0x9a,
0x04,0x41,0x0b,0x05,0x53,0x0e,0x06,0x66,0x11,0x07,0x77,0x14,
0x08,0x88,0x17,0x09,0x9b,0x1a,0x0b,0xaf,0x1d,0x48,0xc4,0x1f,
0x86,0xd9,0x22,0x8f,0xe9,0x24,0x99,0xf9,0x27,0xa8,0xfc,0x41,
0xb7,0xff,0x5b,0xc9,0xff,0x6e,0xdc,0xff,0x81,0xdc,0xff,0x81,
0x02,0x35,0x0f,0x07,0x3f,0x15,0x0c,0x4a,0x1c,0x2d,0x5f,0x1e,
0x4f,0x74,0x20,0x59,0x83,0x24,0x64,0x92,0x28,0x82,0xa1,0x2e,
0xa1,0xb0,0x34,0xa9,0xc1,0x3a,0xb2,0xd2,0x41,0xc4,0xd9,0x45,
0xd6,0xe1,0x49,0xe4,0xf0,0x4e,0xf2,0xff,0x53,0xf2,0xff,0x53,
};
const byte REGION_PALETTE_NTSC_CRT_HOT[ ] = {
0x00, 0x00, 0x00, 0x0d, 0x0d, 0x0d, 0x28, 0x28, 0x28, 0x3e, 0x3e, 0x3e,
0x52, 0x52, 0x52, 0x65, 0x65, 0x65, 0x77, 0x77, 0x77, 0x88, 0x88, 0x88,
0x98, 0x98, 0x98, 0xa8, 0xa8, 0xa8, 0xb7, 0xb7, 0xb7, 0xc6, 0xc6, 0xc6,
0xd5, 0xd5, 0xd5, 0xe3, 0xe3, 0xe3, 0xf1, 0xf1, 0xf1, 0xff, 0xff, 0xff,
0x42, 0x28, 0x00, 0x54, 0x3d, 0x00, 0x65, 0x4f, 0x00, 0x75, 0x60, 0x00,
0x84, 0x70, 0x00, 0x93, 0x80, 0x00, 0xa2, 0x8f, 0x00, 0xb0, 0x9d, 0x00,
0xbe, 0xac, 0x00, 0xcb, 0xb9, 0x00, 0xd8, 0xc7, 0x00, 0xe5, 0xd4, 0x1a,
0xf2, 0xe1, 0x30, 0xfe, 0xee, 0x43, 0xff, 0xfb, 0x55, 0xff, 0xff, 0x66,
0x6e, 0x0d, 0x00, 0x7e, 0x26, 0x00, 0x8d, 0x3a, 0x00, 0x9b, 0x4d, 0x00,
0xaa, 0x5e, 0x00, 0xb8, 0x6f, 0x00, 0xc5, 0x7e, 0x00, 0xd2, 0x8d, 0x00,
0xdf, 0x9c, 0x07, 0xec, 0xaa, 0x22, 0xf9, 0xb8, 0x37, 0xff, 0xc6, 0x4a,
0xff, 0xd3, 0x5b, 0xff, 0xe0, 0x6c, 0xff, 0xed, 0x7b, 0xff, 0xf9, 0x8b,
0x86, 0x00, 0x00, 0x95, 0x0d, 0x00, 0xa3, 0x26, 0x00, 0xb1, 0x3a, 0x00,
0xbf, 0x4d, 0x11, 0xcc, 0x5e, 0x29, 0xd9, 0x6e, 0x3d, 0xe6, 0x7e, 0x4f,
0xf3, 0x8d, 0x60, 0xff, 0x9c, 0x71, 0xff, 0xaa, 0x80, 0xff, 0xb8, 0x8f,
0xff, 0xc5, 0x9e, 0xff, 0xd3, 0xac, 0xff, 0xe0, 0xba, 0xff, 0xed, 0xc7,
0x88, 0x00, 0x2f, 0x97, 0x00, 0x43, 0xa5, 0x16, 0x55, 0xb3, 0x2d, 0x65,
0xc1, 0x41, 0x75, 0xce, 0x53, 0x85, 0xdb, 0x64, 0x94, 0xe8, 0x74, 0xa2,
0xf5, 0x83, 0xb0, 0xff, 0x92, 0xbe, 0xff, 0xa1, 0xcb, 0xff, 0xaf, 0xd9,
0xff, 0xbc, 0xe5, 0xff, 0xca, 0xf2, 0xff, 0xd7, 0xff, 0xff, 0xe4, 0xff,
0x75, 0x00, 0x86, 0x84, 0x00, 0x95, 0x93, 0x11, 0xa3, 0xa1, 0x29, 0xb1,
0xaf, 0x3d, 0xbf, 0xbd, 0x4f, 0xcc, 0xcb, 0x61, 0xda, 0xd8, 0x71, 0xe7,
0xe5, 0x80, 0xf3, 0xf1, 0x8f, 0xff, 0xfe, 0x9e, 0xff, 0xff, 0xac, 0xff,
0xff, 0xba, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xd5, 0xff, 0xff, 0xe2, 0xff,
0x4d, 0x00, 0xbb, 0x5e, 0x00, 0xc8, 0x6e, 0x1a, 0xd6, 0x7e, 0x30, 0xe3,
0x8d, 0x44, 0xef, 0x9c, 0x56, 0xfc, 0xaa, 0x66, 0xff, 0xb8, 0x76, 0xff,
0xc5, 0x86, 0xff, 0xd3, 0x95, 0xff, 0xe0, 0xa3, 0xff, 0xed, 0xb1, 0xff,
0xf9, 0xbf, 0xff, 0xff, 0xcc, 0xff, 0xff, 0xd9, 0xff, 0xff, 0xe6, 0xff,
0x0e, 0x00, 0xcf, 0x26, 0x15, 0xdc, 0x3b, 0x2c, 0xe9, 0x4d, 0x40, 0xf5,
0x5f, 0x52, 0xff, 0x6f, 0x63, 0xff, 0x7f, 0x73, 0xff, 0x8e, 0x83, 0xff,
0x9c, 0x92, 0xff, 0xaa, 0xa0, 0xff, 0xb8, 0xae, 0xff, 0xc6, 0xbc, 0xff,
0xd3, 0xc9, 0xff, 0xe0, 0xd7, 0xff, 0xed, 0xe4, 0xff, 0xfa, 0xf0, 0xff,
0x00, 0x17, 0xc0, 0x00, 0x2e, 0xcd, 0x00, 0x41, 0xda, 0x11, 0x53, 0xe7,
0x29, 0x64, 0xf4, 0x3d, 0x74, 0xff, 0x50, 0x84, 0xff, 0x61, 0x93, 0xff,
0x71, 0xa1, 0xff, 0x81, 0xaf, 0xff, 0x90, 0xbd, 0xff, 0x9e, 0xca, 0xff,
0xac, 0xd8, 0xff, 0xba, 0xe4, 0xff, 0xc8, 0xf1, 0xff, 0xd5, 0xfe, 0xff,
0x00, 0x30, 0x90, 0x00, 0x43, 0x9e, 0x00, 0x55, 0xac, 0x00, 0x66, 0xba,
0x00, 0x76, 0xc8, 0x0e, 0x85, 0xd5, 0x27, 0x94, 0xe2, 0x3b, 0xa2, 0xef,
0x4e, 0xb0, 0xfb, 0x5f, 0xbe, 0xff, 0x6f, 0xcc, 0xff, 0x7f, 0xd9, 0xff,
0x8e, 0xe6, 0xff, 0x9d, 0xf2, 0xff, 0xab, 0xff, 0xff, 0xb9, 0xff, 0xff,
0x00, 0x40, 0x3f, 0x00, 0x53, 0x51, 0x00, 0x63, 0x62, 0x00, 0x74, 0x72,
0x00, 0x83, 0x82, 0x00, 0x92, 0x91, 0x12, 0xa0, 0x9f, 0x2a, 0xaf, 0xad,
0x3e, 0xbc, 0xbb, 0x50, 0xca, 0xc8, 0x61, 0xd7, 0xd6, 0x71, 0xe4, 0xe3,
0x81, 0xf1, 0xef, 0x90, 0xfd, 0xfc, 0x9e, 0xff, 0xff, 0xac, 0xff, 0xff,
0x00, 0x49, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x7a, 0x09,
0x00, 0x8a, 0x23, 0x04, 0x98, 0x38, 0x20, 0xa7, 0x4b, 0x35, 0xb5, 0x5c,
0x48, 0xc2, 0x6c, 0x5a, 0xd0, 0x7c, 0x6a, 0xdd, 0x8b, 0x7a, 0xea, 0x9a,
0x89, 0xf6, 0xa8, 0x98, 0xff, 0xb6, 0xa6, 0xff, 0xc4, 0xb4, 0xff, 0xd1,
0x00, 0x47, 0x00, 0x00, 0x59, 0x00, 0x00, 0x69, 0x00, 0x00, 0x79, 0x00,
0x1d, 0x88, 0x00, 0x33, 0x97, 0x00, 0x46, 0xa5, 0x00, 0x58, 0xb3, 0x00,
0x68, 0xc1, 0x16, 0x78, 0xce, 0x2d, 0x87, 0xdc, 0x41, 0x96, 0xe8, 0x53,
0xa5, 0xf5, 0x64, 0xb3, 0xff, 0x74, 0xc0, 0xff, 0x83, 0xce, 0xff, 0x92,
0x00, 0x3c, 0x00, 0x17, 0x4e, 0x00, 0x2e, 0x60, 0x00, 0x41, 0x70, 0x00,
0x53, 0x7f, 0x00, 0x64, 0x8f, 0x00, 0x74, 0x9d, 0x00, 0x84, 0xab, 0x00,
0x93, 0xb9, 0x00, 0xa1, 0xc7, 0x00, 0xaf, 0xd4, 0x00, 0xbd, 0xe1, 0x1e,
0xca, 0xee, 0x34, 0xd8, 0xfa, 0x47, 0xe5, 0xff, 0x59, 0xf1, 0xff, 0x69,
0x42, 0x29, 0x00, 0x54, 0x3d, 0x00, 0x64, 0x4f, 0x00, 0x74, 0x60, 0x00,
0x84, 0x71, 0x00, 0x93, 0x80, 0x00, 0xa1, 0x8f, 0x00, 0xaf, 0x9e, 0x00,
0xbd, 0xac, 0x00, 0xca, 0xba, 0x00, 0xd8, 0xc7, 0x00, 0xe5, 0xd4, 0x1a,
0xf1, 0xe1, 0x30, 0xfe, 0xee, 0x43, 0xff, 0xfb, 0x55, 0xff, 0xff, 0x66,
0x6e, 0x0d, 0x00, 0x7d, 0x26, 0x00, 0x8c, 0x3b, 0x00, 0x9b, 0x4d, 0x00,
0xa9, 0x5e, 0x00, 0xb7, 0x6f, 0x00, 0xc5, 0x7e, 0x00, 0xd2, 0x8d, 0x00,
0xdf, 0x9c, 0x05, 0xec, 0xaa, 0x21, 0xf9, 0xb8, 0x36, 0xff, 0xc6, 0x49,
0xff, 0xd3, 0x5a, 0xff, 0xe0, 0x6b, 0xff, 0xed, 0x7b, 0xff, 0xf9, 0x8a
};
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
extern uint sound_lenght;
extern uint video_height;
void region_Reset( ) {
if(region_type == REGION_PAL || (region_type == REGION_AUTO && cartridge_region == REGION_PAL)) {
maria_displayArea = REGION_DISPLAY_AREA_PAL;
maria_visibleArea = REGION_VISIBLE_AREA_PAL;
if(palette_default)
palette_Load(REGION_PALETTE_PAL); // Added check for default - bberlin
prosystem_frequency = REGION_FREQUENCY_PAL;
prosystem_scanlines = REGION_SCANLINES_PAL;
tia_size = 624;
pokey_size = 624;
}
else {
maria_displayArea = REGION_DISPLAY_AREA_NTSC;
maria_visibleArea = REGION_VISIBLE_AREA_NTSC;
if(palette_default)
palette_Load(REGION_PALETTE_NTSC); // Added check for default - bberlin
prosystem_frequency = REGION_FREQUENCY_NTSC;
prosystem_scanlines = REGION_SCANLINES_NTSC;
tia_size = 524;
pokey_size = 524;
}
maria_displayArea.GetLength = (maria_displayArea.right - maria_displayArea.left) + 1;
maria_displayArea.GetHeight = (maria_displayArea.bottom - maria_displayArea.top) + 1;
maria_displayArea.GetArea = maria_displayArea.GetLength * maria_displayArea.GetHeight;
// ---------------------------------
// We only support NTSC for A7800DS
// ---------------------------------
void region_Reset( )
{
if(myCartInfo.palette == 0) palette_Load(REGION_PALETTE_NTSC_CRT_COOL);
if(myCartInfo.palette == 1) palette_Load(REGION_PALETTE_NTSC_CRT_WARM);
if(myCartInfo.palette == 2) palette_Load(REGION_PALETTE_NTSC_CRT_HOT);
maria_visibleArea.GetLength = (maria_visibleArea.right - maria_visibleArea.left) + 1;
maria_visibleArea.GetHeight = (maria_visibleArea.bottom - maria_visibleArea.top) + 1;
maria_visibleArea.GetArea = maria_visibleArea.GetLength * maria_visibleArea.GetHeight;
sound_lenght = 22050 / prosystem_frequency;
video_height = maria_visibleArea.bottom-maria_displayArea.top;
}

View file

@ -24,23 +24,23 @@
// ----------------------------------------------------------------------------
#include "Riot.h"
uint riot_and_wsync __attribute__((section(".dtcm"))) = 0x00;
int riot_timer __attribute__((section(".dtcm"))) = TIM64T;
int riot_intervals __attribute__((section(".dtcm"))) = 0;
bool riot_timing = false;
word riot_timer = TIM64T;
byte riot_intervals;
byte riot_dra __attribute__((section(".dtcm"))) = 0;
byte riot_drb __attribute__((section(".dtcm"))) = 0;
byte riot_dra = 0;
byte riot_drb = 0;
uint riot_elapsed __attribute__((section(".dtcm"))) = 0;
int riot_currentTime __attribute__((section(".dtcm"))) = 0;
uint riot_clocks __attribute__((section(".dtcm"))) = 0;
uint riot_shift __attribute__((section(".dtcm"))) = 0;
bool riot_elapsed;
int riot_currentTime;
word riot_clocks;
word riot_shift=0;
void riot_Reset(void) {
riot_SetDRA(0);
riot_SetDRB(0);
riot_and_wsync = 0;
riot_timing = false;
riot_timer = TIM64T;
riot_intervals = 0;
riot_clocks = 0;
@ -73,13 +73,13 @@ void riot_Reset(void) {
// | 15 | Console | Left Difficulty
// | 16 | Console | Right Difficulty
// +----------+--------------+-------------------------------------------------
ITCM_CODE void riot_SetInput(const byte* input) {
void riot_SetInput(const byte* input) {
/*gdement: Comments are messy, but wanted to document how this all works.
Changed this routine to support 1 vs 2 button modes.
Also added the interaction of CTLSWA and DRA on the SWCHA output, and same for SWCHB.
SWCHA is directionals. SWCHB is console switches and button mode.
button signals are in high bits of INPT0-5.*/
memory_ram[SWCHA] = ((~memory_ram[CTLSWA]) | riot_dra); /*SWCHA as driven by RIOT*/
/*now console switches will force bits to ground:*/
@ -194,6 +194,55 @@ ITCM_CODE void riot_SetInput(const byte* input) {
memory_ram[INPT2] &= 0x7f;
}
}
/*
if (input[0x00] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x80; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x80 ;
if (input[0x01] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x40; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x40;
if (input[0x02] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x20; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x20;
if (input[0x03] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x10; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x10;
if(input[0x04]) {
memory_ram[INPT0] = memory_ram[INPT0] | 0x80;
memory_ram[INPT4] = memory_ram[INPT4] &~ 0x80;
}
else {
memory_ram[INPT0] = memory_ram[INPT0] &~ 0x80;
memory_ram[INPT4] = memory_ram[INPT4] | 0x80;
}
if(input[0x05]) {
memory_ram[INPT1] = memory_ram[INPT1] | 0x80;
memory_ram[INPT4] = memory_ram[INPT4] &~ 0x80;
}
else {
memory_ram[INPT1] = memory_ram[INPT1] &~ 0x80;
memory_ram[INPT4] = memory_ram[INPT4] | 0x80;
}
if (input[0x06] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x08; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x08;
if (input[0x07] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x04; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x04;
if (input[0x08] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x02; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x02;
if (input[0x09] ) memory_ram[SWCHA] = memory_ram[SWCHA] &~ 0x01; else memory_ram[SWCHA] = memory_ram[SWCHA] | 0x01;
if(input[0x0a]) {
memory_ram[INPT2] = memory_ram[INPT2] | 0x80;
memory_ram[INPT5] = memory_ram[INPT5] &~ 0x80;
}
else {
memory_ram[INPT2] = memory_ram[INPT2] &~ 0x80;
memory_ram[INPT5] = memory_ram[INPT5] | 0x80;
}
if(input[0x0b]) {
memory_ram[INPT3] = memory_ram[INPT3] | 0x80;
memory_ram[INPT5] = memory_ram[INPT5] &~ 0x80;
}
else {
memory_ram[INPT3] = memory_ram[INPT3] &~ 0x80;
memory_ram[INPT5] = memory_ram[INPT5] | 0x80;
}
if (input[0x0c]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x01; else memory_ram[SWCHB] = memory_ram[SWCHB] | 0x01;
if (input[0x0d]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x02; else memory_ram[SWCHB] = memory_ram[SWCHB] | 0x02;
if (input[0x0e]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x08; else memory_ram[SWCHB] = memory_ram[SWCHB] | 0x08;
if (input[0x0f]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x40; else memory_ram[SWCHB] = memory_ram[SWCHB] | 0x40;
if (input[0x10]) memory_ram[SWCHB] = memory_ram[SWCHB] &~ 0x80; else memory_ram[SWCHB] = memory_ram[SWCHB] | 0x80;
*/
}
/***********************************************************************************
@ -225,25 +274,25 @@ void riot_SetTimer(word timer, byte intervals)
case T1024T:
riot_clocks = 1024;
riot_shift = 10;
riot_and_wsync |= 2;
riot_timing = true;
break;
case TIM1T:
riot_clocks = 1;
riot_shift = 0;
riot_and_wsync |= 2;
riot_timing = true;
break;
case TIM8T:
riot_clocks = 8;
riot_shift = 3;
riot_and_wsync |= 2;
riot_timing = true;
break;
case TIM64T:
riot_clocks = 64;
riot_shift = 6;
riot_and_wsync |= 2;
riot_timing = true;
break;
}
if(riot_and_wsync) {
if(riot_timing) {
riot_currentTime = riot_clocks * intervals;
riot_elapsed = false;
}
@ -252,7 +301,7 @@ void riot_SetTimer(word timer, byte intervals)
// ----------------------------------------------------------------------------
// UpdateTimer
// ----------------------------------------------------------------------------
ITCM_CODE void inline riot_UpdateTimer(byte cycles)
void inline riot_UpdateTimer(byte cycles)
{
riot_currentTime -= cycles;
if(!riot_elapsed && riot_currentTime > 0)
@ -270,7 +319,7 @@ ITCM_CODE void inline riot_UpdateTimer(byte cycles)
else
{
memory_ram[INTIM] = 0;
riot_and_wsync &= 0xFD;
riot_timing = false;
}
}
else

View file

@ -37,10 +37,9 @@ extern void riot_SetDRA(byte data);
extern void riot_SetDRB(byte data);
extern void riot_SetTimer(word timer, byte intervals);
extern void riot_UpdateTimer(byte cycles);
extern uint riot_and_wsync;
extern int riot_timer;
extern int riot_intervals;
extern u32 snes_adaptor;
extern bool riot_timing;
extern word riot_timer;
extern byte riot_intervals;
extern void riot_SetDRA(byte data);
extern void riot_SetDRB(byte data);

View file

@ -31,27 +31,17 @@
#include "shared.h"
typedef union
{
int32 w;
struct {
byte l;
byte h;
byte b2;
byte b3;
} b;
} PCUnion;
extern void sally_Reset( );
extern uint sally_ExecuteInstruction( );
extern uint sally_ExecuteRES( );
extern uint sally_ExecuteNMI( );
extern uint sally_ExecuteIRQ( );
extern byte sally_a;
extern byte sally_x;
extern byte sally_y;
extern uint sally_p;
extern uint sally_s;
extern bool wsync_happened;
extern byte sally_p;
extern byte sally_s;
extern pair sally_pc;
extern void sally_Execute(unsigned int cycles );

File diff suppressed because it is too large Load diff

30
arm9/source/emu/Sound.c Normal file
View file

@ -0,0 +1,30 @@
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "ProSystem.h"
#include "Sound.h"
#define SOUND_SOURCE "Sound.cpp"
uint sound_lenght;
unsigned char sound_buffer[SNDLENGTH]; // Sound buffer
unsigned int targetIndex = 0;
void processSound(register unsigned char *buffer)
{
// Handled directly in sound interrupt routine in a7800utils.c
}

39
arm9/source/emu/Sound.h Normal file
View file

@ -0,0 +1,39 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// Sound.h
// ----------------------------------------------------------------------------
#ifndef SOUND_H
#define SOUND_H
#include "shared.h"
#define SNDLENGTH (4096)
extern uint sound_lenght;
extern unsigned char sound_buffer[SNDLENGTH]; // Sound buffer
extern bool sound_Store();
extern void processSound(register unsigned char *buffer);
#endif

View file

@ -1,252 +0,0 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// TiaSound is Copyright(c) 1997 by Ron Fries
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library 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 Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Any permitted reproduction of these routines, in whole or in part, must
// bear this legend.
// ----------------------------------------------------------------------------
// Tia.cpp
// ----------------------------------------------------------------------------
#include "Tia.h"
#define TIA_POLY4_SIZE 15
#define TIA_POLY5_SIZE 31
#define TIA_POLY9_SIZE 511
u32 tiaBufIdx __attribute__((section(".dtcm"))) = 0;
u16 tia_buffer[SNDLENGTH] __attribute__((section(".dtcm"))) = {0};
byte tia_volume[2] __attribute__((section(".dtcm"))) = {0};
uint tia_counter[2] __attribute__((section(".dtcm"))) = {0};
uint tia_counterMax[2] __attribute__((section(".dtcm"))) = {0};
byte TIA_POLY4[ ] __attribute__((section(".dtcm"))) = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
byte TIA_POLY5[ ] __attribute__((section(".dtcm"))) = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1};
static byte TIA_POLY9[ ] __attribute__((section(".dtcm"))) = {0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,1,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1,1,0,1,0,0,0,1,1,0,0,1,1,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,0,1,0,1,1,1,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,1,0,1,1,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,1,0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0};
static byte TIA_DIV31[ ] __attribute__((section(".dtcm"))) = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0};
byte tia_audc[2] __attribute__((section(".dtcm"))) = {0};
byte tia_audf[2] __attribute__((section(".dtcm"))) = {0};
byte tia_audv[2] __attribute__((section(".dtcm"))) = {0};
static byte tia_poly4Cntr[2] __attribute__((section(".dtcm"))) = {0};
static byte tia_poly5Cntr[2] __attribute__((section(".dtcm"))) = {0};
static u16 tia_poly9Cntr[2] __attribute__((section(".dtcm"))) = {0};
u16 tia_wait __attribute__((section(".dtcm"))) = 0;
// ----------------------------------------------------------------------------
// ProcessChannel
// ----------------------------------------------------------------------------
static ITCM_CODE void tia_ProcessChannel0(void)
{
tia_poly5Cntr[0] = (tia_poly5Cntr[0] + 1) % TIA_POLY5_SIZE;
if(((tia_audc[0] & 2) == 0) || (((tia_audc[0] & 1) == 0) && TIA_DIV31[tia_poly5Cntr[0]]) || (((tia_audc[0] & 1) == 1) && TIA_POLY5[tia_poly5Cntr[0]]))
{
if(tia_audc[0] & 4)
{
tia_volume[0] = (!tia_volume[0])? tia_audv[0]: 0;
}
else if(tia_audc[0] & 8)
{
if(tia_audc[0] == 8)
{
tia_poly9Cntr[0] = (tia_poly9Cntr[0]+1) % TIA_POLY9_SIZE;
tia_volume[0] = (TIA_POLY9[tia_poly9Cntr[0]])? tia_audv[0]: 0;
}
else
{
tia_volume[0] = (TIA_POLY5[tia_poly5Cntr[0]])? tia_audv[0]: 0;
}
}
else
{
tia_poly4Cntr[0] = (tia_poly4Cntr[0] + 1) % TIA_POLY4_SIZE;
tia_volume[0] = (TIA_POLY4[tia_poly4Cntr[0]])? tia_audv[0]: 0;
}
}
}
static ITCM_CODE void tia_ProcessChannel1(void)
{
tia_poly5Cntr[1] = (tia_poly5Cntr[1] + 1) % TIA_POLY5_SIZE;
if(((tia_audc[1] & 2) == 0) || (((tia_audc[1] & 1) == 0) && TIA_DIV31[tia_poly5Cntr[1]]) || (((tia_audc[1] & 1) == 1) && TIA_POLY5[tia_poly5Cntr[1]]))
{
if(tia_audc[1] & 4)
{
tia_volume[1] = (!tia_volume[1])? tia_audv[1]: 0;
}
else if(tia_audc[1] & 8)
{
if(tia_audc[1] == 8)
{
tia_poly9Cntr[1] = (tia_poly9Cntr[1]+1) % TIA_POLY9_SIZE;
tia_volume[1] = (TIA_POLY9[tia_poly9Cntr[1]])? tia_audv[1]: 0;
}
else
{
tia_volume[1] = (TIA_POLY5[tia_poly5Cntr[1]])? tia_audv[1]: 0;
}
}
else
{
tia_poly4Cntr[1] = (tia_poly4Cntr[1] + 1) % TIA_POLY4_SIZE;
tia_volume[1] = (TIA_POLY4[tia_poly4Cntr[1]])? tia_audv[1]: 0;
}
}
}
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void tia_Reset( ) {
uint index;
tiaBufIdx = 0;
for(index = 0; index < 2; index++) {
tia_volume[index] = 0;
tia_counterMax[index] = 0;
tia_counter[index] = 0;
tia_audc[index] = 0;
tia_audf[index] = 0;
tia_audv[index] = 0;
tia_poly4Cntr[index] = 0;
tia_poly5Cntr[index] = 0;
tia_poly9Cntr[index] = 0;
}
tia_Clear( );
tia_wait = 0;
}
// ----------------------------------------------------------------------------
// Clear
// ----------------------------------------------------------------------------
void tia_Clear( ) {
uint index;
for(index = 0; index < SNDLENGTH; index++) {
tia_buffer[index] = 0;
}
}
// Same as TIA_Process but designed for Pokey integration...
ITCM_CODE int TIA_Sample(void)
{
if(tia_counter[0] > 1)
{
tia_counter[0]--;
}
else if(tia_counter[0] == 1)
{
tia_counter[0] = tia_counterMax[0];
tia_ProcessChannel0();
}
if(tia_counter[1] > 1)
{
tia_counter[1]--;
}
else if(tia_counter[1] == 1)
{
tia_counter[1] = tia_counterMax[1];
tia_ProcessChannel1();
}
return ((int)tia_volume[0] + (int)tia_volume[1]);
}
// --------------------------------------------------------------------------------------
// Process
// --------------------------------------------------------------------------------------
ITCM_CODE void tia_Process(void)
{
u32 samp[2];
if (tia_wait) return;
for(u8 index = 0; index < 2; index++)
{
if(tia_counter[0] > 1)
{
tia_counter[0]--;
}
else if(tia_counter[0] == 1)
{
tia_counter[0] = tia_counterMax[0];
tia_ProcessChannel0();
}
if(tia_counter[1] > 1)
{
tia_counter[1]--;
}
else if(tia_counter[1] == 1)
{
tia_counter[1] = tia_counterMax[1];
tia_ProcessChannel1();
}
samp[index] = ((tia_volume[0] + tia_volume[1]));
}
// We have filled the buffer... let the buffer drain a bit
if (((tiaBufIdx+1) & (SNDLENGTH-1)) == myTiaBufIdx)
{
tia_wait = (SNDLENGTH >> 2);
}
else
{
tia_buffer[tiaBufIdx++] = (samp[1] << 8) | (samp[0]);
tiaBufIdx &= (SNDLENGTH-1);
}
}
ITCM_CODE u16 tia_ProcessNow(void)
{
u32 samp[2];
for(u8 index = 0; index < 2; index++)
{
if(tia_counter[0] > 1)
{
tia_counter[0]--;
}
else if(tia_counter[0] == 1)
{
tia_counter[0] = tia_counterMax[0];
tia_ProcessChannel0();
}
if(tia_counter[1] > 1)
{
tia_counter[1]--;
}
else if(tia_counter[1] == 1)
{
tia_counter[1] = tia_counterMax[1];
tia_ProcessChannel1();
}
samp[index] = ((tia_volume[0] + tia_volume[1]));
}
return (u16)((samp[1] << 8) | (samp[0]));
}

View file

@ -40,15 +40,12 @@
// ----------------------------------------------------------------------------
#ifndef TIA_H
#define TIA_H
#define TIA_BUFFER_SIZE 624
#include "Equates.h"
#include "shared.h"
#define SNDLENGTH (1024)
extern u16 tia_buffer[];
extern byte tia_audc[2];
extern byte tia_audf[2];
extern byte tia_audv[2];
@ -56,40 +53,10 @@ extern byte tia_audv[2];
extern void tia_Reset( );
extern void tia_SetRegister(word address, byte data);
extern void tia_MemoryChannel(byte channel);
extern void tia_Clear( );
extern void tia_Process(void);
extern u16 tia_ProcessNow(void);
extern byte tia_volume[2];
extern uint tia_counter[2];
extern uint tia_counterMax[2];
extern u16 tia_wait;
extern u32 myTiaBufIdx;
inline void tia_MemoryChannel(byte channel)
{
byte frequency = 0;
if(tia_audc[channel] == 0)
{
tia_volume[channel] = tia_audv[channel];
}
else
{
frequency = tia_audf[channel] + 1;
if(tia_audc[channel] > 11)
{
frequency *= 3;
}
}
if(frequency != tia_counterMax[channel])
{
tia_counterMax[channel] = frequency;
if(tia_counter[channel] == 0 || frequency == 0)
{
tia_counter[channel] = frequency;
}
}
}
extern void tia_Process(uint length);
extern byte tia_buffer[TIA_BUFFER_SIZE];
extern uint tia_size;
#endif

248
arm9/source/emu/Tia.itcm.c Normal file
View file

@ -0,0 +1,248 @@
// ----------------------------------------------------------------------------
// ___ ___ ___ ___ ___ ____ ___ _ _
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
//
// ----------------------------------------------------------------------------
// Copyright 2005 Greg Stanton
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// ----------------------------------------------------------------------------
// TiaSound is Copyright(c) 1997 by Ron Fries
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of version 2 of the GNU Library General Public License
// as published by the Free Software Foundation.
//
// This library 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 Library
// General Public License for more details.
// To obtain a copy of the GNU Library General Public License, write to the
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// Any permitted reproduction of these routines, in whole or in part, must
// bear this legend.
// ----------------------------------------------------------------------------
// Tia.cpp
// ----------------------------------------------------------------------------
#include "Tia.h"
#define TIA_POLY4_SIZE 15
#define TIA_POLY5_SIZE 31
#define TIA_POLY9_SIZE 511
byte tia_buffer[TIA_BUFFER_SIZE] = {0};
uint tia_size = 524;
extern int debug[];
static const byte TIA_POLY4[ ] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0};
static const byte TIA_POLY5[ ] = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1};
static const byte TIA_POLY9[ ] = {0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,0,1,1,1,0,1,1,0,0,1,0,0,1,1,1,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,1,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1,1,0,1,0,0,0,1,1,0,0,1,1,1,1,0,0,1,0,0,0,1,1,1,0,0,1,1,0,1,0,1,1,0,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,1,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,0,0,1,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,0,1,0,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,0,1,0,1,1,1,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,1,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,1,0,1,1,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,1,1,1,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,1,0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0};
static const byte TIA_DIV31[ ] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0};
static byte tia_volume[2] = {0};
static byte tia_counterMax[2] = {0};
static byte tia_counter[2] = {0};
byte tia_audc[2] = {0};
byte tia_audf[2] = {0};
byte tia_audv[2] = {0};
static uint tia_poly4Cntr[2] = {0};
static uint tia_poly5Cntr[2] = {0};
static uint tia_poly9Cntr[2] = {0};
static uint tia_soundCntr = 0;
// ----------------------------------------------------------------------------
// ProcessChannel
// ----------------------------------------------------------------------------
static void tia_ProcessChannel(byte channel)
{
tia_poly5Cntr[channel] = (tia_poly5Cntr[channel] + 1) % TIA_POLY5_SIZE;
if(((tia_audc[channel] & 2) == 0) || (((tia_audc[channel] & 1) == 0) && TIA_DIV31[tia_poly5Cntr[channel]]) || (((tia_audc[channel] & 1) == 1) && TIA_POLY5[tia_poly5Cntr[channel]]))
{
if(tia_audc[channel] & 4)
{
tia_volume[channel] = (!tia_volume[channel])? tia_audv[channel]: 0;
}
else if(tia_audc[channel] & 8)
{
if(tia_audc[channel] == 8)
{
tia_poly9Cntr[channel] = (tia_poly9Cntr[channel]+1) % TIA_POLY9_SIZE;
tia_volume[channel] = (TIA_POLY9[tia_poly9Cntr[channel]])? tia_audv[channel]: 0;
}
else
{
tia_volume[channel] = (TIA_POLY5[tia_poly5Cntr[channel]])? tia_audv[channel]: 0;
}
}
else
{
tia_poly4Cntr[channel] = (tia_poly4Cntr[channel] + 1) % TIA_POLY4_SIZE;
tia_volume[channel] = (TIA_POLY4[tia_poly4Cntr[channel]])? tia_audv[channel]: 0;
}
}
}
// ----------------------------------------------------------------------------
// Reset
// ----------------------------------------------------------------------------
void tia_Reset( ) {
uint index;
tia_soundCntr = 0;
for(index = 0; index < 2; index++) {
tia_volume[index] = 0;
tia_counterMax[index] = 0;
tia_counter[index] = 0;
tia_audc[index] = 0;
tia_audf[index] = 0;
tia_audv[index] = 0;
tia_poly4Cntr[index] = 0;
tia_poly5Cntr[index] = 0;
tia_poly9Cntr[index] = 0;
}
tia_Clear( );
}
// ----------------------------------------------------------------------------
// Clear
// ----------------------------------------------------------------------------
void tia_Clear( ) {
uint index;
for(index = 0; index < TIA_BUFFER_SIZE; index++) {
tia_buffer[index] = 0;
}
}
// ----------------------------------------------------------------------------
// SetRegister
// ----------------------------------------------------------------------------
void tia_SetRegister(word address, byte data)
{
byte channel=0;
byte frequency;
switch(address) {
case AUDC0:
tia_audc[0] = data & 15;
break;
case AUDC1:
tia_audc[1] = data & 15;
channel = 1;
break;
case AUDF0:
tia_audf[0] = data & 31;
break;
case AUDF1:
tia_audf[1] = data & 31;
channel = 1;
break;
case AUDV0:
tia_audv[0] = (data & 15) << 2;
break;
case AUDV1:
tia_audv[1] = (data & 15) << 2;
channel = 1;
break;
default:
return;
}
if(tia_audc[channel] == 0)
{
frequency = 0;
tia_volume[channel] = tia_audv[channel];
}
else
{
frequency = tia_audf[channel] + 1;
if(tia_audc[channel] > 11)
{
frequency *= 3;
}
}
if(frequency != tia_counterMax[channel])
{
tia_counterMax[channel] = frequency;
if(tia_counter[channel] == 0 || frequency == 0)
{
tia_counter[channel] = frequency;
}
}
}
void tia_MemoryChannel(byte channel)
{
byte frequency = 0;
if(tia_audc[channel] == 0)
{
tia_volume[channel] = tia_audv[channel];
}
else
{
frequency = tia_audf[channel] + 1;
if(tia_audc[channel] > 11)
{
frequency *= 3;
}
}
if(frequency != tia_counterMax[channel])
{
tia_counterMax[channel] = frequency;
if(tia_counter[channel] == 0 || frequency == 0)
{
tia_counter[channel] = frequency;
}
}
}
// --------------------------------------------------------------------------------------
// Process
// --------------------------------------------------------------------------------------
void tia_Process(uint length)
{
static int sound_sample_150pct=0;
uint index;
for(index = 0; index < length; index++)
{
if(tia_counter[0] > 1)
{
tia_counter[0]--;
}
else if(tia_counter[0] == 1)
{
tia_counter[0] = tia_counterMax[0];
tia_ProcessChannel(0);
}
if(tia_counter[1] > 1)
{
tia_counter[1]--;
}
else if(tia_counter[1] == 1)
{
tia_counter[1] = tia_counterMax[1];
tia_ProcessChannel(1);
}
// We sample 50% more than we output... helps _slightly_ with sound quality...
if (sound_sample_150pct == 0 || sound_sample_150pct == 1)
{
tia_buffer[tia_soundCntr] = ((tia_volume[0] + tia_volume[1])) + 128;
tia_soundCntr = (tia_soundCntr+1) % tia_size;
} else index--;
sound_sample_150pct = (sound_sample_150pct+1) % 3;
}
}

View file

@ -3,10 +3,21 @@
#include <nds.h>
//#define SYSVID_WIDTH 320
//#define SYSVID_HEIGHT 223
//typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int uint;
extern unsigned short *bufVideo; // Video buffer
extern char gameName[256];
extern unsigned int gameCRC;
extern uint video_height;
extern word atari_pal16[256];
extern void system_loadcfg(char *cfg_name);
extern void system_savecfg(char *cfg_name);
#endif

177
arm9/source/emu/zip/ioapi.c Normal file
View file

@ -0,0 +1,177 @@
/* ioapi.c -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#include "ioapi.h"
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
voidpf ZCALLBACK fopen_file_func OF((
voidpf opaque,
const char* filename,
int mode));
uLong ZCALLBACK fread_file_func OF((
voidpf opaque,
voidpf stream,
void* buf,
uLong size));
uLong ZCALLBACK fwrite_file_func OF((
voidpf opaque,
voidpf stream,
const void* buf,
uLong size));
long ZCALLBACK ftell_file_func OF((
voidpf opaque,
voidpf stream));
long ZCALLBACK fseek_file_func OF((
voidpf opaque,
voidpf stream,
uLong offset,
int origin));
int ZCALLBACK fclose_file_func OF((
voidpf opaque,
voidpf stream));
int ZCALLBACK ferror_file_func OF((
voidpf opaque,
voidpf stream));
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
voidpf opaque;
const char* filename;
int mode;
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
voidpf opaque;
voidpf stream;
void* buf;
uLong size;
{
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
voidpf opaque;
voidpf stream;
const void* buf;
uLong size;
{
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
long ZCALLBACK ftell_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
long ret;
ret = ftell((FILE *)stream);
return ret;
}
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
voidpf opaque;
voidpf stream;
uLong offset;
int origin;
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
fseek((FILE *)stream, offset, fseek_origin);
return ret;
}
int ZCALLBACK fclose_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
int ret;
ret = fclose((FILE *)stream);
return ret;
}
int ZCALLBACK ferror_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
int ret;
ret = ferror((FILE *)stream);
return ret;
}
void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}

View file

@ -0,0 +1,75 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
*/
#ifndef _ZLIBIOAPI_H
#define _ZLIBIOAPI_H
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,285 @@
/*
* 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 Library 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
# include <limits.h>
#include "unzip.h"
#include "global.h"
#define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256)
#ifndef LINUX_MODE
char *
strcasestr (const char *s1, const char *s2)
{
char *tmps1 = (char *) strupr (strdup (s1));
char *tmps2 = (char *) strupr (strdup (s2));
char *result = strstr (tmps1, tmps2);
free (tmps1);
free (tmps2);
return result;
}
# endif
static char possible_filename_in_zip[MAX_PATH];
/*!
* find_possible_filename_in_zip : Look whether the given archive contains a rom
* @param zipfilename Name of the archive file in zip format in which to search for a rom
* @return NULL in case of error or no rom found else a pointer to a statically allocated
* storage containing the filename found inside
*/
char *
find_possible_filename_in_zip (char *zipfilename, const char* ext)
{
char ext_buff[128];
uLong i;
unz_global_info gi;
unzFile uf;
int err;
if (zipfilename == NULL)
return NULL;
strcpy(ext_buff, ext);
uf = unzOpen (zipfilename);
if (uf == NULL)
{
strcat (zipfilename, ".zip");
uf = unzOpen (zipfilename);
}
if (uf == NULL)
return NULL;
err = unzGetGlobalInfo (uf, &gi);
if (err != UNZ_OK)
{
unzClose( uf );
return NULL;
}
for (i = 0; i < gi.number_entry; i++)
{
char filename_inzip[256];
unz_file_info file_info;
err = unzGetCurrentFileInfo (uf, &file_info, filename_inzip,
sizeof (filename_inzip), NULL, 0, NULL, 0);
if (err != UNZ_OK)
{
unzClose( uf );
return NULL;
}
const char* strtok_ext = ext_buff;
const char* scan_ext;
while ( (scan_ext = strtok( strtok_ext, ".")) != 0) {
strtok_ext = 0;
if (strcasestr(filename_inzip, scan_ext))
{
strncpy (possible_filename_in_zip, filename_inzip, MAX_PATH);
unzClose( uf );
return possible_filename_in_zip;
}
}
if ((i + 1) < gi.number_entry)
{
err = unzGoToNextFile (uf);
if (err != UNZ_OK)
{
unzClose( uf );
return NULL;
}
}
}
unzClose( uf );
return NULL;
}
/*!
* do_extract_currentfile_in_memory : Extract the current pointed file in the zip archive into a buffer
* @param uf the archive file handle
* @param unzipped_size a pointer to the size of the unzipped data, it is filled by this function for caller
* @return uncompressed data as pointer, to be freed by caller or NULL in case of problem
*/
static char *
do_extract_currentfile_in_memory (unzFile uf, size_t * unzipped_size)
{
char filename_inzip[256];
char *filename_withoutpath;
char *p;
int err = UNZ_OK;
FILE *fout = NULL;
void *buf;
uInt size_buf;
unz_file_info file_info;
char *return_value = NULL;
err = unzGetCurrentFileInfo (uf, &file_info, filename_inzip,
sizeof (filename_inzip), NULL, 0, NULL, 0);
if (err != UNZ_OK)
{
//Log ("error %d with zipfile in unzGetCurrentFileInfo\n", err);
return NULL;
}
size_buf = WRITEBUFFERSIZE;
buf = (void *) malloc (size_buf);
if (buf == NULL)
{
//Log ("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
p = filename_withoutpath = filename_inzip;
while ((*p) != '\0')
{
if (((*p) == '/') || ((*p) == '\\'))
filename_withoutpath = p + 1;
p++;
}
if ((*filename_withoutpath) != '\0')
{
const char *write_filename;
int skip = 0;
write_filename = filename_withoutpath;
err = unzOpenCurrentFile (uf);
if (err != UNZ_OK)
{
//Log ("error %d with zipfile in unzOpenCurrentFile\n", err);
return NULL;
}
*unzipped_size = 0;
do
{
err = unzReadCurrentFile (uf, buf, size_buf);
if (err < 0)
{
//Log ("error %d with zipfile in unzReadCurrentFile\n", err);
break;
}
if (err > 0)
{
*unzipped_size += err;
return_value = realloc (return_value, *unzipped_size);
if (return_value == NULL)
{
err = UNZ_ERRNO;
break;
}
memcpy (return_value + *unzipped_size - err, buf, err);
}
}
while (err > 0);
if (err != UNZ_OK)
{
//Log ("Error %s with zipfile in uncompressing\n", strerror (errno));
}
err = unzCloseCurrentFile (uf);
if (err != UNZ_OK)
{
//Log ("error %d with zipfile in unzCloseCurrentFile\n", err);
}
}
free (buf);
return return_value;
}
/*!
* do_extract_onefile_in_memory : Extract an archived file into a buffer
* @param uf Handle to the archive in ip format in which to read data
* @param filename Name of the file archived in the zip file the data of which we want
* @param unzipped_size Pointer to the size of the extracted data
* @return NULL in case of problem or a pointer to the archived file content. It is allocated
*/
static char *
do_extract_onefile_in_memory (unzFile uf, const char *filename,
size_t * unzipped_size)
{
if (unzLocateFile (uf, filename, CASESENSITIVITY) != UNZ_OK)
{
//Log ("file %s not found in the zipfile\n", filename);
return NULL;
}
return do_extract_currentfile_in_memory (uf, unzipped_size);
}
/*!
* extract_file_in_memory : Extract an archived file into a buffer
* @param zipfilename Name of the archive in zip format in which to read data
* @param archivedfile Name of the file archived in the zip file the data of which we want
* @param unzipped_size Pointer to the size of the extracted data
* @return NULL in case of problem or a pointer to the archived file content. It is allocated
* dynamically and needs to be explicitely freed
*/
extern char *
extract_file_in_memory (char *zipfilename, char *archivedfile, size_t * unzipped_size)
{
unzFile uf;
int err;
char *return_value;
if (zipfilename == NULL)
return NULL;
uf = unzOpen (zipfilename);
if (uf == NULL)
{
strcat (zipfilename, ".zip");
uf = unzOpen (zipfilename);
}
if (uf == NULL)
return NULL;
return_value =
do_extract_onefile_in_memory (uf, archivedfile, unzipped_size);
unzCloseCurrentFile (uf);
unzClose(uf);
return return_value;
}

View file

@ -0,0 +1,26 @@
/*
* 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 Library 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 MINIUNZ_H
#define MINIUNZ_H
//! Look for possible filename in zip archive
char *find_possible_filename_in_zip (char *zipfilename, const char* extstr);
//! Extract file content from zip archive
int extract_file_in_memory (char *zipfilename, char *archivedfile,
size_t * unzipped_size);
#endif

1299
arm9/source/emu/zip/unzip.c Normal file

File diff suppressed because it is too large Load diff

275
arm9/source/emu/zip/unzip.h Normal file
View file

@ -0,0 +1,275 @@
/* unzip.h -- IO for uncompress .zip files using zlib
Version 0.15 beta, Mar 19th, 1998,
Copyright (C) 1998 Gilles Vollant
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported.
Old compressions used by old PKZip 1.x are not supported
THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
CAN CHANGE IN FUTURE VERSION !!
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip */
#ifndef _unz_H
#define _unz_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unzFile__;
typedef unzFile__ *unzFile;
#else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info_s
{
uLong number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
uLong compressed_size; /* compressed size 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
"zlib/zlib111.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
*/
extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
unz_global_info *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of byte copied if somes bytes are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern z_off_t ZEXPORT unztell OF((unzFile file));
/*
Give the current position in uncompressed data
*/
extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf, or (if <0)
the error code
*/
#ifdef __cplusplus
}
#endif
#endif /* _unz_H */

1219
arm9/source/emu/zip/zip.c Normal file

File diff suppressed because it is too large Load diff

235
arm9/source/emu/zip/zip.h Normal file
View file

@ -0,0 +1,235 @@
/* zip.h -- IO for compress .zip files using zlib
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
For uncompress .zip file, look at unzip.h
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
*/
#ifndef _zip_H
#define _zip_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level));
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCtypting));
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCtypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf,
unsigned len));
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size,
uLong crc32));
/*
Close the current file in the zipfile, for fiel opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment));
/*
Close the zipfile
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip_H */

View file

@ -1,9 +1,7 @@
#include <nds.h>
#include <stdio.h>
#include <maxmod9.h>
#include "a7800utils.h"
#include "soundbank.h"
#include "mus_intro_wav.h"
#include "pdev_tbg0.h"
@ -17,6 +15,7 @@ void vblankIntro() {
// Intro with portabledev logo
void intro_logo(void) {
int soundId=-1;
bool bOK;
// Init graphics
@ -35,8 +34,6 @@ void intro_logo(void) {
REG_BLDCNT = BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0; REG_BLDY = 16;
REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0; REG_BLDY_SUB = 16;
mmEffect(SFX_MUS_INTRO);
// Show portabledev
decompress(pdev_tbg0Tiles, bgGetGfxPtr(bg1), LZ77Vram);
decompress(pdev_tbg0Map, (void*) bgGetMapPtr(bg1), LZ77Vram);
@ -48,6 +45,8 @@ void intro_logo(void) {
FadeToColor(0,BLEND_FADE_BLACK | BLEND_SRC_BG0 | BLEND_DST_BG0,3,0,3);
soundId = soundPlaySample((const void *) mus_intro_wav, SoundFormat_ADPCM, mus_intro_wav_size, 22050, 127, 64, false, 0);
bOK=false;
while (!bOK) { if ( !(keysCurrent() & 0x1FFF) ) bOK=true; } // 0x1FFF = key or pen
vusCptVBL=0;bOK=false;
@ -56,4 +55,5 @@ void intro_logo(void) {
while (!bOK) { if ( !(keysCurrent() & 0x1FFF) ) bOK=true; }
FadeToColor(1,BLEND_FADE_WHITE | BLEND_SRC_BG0 | BLEND_DST_BG0,3,16,3);
if (soundId!=-1) soundKill(soundId);
}

View file

@ -1,40 +1,10 @@
// =====================================================================================
// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, it's source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and wavemotion-dave (Phoenix-Edition),
// Alekmaul (original port) and Greg Stanton (ProSystem Emulator) are thanked profusely.
//
// A7800DS emulator is offered as-is, without any warranty.
//
// The original GPL license:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// =====================================================================================
#include <stdio.h>
#include <time.h>
#include <fat.h>
#include <nds.h>
#include <maxmod9.h>
#include "main.h"
#include "intro.h"
#include "config.h"
#include "a7800utils.h"
#include "soundbank.h"
// Program entry point
int main(int argc, char **argv)
@ -58,26 +28,14 @@ int main(int argc, char **argv)
// Intro and main screen
intro_logo();
dsInitScreenMain();
emu_state = A7800_MENUINIT;
srand(time(NULL));
LoadConfig();
bios_check_and_load();
etatEmu = A7800_MENUINIT;
//load rom file via args if a rom path is supplied
if(argc > 1)
{
dsShowScreenMain(true);
dsShowScreenMain();
dsLoadGame(argv[1]);
emu_state = A7800_PLAYINIT;
}
else
{
chdir("/roms"); // Try to start in roms area... doesn't matter if it fails
chdir("a7800"); // And try to start in the subdir /a7800... doesn't matter if it fails.
chdir("a78"); // And try to start in the subdir /a78... doesn't matter if it fails.
etatEmu = A7800_PLAYINIT;
}
// Main loop of emulation

View file

@ -1,29 +1,3 @@
// =====================================================================================
// Copyright (c) 2022-2024 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, it's source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and wavemotion-dave (Phoenix-Edition),
// Alekmaul (original port) and Greg Stanton (ProSystem Emulator) are thanked profusely.
//
// A7800DS emulator is offered as-is, without any warranty.
//
// The original GPL license:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// =====================================================================================
#ifndef _MAIN_H
#define _MAIN_H

View file

@ -1,914 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h>
#include "printf.h"
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
// printf_config.h header file
// default: undefined
#ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
#define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
// output function type
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
// internal buffer output
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
// internal null output
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
// internal _putchar wrapper
static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)buffer; (void)idx; (void)maxlen;
if (character) {
_putchar(character);
}
}
// internal output function wrapper
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)idx; (void)maxlen;
if (character) {
// buffer is the output fct pointer
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
value /= conv.F;
}
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
// internal vsnprintf
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
if (!buffer) {
// use null output function
out = _out_null;
}
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
// return written chars without terminating \0
return (int)idx;
}
///////////////////////////////////////////////////////////////////////////////
int printf_(const char* format, ...)
{
va_list va;
va_start(va, format);
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int sprintf_(char* buffer, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int snprintf_(char* buffer, size_t count, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
va_end(va);
return ret;
}
int vprintf_(const char* format, va_list va)
{
char buffer[1];
return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
}
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va)
{
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...)
{
va_list va;
va_start(va, format);
const out_fct_wrap_type out_fct_wrap = { out, arg };
const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
va_end(va);
return ret;
}

View file

@ -1,121 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _PRINTF_H_
#define _PRINTF_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_DISABLE_SUPPORT_PTRDIFF_T
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
void _putchar(char character);
/**
* Tiny printf implementation
* You have to implement _putchar if you use printf()
* To avoid conflicts with the regular printf() API it is overridden by macro defines
* and internal underscore-appended functions like printf_() are used
* \param format A string that specifies the format of the output
* \return The number of characters that are written into the array, not counting the terminating null character
*/
#define printf printf_
int printf_(const char* format, ...);
/**
* Tiny sprintf implementation
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define sprintf sprintf_
int sprintf_(char* buffer, const char* format, ...);
/**
* Tiny snprintf/vsnprintf implementation
* \param buffer A pointer to the buffer where to store the formatted string
* \param count The maximum number of characters to store in the buffer, including a terminating null character
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
* null character. A value equal or larger than count indicates truncation. Only when the returned value
* is non-negative and less than count, the string has been completely written.
*/
#define snprintf snprintf_
#define vsnprintf vsnprintf_
int snprintf_(char* buffer, size_t count, const char* format, ...);
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va);
/**
* Tiny vprintf implementation
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define vprintf vprintf_
int vprintf_(const char* format, va_list va);
/**
* printf with output function
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
* \param out An output function which takes one character and an argument pointer
* \param arg An argument pointer for user data passed to output function
* \param format A string that specifies the format of the output
* \return The number of characters that are sent to the output function, not counting the terminating null character
*/
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
#ifdef __cplusplus
}
#endif
#endif // _PRINTF_H_

View file

@ -1,6 +0,0 @@
#define SFX_CLICKNOQUIT 0
#define SFX_KEYCLICK 1
#define SFX_MUS_INTRO 2
#define MSL_NSONGS 0
#define MSL_NSAMPS 3
#define MSL_BANKSIZE 3

BIN
logo.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 630 B

After

Width:  |  Height:  |  Size: 630 B

84
readme.txt Normal file
View file

@ -0,0 +1,84 @@
a7800DS
--------------------------------------------------------------------------------
a7800DS is an Atari ProSystem 7800 console emulator.
To use this emulator, you must use compatibles rom with a78/bin format.
Do not ask me about such files, I don't have them. A search with Google will certainly
help you.
Features :
----------
Most things you should expect from an emulator.
Missing :
---------
All that is not yet emulated ;)
Need to improve speed
Check updates on my web site :
http://www.portabledev.com
--------------------------------------------------------------------------------
History :
--------------------------------------------------------------------------------
V1.4 : 13-Dec-2020 by wavemotion-dave
* Implemented Hiscore Saving per the HSC cart. Put the 4k highscore.rom (don't ask)
where your ROMs live. If found, it will enable saving of high scores
on all 9 original games (Asteroids, Joust, Centipede, Xevious, Dig Dug, Galaga,
Food Fight, Ms Pac-Man and Robotron) as well as most of the newer homebrews.
V1.3 : 12-Dec-2020 by wavemotion-dave
* Backported some fixes and emulation timing improvments from Prosystem 1.3g
plus the Wii version. Renders a few more games playable.
* Fixed region for Froggie and Beef Drop - they now look right and play
at full speed.
* Minor other improvements as time permitted.
V1.2 : 10-Dec-2020 by wavemotion-dave
* More speed improvements. Fixed some 320 pixel games. Improved sound.
V1.1 : 09-Dec-2020 by wavemotion-dave
* Brought back to life... cleanup and about a 50% speed improvement, better
screen rendering/scaling and slightly improved UI features.
V1.0 : 24/05/2011
* Initial release based on my a320 version (which is based on Prosystem 1.0.3)
* Compiled with last version of Devkitpro/libnds, so DSi compatible \o/
--------------------------------------------------------------------------------
How tu use a7800DS :
--------------------------------------------------------------------------------
YOU NEED PERHAPS TO PATCH THE NDS FILE WITH THE DLDI PATCH BEFORE USING IT.
Unzip a7800DS.nds from the a7800DS.zip archive in a directory of your flash / (micro) SD
/ MMC card.
Put the a78/bin files where you want on your flashcard.
That's all, a7800DS can be use now :) !
When the emulator starts, click on the cartridge slot to choose a file. you are use Up/Down
to select a file, then use A to load it.
Controls :
* Direction pad : the joystick ...
* A : Fire button 1
* B : Fire button 2
* SELECT : SELECT Button
* START : START Button
* R : RESET Button (yes R like Reset :P)
Use stylus on buttons for other actions on bottom screen.
--------------------------------------------------------------------------------
Credits:
--------------------------------------------------------------------------------
Thanks Wintermute for devkitpro and libnds (http://www.devkitpro.org).
Greg Stanton for ProSystem source code (https://home.comcast.net/~gscottstanton/)
an Atari 7800 emulator.
zx81 (http://zx81.zx81.free.fr/serendipity_fr/) for PSP A7800 version (that helped
me a lot to understand ProSystem).
raz0red (http://www.twitchasylum.com/forum/viewtopic.php?t=519) for WII7800 (that
helped me a lot to fix some timing problem).
--------------------------------------------------------------------------------
Alekmaul
alekmaul@portabledev.com
http://www.portabledev.com
--------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

View file

@ -1,192 +0,0 @@
; A78 Header v4.2
;
; Use this file to add an a78 header via the source code of your ROM.
;
; _Implementation Notes_
;
; * Include this header near the beginning of your DASM source, but after
; your initial ROM ORG statement.
; * Change the fields withn the file to describe your game's hardware
; requirements to emulators and flash carts.
; * All unused/reserved bits and bytes must be set to zero.
.ROMSIZE = $20000 ; Update with your total ROM size.
; Uncomment the following entry to force older v3 style headers.
;V3ONLY = 1
; Uncomment the following entry to break support with platforms that only
; have v3 headers implemented.
;V4ONLY = 1
; Auto-header ROM allocation follows. If the current address is page aligned,
; we backup 128 bytes. This may cause issues if you use a different ORG+RORG
; at the start of your ROM - in that case, account for the 128 bytes of
; header within your game ROM start ORG+RORG statements.
if ( . & $FF ) = 0 ; Check if we're at an even page.
ORG (. - 128),0 ; If so, go -128 bytes, for header space.
else
ORG .,0 ; In case zero-fill wasn't specified
endif ; orginally.
SEG ROM
.HEADER = .
; Format detection - do not modify.
#ifconst V3ONLY
DC.B 3 ; 0 header major version
#else
DC.B 4 ; 0 header major version
#endif ; V3ONLY
DC.B "ATARI7800" ; 1..16 header magic string - zero pad
ORG .HEADER+$11,0
DC.B "Game Name Here" ; 17..48 cartridge title string - zero pad
ORG .HEADER+$31,0
DC.B (.ROMSIZE>>24) ; 49..52 cartridge ROM size
DC.B (.ROMSIZE>>16&$FF)
DC.B (.ROMSIZE>>8&$FF)
DC.B (.ROMSIZE&$FF)
#ifnconst V4ONLY
; The following 2 cartridge type bytes are deprecated as of header v4.0.
; It's recommended that you still populate these bytes for support with
; platforms that don't yet support v4.
DC.B %00000000 ; 53 cartridge type A
DC.B %00000000 ; 54 cartridge type B
; _Cartridge Type A_
; bit 7 ; POKEY @ $0800 - $080F
; bit 6 ; EXRAM/M2 (halt banked RAM)
; bit 5 ; BANKSET
; bit 4 ; SOUPER
; bit 3 ; YM2151 @ $0460 - $0461
; bit 2 ; POKEY @ $0440 - $044F
; bit 1 ; ABSOLUTE
; bit 0 ; ACTIVISION
; _Cartridge Type B_
; bit 7 ; EXRAM/A8 (mirror RAM)
; bit 6 ; POKEY @ $0450 - $045F
; bit 5 ; EXRAM/X2 (hotspot banked RAM)
; bit 4 ; EXFIX (2nd last bank @ $4000)
; bit 3 ; EXROM (ROM @ $4000)
; bit 2 ; EXRAM (RAM @ $4000)
; bit 1 ; SUPERGAME
; bit 0 ; POKEY @ $4000 - $7FFF
#else
DC.B %11111111
DC.B %11111111
#endif ; !V4ONLY
DC.B 1 ; 55 controller 1 device type
DC.B 1 ; 56 controller 2 device type
; 0 = none
; 1 = 7800 joystick
; 2 = lightgun
; 3 = paddle
; 4 = trakball
; 5 = 2600 joystick
; 6 = 2600 driving
; 7 = 2600 keypad
; 8 = ST mouse
; 9 = Amiga mouse
; 10 = AtariVox
; 11 = SNES2Atari
; 12 = Mega7800
DC.B %00000000 ; 57 tv type
; bits 7..3 ; reserved
; bit 2 ; 0:single-region,1:multi-region
; bit 1 ; 0:component,1:composite
; bit 0 ; 0:NTSC,1:PAL
DC.B %00000000 ; 58 save peripheral
; bits 7..2 ; reserved
; bit 1 ; SaveKey/AtariVox
; bit 0 ; High Score Cart (HSC)
; The following irq source byte is deprecated as of header v4.0.
; It's recommended that you still populate this byte for support with
; platforms that don't yet support v4.
ORG .HEADER+62,0
DC.B %00000000 ; 62 external irq source
; bits 7..5 ; reserved
; bit 4 ; POKEY @ $0800 - $080F
; bit 3 ; YM2151 @ $0460 - $0461
; bit 2 ; POKEY @ $0440 - $044F
; bit 1 ; POKEY @ $0450 - $045F
; bit 0 ; POKEY @ $4000 - $7FFF
DC.B %00000000 ; 63 slot passthrough device
; bits 7..1 ; reserved
; bit 0 ; XM module
#ifnconst V3ONLY
; The following 6 bytes are v4 header specific. You should populate
; them with valid info if you're not using V3ONLY, because they will
; take precedence over v3 headers.
DC.B 0 ; 64 mapper
; 0 = linear
; 1 = supergame
; 2 = activision
; 3 = absolute
; 4 = souper
DC.B 0 ; 65 mapper options
; linear_
; bit 7 ; bankset rom
; bits 0-1 ; option @4000...
; 0 = none
; 1 = 16K EXRAM
; 2 = 8K EXRAM/A8
; 3 = 32K EXRAM/M2
; supergame_
; bit 7 ; bankset rom
; bits 0-2 ; option @4000...
; 0 = none
; 1 = 16K EXRAM
; 2 = 8K EXRAM/A8
; 3 = 32K EXRAM/M2
; 4 = 16K EXROM
; 5 = EXFIX
; 6 = 32K EXRAM/X2
DC.B %00000000 ; 66 audio hi
DC.B %00000000 ; 67 audio lo
; bit 5 ; adpcm@420
; bit 4 ; covox@430
; bit 3 ; ym2151@460
; bits 0-2 ; pokey...
; 0 = none
; 1 = pokey@440
; 2 = pokey@450
; 3 = dual pokey @440+@450
; 4 = pokey@800
; 5 = pokey@4000
DC.B %00000000 ; 68 interrupt hi
DC.B %00000000 ; 69 interrupt lo
; bit 2 ; YM2151
; bit 1 ; pokey 2 (@440)
; bit 0 ; pokey 1 (@4000, @450, or @800)
#endif ; !V3ONLY
ORG .HEADER+100,0 ; 100..127 footer magic string
DC.B "ACTUAL CART DATA STARTS HERE"