diff --git a/.gitignore b/.gitignore index 5524d520a..8e6d3e86a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,5 @@ src/**/*.psess src/**/*.vspx src/**/**.pdb Stella.xcscheme +src/tools/fonts/* + diff --git a/Announce.txt b/Announce.txt index 18f636c79..2262f7975 100644 --- a/Announce.txt +++ b/Announce.txt @@ -9,7 +9,7 @@ SSSS ttt eeeee llll llll aaaaa =========================================================================== - Release 6.1 for Linux, macOS and Windows + Release 6.2.1 for Linux, macOS and Windows =========================================================================== The Atari 2600 Video Computer System (VCS), introduced in 1977, was the @@ -21,27 +21,27 @@ all of your favourite Atari 2600 games again! Stella was originally developed for Linux by Bradford W. Mott, however, it has been ported to a number of other platforms and is currently maintained by Stephen Anthony. -This is the 6.1 release of Stella for Linux, macOS and Windows. The +This is the 6.2.1 release of Stella for Linux, macOS and Windows. The distributions currently available are: * Binaries for Windows Vista/7/8/10 : - Stella-6.1-win32.exe (32-bit EXE installer) - Stella-6.1-x64.exe (64-bit EXE installer) - Stella-6.1-windows.zip (32/64 bit versions) + Stella-6.2.1-win32.exe (32-bit EXE installer) + Stella-6.2.1-x64.exe (64-bit EXE installer) + Stella-6.2.1-windows.zip (32/64 bit versions) * Binary distribution for macOS 10.7 and above : - Stella-6.1-macos.dmg (64-bit Intel) + Stella-6.2.1-macos.dmg (64-bit Intel) * Binary distribution in 32-bit & 64-bit Ubuntu DEB format : - stella_6.1-1_i386.deb - stella_6.1-1_amd64.deb + stella_6.2.1-1_i386.deb + stella_6.2.1-1_amd64.deb * Binary distribution in 32-bit & 64-bit RPM format : - stella-6.1-2.i386.rpm - stella-6.1-2.x86_64.rpm + stella-6.2.1-2.i386.rpm + stella-6.2.1-2.x86_64.rpm * Source code distribution for all platforms : - stella-6.1-src.tar.xz + stella-6.2.1-src.tar.xz Distribution Site diff --git a/Changes.txt b/Changes.txt index 3ca8e06c5..9db31b627 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,7 +12,155 @@ Release History =========================================================================== -6.0.2 to 6.1: (MM dd, 2020) +6.2.1 to 6.3 (XXXX XX, 2020) + + * Added adjustable autofire. + + * Added 'Dark' UI theme. (TODO: DOC) + + * Extended global hotkeys for debug options. + + * Added option to playback a game using the Time Machine. + + * Allow taking snapshots from within the Time Machine dialog. + + * Added the ability to access most files that Stella uses from within a + ZIP file. This includes the following: + - Per-ROM properties file (so one can distribute a ROM and its + associated properties). + - Debugger symbol (.sym) and list (.lst) files, etc. + - Several others, as we extend the support. + Basically, you are now able to put many files that Stella uses inside + one ZIP file, and distribute just that file. + + * Added option to select the audio device. + + * Added option to display detected settings info when a ROM is loaded. + + * Replaced "Re-disassemble" with "Disassemble @ current line" in debugger. + + * Fixed bug when taking fullscreen snapshots; the dimensions were + sometimes cut off. + +-Have fun! + + +6.2 to 6.2.1: (June 20, 2020) + + * Fixed Pitfall II ROM not working correctly. + + * Fixed crashes when using some combinations of bankswitching schemes on + incorrect ROMs, or when using invalid ROM file sizes, etc. + + * Fixed RIOT timer behaviour on reading/writing at the wraparound cycle. + + * Fixed incorrectly setting D6 bit on TIA reads in some cases. Related + to this, improve 'tiadriven' option to randomize only D5..D0 bits. + + * Fixed custom palette and TV effects adjustable slider rounding issue. + + * Fixed some bugs in 3E+ scheme when using non-standard ROM sizes. + + * Fixed crash in Audio & Video dialog when opened from debugger, and the + debugger window sometimes being resized when using the Options dialog. + + * Make NTSC custom phase shift not affect Yellow anymore. + + * Fixed '1x' snapshot mode; TV effects are now disabled. This mode + now generates a clean, pixel-exact image. + + * Fixed mappings sometimes not being saved in the Retron77 port. + + * A ROM properties file may now be placed next to the ROM (with the same + name as the ROM, except ending in .pro), and Stella will automatically + apply the properties to the ROM. [NOTE: this was present in 6.2, but + was mistakenly left out of the changelog] + + * Added button to Game Info dialog to save properties of the currently + loaded ROM to a separate properties file (in the default save directory). + This is useful in conjunction with the previous item. + + * Allow changing custom palette and TV effects adjustables in 1% steps + again. + + * Updated documentation for changes in ROM properties key names. + + * The codebase now compiles under gcc6 again. Future versions will + require gcc7, though. + + +6.1.2 to 6.2: (June 7, 2020) + + * Added interactive palette to Video & Audio settings. + + * Added 'Custom' palette, generated from user controlled phase shifts. + + * Added that adjustable audio & video settings are displayed as gauge bars. + + * Added four global hotkeys which allow selecting and changing numerous + audio & video settings without having to remember the dedicated hotkeys. + + * Added 'Turbo' mode, runs the game as fast as the computer allows. + + * Added that paddle centering (per ROM) and sensitivity can be adjusted. + + * Added that mouse sensitivity for Driving controller can be adjusted. + + * Added paddle filtering in UI to avoid unwanted navigation events. + + * Added selectable dialog fonts. + + * Added separate positioning of launcher, emulator and debugger. + + * Added optional display to game refresh rate adaption in fullscreen mode. + + * Added option which lets default ROM path follow launcher navigation. + + * Added debugger 'saveaccess' function, which saves memory access counts to + a CSV file. + + * Added displaying last write address in the debugger. + + * Added debugger pseudo-register '_scanend', which gives the number of + scanlines at the end of the last frame. + + * Added detection of color and audio data in DiStella. + + * Restored 'cfg' directory for Distella config files. + + * Added TV Boy and 3EX bank switching types. + + * Removed unused CV+ and DASH bank switching types. + + * Added support for loading grayscale PNG images in the ROM launcher. + + +6.1.1 to 6.1.2: (April 25, 2020) + + * Fixed bug with remapped events not being reloaded in certain cases. + + * Fixed bug in debugger for 3E scheme when displaying active RAM bank. + + * Fixed bug in "Dragon Defender" ROM being misconfigured for Mindlink + controller. + + +6.1 to 6.1.1: (April 4, 2020) + + * Fixed crash in 3E bankswitching scheme when writing to ROM addresses. + + * Fix snapshots on Retina HiDPI displays capturing only the top-left + corner. + + * Fixed wrong color for BK (background) swatch in the debugger. + + * Fixed 'Right Diff' button in Command menu changing left difficulty + instead. + + * Fixed compilation of libretro port on Debian Buster. + + +6.0.2 to 6.1: (March 22, 2020) * IMPORTANT NOTES: - Because of major event remapping changes, all remappings will be reset @@ -119,7 +267,9 @@ * Added option to change pitch of Pitfall II music. - * ROM Info Launcher can now display multiple lines per property and + * ROM Info Viewer size is not limited to fixed zoom steps anymore. + + * ROM Info Viewer can now display multiple lines per property and the bank switching type. * In file listings, you can now select directories by holding 'Shift' on @@ -179,6 +329,10 @@ * Fixed bug in DPC+ scheme; 'fast fetch mode' was enabled at startup, when it should be disabled by default. + * Some more work on DPC+ playfield 'jitter' effect for certain older DPC+ + driver versions; more ROMs are now detected properly. Special thanks + to SpiceWare for his research in this area. + * Added proper Retron77 port. * Added proper libretro port, and fixed display for OpenGLES renderers. @@ -192,7 +346,8 @@ * Updated included PNG library to latest stable version. --Have fun! + * Updated UNIX configure script to work with the gcc version 10 and + above. 6.0.1 to 6.0.2: (October 11, 2019) diff --git a/Makefile b/Makefile index b0e41062b..08cfc640c 100644 --- a/Makefile +++ b/Makefile @@ -8,14 +8,11 @@ ## SS SS tt ee ll ll aa aa ## SSSS ttt eeeee llll llll aaaaa ## -## Copyright (c) 1995-2016 by Bradford W. Mott, Stephen Anthony +## Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony ## and the Stella Team ## ## See the file "License.txt" for information on usage and redistribution of ## this file, and for a DISCLAIMER OF ALL WARRANTIES. -## -## Based on code from ScummVM - Scumm Interpreter -## Copyright (C) 2002-2004 The ScummVM project ##============================================================================ ####################################################################### @@ -99,7 +96,7 @@ EXECUTABLE := stella$(EXEEXT) EXECUTABLE_PROFILE_GENERATE := stella-pgo-generate$(EXEEXT) EXECUTABLE_PROFILE_USE := stella-pgo$(EXEEXT) -PROFILE_DIR = $(CURDIR)/profile +PROFILE_DIR = $(CURDIR)/test/roms/profile PROFILE_OUT = $(PROFILE_DIR)/out PROFILE_STAMP = profile.stamp diff --git a/appveyor.yml b/appveyor.yml index a087f4e42..211b69a24 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,15 +7,15 @@ environment: matrix: - Platform: x64 - Platform: Win32 - + Configuration: Release - SDL2_version: 2.0.10 + SDL2_version: 2.0.12 install: - cmd: | - curl -o "C:\SDL2-devel.zip" https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip + curl -o "C:\SDL2-devel.zip" "https://www.libsdl.org/release/SDL2-devel-%SDL2_version%-VC.zip" 7z x "C:\SDL2-devel.zip" -o"C:\" xcopy /S "C:\SDL2-%SDL2_version%\include" src\common diff --git a/configure b/configure index 85c81550a..4fb2cf08d 100755 --- a/configure +++ b/configure @@ -458,11 +458,17 @@ elif test "$have_gcc" = yes; then fi case $cxx_version in - 4.[7-9]|4.[7-9].[0-9]|4.[7-9].[0-9][-.]*|[5-9]|[5-9].[0-9]|[5-9].[0-9].[0-9]|[5-9].[0-9].[0-9][-.]*) + [1-9]*) _cxx_major=`echo $cxx_version | cut -d '.' -f 1` _cxx_minor=`echo $cxx_version | cut -d '.' -f 2` - cxx_version="$cxx_version, ok" - cxx_verc_fail=no + # Need at least version 4.7 + if [ $_cxx_major -ge 5 ] || [ $_cxx_major -eq 4 -a $_cxx_minor -ge 7 ]; then + cxx_version="$cxx_version, ok" + cxx_verc_fail=no + else + cxx_version="$cxx_version, bad" + cxx_verc_fail=yes + fi ;; 'not found') cxx_verc_fail=yes diff --git a/debian/changelog b/debian/changelog index 3d045e4ef..75c7267b6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,38 @@ +stella (6.2.1-1) stable; urgency=high + + * Version 6.2.1 release + + -- Stephen Anthony Sat, 20 Jun 2020 17:09:59 -0230 + + +stella (6.2-1) stable; urgency=high + + * Version 6.2 release + + -- Stephen Anthony Sun, 7 Jun 2020 17:09:59 -0230 + + +stella (6.1.2-1) stable; urgency=high + + * Version 6.1.2 release + + -- Stephen Anthony Sat, 25 Apr 2020 17:09:59 -0230 + + +stella (6.1.1-1) stable; urgency=high + + * Version 6.1.1 release + + -- Stephen Anthony Sat, 04 Apr 2020 17:09:59 -0230 + + +stella (6.1-1) stable; urgency=high + + * Version 6.1 release + + -- Stephen Anthony Sun, 22 Mar 2020 17:09:59 -0230 + + stella (6.0.2-1) stable; urgency=high * Version 6.0.2 release diff --git a/docs/debugger.html b/docs/debugger.html index 19af56cdf..781d05bf5 100644 --- a/docs/debugger.html +++ b/docs/debugger.html @@ -15,7 +15,7 @@
Stella
-

Release 6.1

+

Release 6.2.1

Integrated Debugger

(a work in progress)


@@ -121,13 +121,14 @@ feature that no other 2600 debugger has; it's completely cross-platform.<
  • Supports Distella 'configuration directives', which may be used to override automatic code/data determination in the disassembly. For now, - the following directives are supported: CODE, GFX, PGFX, DATA, ROW. - These directives can be entered at the debugger prompt, or (automatically) + the following directives are supported: CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. + These directives can be entered at the debugger prompt, or be (automatically) loaded and saved in configuration files.
  • Extensive disassembly support, both from the emulation core and with help from Distella. Where possible, the disassembly differentiates between code, - player graphics and playfield graphics (ie, addresses stored in GRPx and PFx) + player and playfield graphics, colors and audio (ie, addresses stored in + GRPx, PFx, COLUxx, AUDxx) and data (addresses used as an operand of a command). Code sections are also differentiated between actual code, and 'tentative' code (ie, areas that may represent code sections, but haven't actually been executed yet). Such @@ -330,7 +331,7 @@ previous rewind operation. The rewind buffer is 100 levels deep by default, the size can be configured e.g. in the Developer Settings - Time Machine dialog.

    -

    The other operations are Step, Trace, Scan+1, Frame+1 and Exit (debugger).

    +

    The other operations are Step, Trace, Scan+1, Frame+1 and Run.

    You can also use the buttons from anywhere in the GUI via hotkeys.

    @@ -381,12 +382,12 @@ size can be configured e.g. in the Backquote (`) - Exit + Run

    For MacOS use 'Cmd' instead of  'Alt' key. -

    To the left of the global buttons, you find the "Options..." button.

    +

    To the left of the global buttons, you find the 'Options...' button.

    @@ -607,7 +608,7 @@ created a symbol file, you can use labels for the expression.

    Example: You have got a label called "kernel". To break there, the command is "break kernel". After you've set the breakpoint, -exit the debugger ("quit" or click the Exit button). The emulator +exit the debugger (enter "run" or click the 'Run' button). The emulator will run until it gets to the breakpoint, then it will enter the debugger with the Program Counter pointing to the instruction at the breakpoint.

    @@ -754,6 +755,7 @@ that holds 'number of scanlines' on an actual console).

    _fcycles Number of cycles since frame started _icycles Number of cycles of last instruction _scan Current scanline count + _scanend Scanline count at end of last frame _scycles Number of cycles in current scanline _vblank Whether vertical blank is enabled (1 or 0) _vsync Whether vertical sync is enabled (1 or 0) @@ -906,7 +908,9 @@ Type "help 'cmd'" to see extended information about the given command.

                     a - Set Accumulator to <value>
    +              aud - Mark 'AUD' range in disassembly
                  base - Set default number base to <base> (bin, dec, hex)
    +             bcol - Mark 'BCOL' range in disassembly
                 break - Set/clear breakpoint at <address> and <bank>
               breakif - Set/clear breakpoint on <condition>
            breaklabel - Set/clear breakpoint on <address> (no mirrors, all banks)
    @@ -919,6 +923,7 @@ clearsavestateifs - Clear all savestate points
          clearwatches - Clear all watches
                   cls - Clear prompt area of text
                  code - Mark 'CODE' range in disassembly
    +              col - Mark 'COL' range in disassembly
             colortest - Show value xx as TIA color
                     d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
                  data - Mark 'DATA' range in disassembly
    @@ -959,6 +964,7 @@ clearsavestateifs - Clear all savestate points
                     n - Negative Flag: set (0 or 1), or toggle (no arg)
               palette - Show current TIA palette
                    pc - Set Program Counter to address xx
    +             pcol - Mark 'PCOL' range in disassembly
                  pgfx - Mark 'PGFX' range in disassembly
                 print - Evaluate/print expression xx in hex/dec/binary
                   ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
    @@ -972,6 +978,7 @@ clearsavestateifs - Clear all savestate points
               runtopc - Run until PC is set to value xx
                     s - Set Stack Pointer to value xx
                  save - Save breaks, watches, traps and functions to file xx
    +       saveaccess - Save access counters to CSV file
            saveconfig - Save Distella config file (with default name)
               savedis - Save Distella disassembly (with default name)
               saverom - Save (possibly patched) ROM (with default name)
    @@ -1022,8 +1029,8 @@ graphics and positions, and the playfield.

    of the displays are editable. You can even toggle individual bits in the GRP0/1 and playfield registers (remember to double-click).

    -

    The group of buttons labelled "Strobes" allows you to write to any -of the strobe registers at any time.

    +

    The buttons allow you to write to any of the strobe registers at +any time.

    The collision registers are displayed in decoded format, in a table. You can see exactly which objects have hit what. These are read-only @@ -1098,7 +1105,7 @@ or TV effects are enabled, you won't see the effects here; this shows the raw TIA image only.

    To e.g. watch the TIA draw the frame one scanline at a time, you can -use the "Scan+1" button, the prompt "scan" command or the Control-L key.

    +use the 'Scan+1' button, the prompt "scan" command or the Control-L key.

    You can also right-click anywhere in this window to show a context menu, as illustrated:

    @@ -1193,6 +1200,8 @@ the reason will be shown as follows:
  • "WTrap:" for write traps
  • "RTrapIf:" for conditional read traps
  • "WTrapIf:" for conditional write traps
  • +
  • "RWP:" for reads from write ports
  • +
  • "WRP:" for writes to read ports
  • See the Breakpoints, watches and traps... @@ -1206,7 +1215,7 @@ section for details.

    All the registers and flags are displayed, and can be changed by double-clicking on them (to the left). Flags are toggled on double-click. -Selected registers here can also be changed by using the "Data Operations" buttons, +Selected registers here can also be changed by using the 'Data Operations' buttons, further described in (J). All items are shown in hex. Any label defined for the current PC value is shown to the right. Decimal and binary equivalents are shown for SP/A/X/Y to the right (first decimal, then binary).

    @@ -1215,6 +1224,8 @@ registers. For example, consider the command 'LDA ($80),Y'. The operand of the command resolves to some address, which isn't always easy to determine at first glance. The 'Src Addr' area shows the actual resulting operand/address being used with the given opcode.

    +

    The destination address of the last write is shown besides 'Dest'.

    +

    There's not much else to say about the CPU Registers widget: if you know 6502 assembly, it's pretty self-explanatory. If you don't, well, you should learn :)

    @@ -1369,21 +1380,78 @@ can use. These are known as 'directives', and partly correspond to configuration options from the standalone Distella program. They are listed in order of decreasing hierarchy:

    - - - - - + + + + + + + + + + + + + + + + + + +
    CODEAddresses which have appeared in the program counter, or -which tentatively can appear in the program counter. These can be edited in hex.
    GFXAddresses which contain data stored in the player graphics registers -(GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which -can be edited in either hex or binary. The bitmap is shown as large blocks.
    PGFXAddresses which contain data stored in the playfield graphics registers -(PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which -can be edited in either hex or binary. The bitmap is shown as small dashes.
    DATAAddresses used as an operand for some opcode. These can be edited -in hex.
    ROWAddresses not used as any of the above. These are shown up -to 8 per line, and cannot be edited.
    + CODE + + Addresses which have appeared in the program counter, or + which tentatively can appear in the program counter. These can be edited in hex. +
    + GFX + + Addresses which contain data stored in the player graphics registers + (GRP0/GRP1). These addresses are shown with a bitmap of the graphics, which + can be edited in either hex or binary. The bitmap is shown as large blocks. +
    + PGFX + + Addresses which contain data stored in the playfield graphics registers + (PF0/PF1/PF2). These addresses are shown with a bitmap of the graphics, which + can be edited in either hex or binary. The bitmap is shown as small dashes. +
    + COL + + Addresses which contain data stored in the player color registers + (COLUP0/COLUP1). These addresses are shown as color constants, which + can be edited in hex. The color constant names are depending on the ROM's TV type. +
    + PCOL + + Addresses which contain data stored in the playfield color register + (COLUPF). These addresses are shown as color constants, which + can be edited in hex. The color constant names are depending on the ROM's TV type. +
    + BCOL + + Addresses which contain data stored in the background color register + (COLUBK). These addresses are shown as color constants, which + can be edited in hex. The color constant names are depending on the ROM's TV type. +
    + AUD + + Addresses which contain data stored in the audio registers + (AUDC0/AUDC1/AUDF0/AUDF1/AUDV0/AUDV1). These can be edited + in hex. +
    + DATA + + Addresses used as an operand for some opcode. These can be edited + in hex. +
    + ROW + + Addresses not used as any of the above. These are shown up + to 8 per line and cannot be edited. +
    -

    For code sections, the 6502 mnemonic will be UPPERCASE for all standard instructions, or lowercase for "illegal" 6502 instructions (like "dcp"). If automatic resolving of code sections has been disabled for any reason, you'll likely see a lot @@ -1428,13 +1496,13 @@ anywhere in the listing:

    The following options are available:

    • Set PC @ current line: Set the Program Counter to the address of the -disassembly line where the mouse was clicked (highlighted in yellow).
    • +disassembly line where the mouse was clicked.
    • RunTo PC @ current line: Single-step through code until the Program Counter -matches the address of the disassembly line where the mouse was clicked (highlighted in yellow)
    • +matches the address of the disassembly line where the mouse was clicked. -
    • Re-disassemble: Self-explanatory; force the current bank to be -disassembled, regardless of whether anything has changed.
    • +
    • Disassemble @ current line: Disassemble from the disassembly line where the mouse was clicked. +This allows to fill gaps in the disassembly and is most useful for bankswitched ROMs.
    • Show tentative code: Allow Distella to do a static analysis/disassembly.
    • @@ -1445,7 +1513,8 @@ isn't already a defined label). in either binary or hexidecimal.
    • Use address relocation: Corresponds to the Distella '-r' option -(Relocate calls out of address range).
    • +(Relocate calls out of address range).
      +Note: The code will continue to run fine, but the ROM image will be altered.
    @@ -1520,12 +1589,12 @@ the RAM in the DPC scheme is not viewable by the 6507, so its addresses start fr

    Distella Configuration Files

    As mentioned in ROM Disassembly, Stella supports the following directives: -CODE/GFX/PGFX/DATA/ROW. While the debugger will try to automatically mark address +CODE, GFX, PGFX, COL, PCOL, BCOL, AUD, DATA, ROW. While the debugger will try to automatically mark address space with the appropriate directive, there are times when it will fail. There are several options in this case:

    1. Manually set the directives: Directives can be set in the debugger -prompt with the code/gfx/pgfx/data/row commands. These accept an address range +prompt with the aud/code/col/bcol/gfx/pcol/pgfx/data/row commands. These accept an address range for the given directive type. Setting a range with the same type a second time will remove that directive from the range.
    2. Use configuration files: Configuration files can be used to automatically @@ -1564,7 +1633,7 @@ but it helps to know at least a little about 6502 programming.

    3. Enter the debugger by pressing the ` (backquote) key. Don't get killed before you do this, though. You should still have all 5 lives.
    4. -
    5. In the RAM display, click the "Search" button and enter "5" for input. +
    6. In the RAM display, click the 'Search' button and enter "5" for input. This searches RAM for your value and highlights all addresses that match the input. You should see two addresses highlighted: "00a5" and "00ba". These are the only two addresses that currently have the value 5, so they're @@ -1580,7 +1649,7 @@ but it helps to know at least a little about 6502 programming.

    7. Get killed! Ram an enemy tank, or let him shoot you. Wait for the explosion to finish. You will now have 4 lives.
    8. -
    9. Enter the debugger again. Click the "Compare" button in RAM widget and enter +
    10. Enter the debugger again. Click the 'Compare...' button in RAM widget and enter a value of 4. Now the RAM widget should only show one highlighted address: "00ba". What we did was search within our previous results (the ones that were 5 before) for the new value 4. Address $00ba used to have the value 5, diff --git a/docs/graphics/debugger_cpuregs.png b/docs/graphics/debugger_cpuregs.png index f8cd3cb55..feb238c1b 100644 Binary files a/docs/graphics/debugger_cpuregs.png and b/docs/graphics/debugger_cpuregs.png differ diff --git a/docs/graphics/debugger_main.png b/docs/graphics/debugger_main.png index 4a8466e8f..c59f1a345 100644 Binary files a/docs/graphics/debugger_main.png and b/docs/graphics/debugger_main.png differ diff --git a/docs/graphics/debugger_romcmenu.png b/docs/graphics/debugger_romcmenu.png index d6a78172e..f6cd561a3 100644 Binary files a/docs/graphics/debugger_romcmenu.png and b/docs/graphics/debugger_romcmenu.png differ diff --git a/docs/graphics/eventmapping.png b/docs/graphics/eventmapping.png index 86deacd4a..f9b089b6d 100644 Binary files a/docs/graphics/eventmapping.png and b/docs/graphics/eventmapping.png differ diff --git a/docs/graphics/eventmapping_devsports.png b/docs/graphics/eventmapping_devsports.png index d66197a72..9b3da3ebc 100644 Binary files a/docs/graphics/eventmapping_devsports.png and b/docs/graphics/eventmapping_devsports.png differ diff --git a/docs/graphics/eventmapping_mouse.png b/docs/graphics/eventmapping_mouse.png new file mode 100644 index 000000000..daac75b09 Binary files /dev/null and b/docs/graphics/eventmapping_mouse.png differ diff --git a/docs/graphics/eventmapping_remap.png b/docs/graphics/eventmapping_remap.png index a2e3ce949..34df62937 100644 Binary files a/docs/graphics/eventmapping_remap.png and b/docs/graphics/eventmapping_remap.png differ diff --git a/docs/graphics/launcher_options_snapshots.png b/docs/graphics/launcher_options_snapshots.png index 0d2b2e8d6..a833f8bb3 100644 Binary files a/docs/graphics/launcher_options_snapshots.png and b/docs/graphics/launcher_options_snapshots.png differ diff --git a/docs/graphics/options.png b/docs/graphics/options.png index db86da3fb..9f8a95430 100644 Binary files a/docs/graphics/options.png and b/docs/graphics/options.png differ diff --git a/docs/graphics/options_audio.png b/docs/graphics/options_audio.png index e77d69a5e..e46d77b87 100644 Binary files a/docs/graphics/options_audio.png and b/docs/graphics/options_audio.png differ diff --git a/docs/graphics/options_developer.png b/docs/graphics/options_developer.png index 8d345f9aa..f405818b1 100644 Binary files a/docs/graphics/options_developer.png and b/docs/graphics/options_developer.png differ diff --git a/docs/graphics/options_developer_emulation.png b/docs/graphics/options_developer_emulation.png index 6b8009f35..977893402 100644 Binary files a/docs/graphics/options_developer_emulation.png and b/docs/graphics/options_developer_emulation.png differ diff --git a/docs/graphics/options_developer_timemachine.png b/docs/graphics/options_developer_timemachine.png index ddb58f28e..498f83c0f 100644 Binary files a/docs/graphics/options_developer_timemachine.png and b/docs/graphics/options_developer_timemachine.png differ diff --git a/docs/graphics/options_emulation.png b/docs/graphics/options_emulation.png new file mode 100644 index 000000000..99a1dfa4d Binary files /dev/null and b/docs/graphics/options_emulation.png differ diff --git a/docs/graphics/options_gameinfo_cartridge.png b/docs/graphics/options_gameinfo_cartridge.png index ea09b9842..b90761623 100644 Binary files a/docs/graphics/options_gameinfo_cartridge.png and b/docs/graphics/options_gameinfo_cartridge.png differ diff --git a/docs/graphics/options_gameinfo_console.png b/docs/graphics/options_gameinfo_console.png index 49577140c..e3aee16e5 100644 Binary files a/docs/graphics/options_gameinfo_console.png and b/docs/graphics/options_gameinfo_console.png differ diff --git a/docs/graphics/options_gameinfo_controller.png b/docs/graphics/options_gameinfo_controller.png index 9b9413ab2..fe5adb275 100644 Binary files a/docs/graphics/options_gameinfo_controller.png and b/docs/graphics/options_gameinfo_controller.png differ diff --git a/docs/graphics/options_gameinfo_emulation.png b/docs/graphics/options_gameinfo_emulation.png index 0db133505..221a08fa5 100644 Binary files a/docs/graphics/options_gameinfo_emulation.png and b/docs/graphics/options_gameinfo_emulation.png differ diff --git a/docs/graphics/options_misc.png b/docs/graphics/options_misc.png index aa382419f..1faa756b5 100644 Binary files a/docs/graphics/options_misc.png and b/docs/graphics/options_misc.png differ diff --git a/docs/graphics/options_misc_classic.png b/docs/graphics/options_misc_classic.png index d4a77dc9f..1eab6039e 100644 Binary files a/docs/graphics/options_misc_classic.png and b/docs/graphics/options_misc_classic.png differ diff --git a/docs/graphics/options_misc_light.png b/docs/graphics/options_misc_light.png index b1113c033..c0cebe477 100644 Binary files a/docs/graphics/options_misc_light.png and b/docs/graphics/options_misc_light.png differ diff --git a/docs/graphics/options_ui.png b/docs/graphics/options_ui.png index 14a6e33af..54ed568fc 100644 Binary files a/docs/graphics/options_ui.png and b/docs/graphics/options_ui.png differ diff --git a/docs/graphics/options_video.png b/docs/graphics/options_video.png index be67fe065..58654148a 100644 Binary files a/docs/graphics/options_video.png and b/docs/graphics/options_video.png differ diff --git a/docs/graphics/options_video_palettes.png b/docs/graphics/options_video_palettes.png new file mode 100644 index 000000000..dae0cf7ee Binary files /dev/null and b/docs/graphics/options_video_palettes.png differ diff --git a/docs/graphics/options_video_tv.png b/docs/graphics/options_video_tv.png index e76d32ba6..5ce3c3f2a 100644 Binary files a/docs/graphics/options_video_tv.png and b/docs/graphics/options_video_tv.png differ diff --git a/docs/graphics/resources/debugger_main.pdn b/docs/graphics/resources/debugger_main.pdn index e486c0048..6c864a2a4 100644 Binary files a/docs/graphics/resources/debugger_main.pdn and b/docs/graphics/resources/debugger_main.pdn differ diff --git a/docs/graphics/timemachine.png b/docs/graphics/timemachine.png index 269005fe8..fc2237abf 100644 Binary files a/docs/graphics/timemachine.png and b/docs/graphics/timemachine.png differ diff --git a/docs/index.html b/docs/index.html index 602bcc08f..89bee1158 100644 --- a/docs/index.html +++ b/docs/index.html @@ -19,7 +19,7 @@

      A multi-platform Atari 2600 VCS emulator

      -

      Release 6.1

      +

      Release 6.2.1



      User's Guide

      @@ -70,7 +70,7 @@


      -
      February 1999 - January 2020
      +
      February 1999 - June 2020
      The Stella Team
      Stella Homepage
      @@ -302,7 +302,7 @@
    11. Supports using ROM filename extensions to force specific bankswitching schemes
    12. Supports using ROM filename to force specific display formats
    13. Supports Supercharger single-load and multi-load games
    14. -
    15. Supports ROMs stored in ZIP and GZIP format, as well as the usual raw A26/BIN/ROM formats
    16. +
    17. Supports the usual raw A26/BIN/ROM formats, also when stored in ZIP files
    18. Supports property file for setting the properties associated with games
    19. Supports the NTSC, PAL and SECAM television standards in 50Hz and 60Hz mode
    20. Supports autodetection of display format for 50Hz vs. 60Hz modes
    21. @@ -355,12 +355,11 @@

      The Linux version of Stella is designed to work on a Linux Workstation with the following:

        -
      • Linux Kernel 3.x
      • i386 or x86_64 class machine, with 32 or 64-bit distribution
      • OpenGL capable video card
      • Other architectures (MIPS, PPC, PPC64, etc.) have been confirmed to work, but aren't as well tested as i386/x86_64
      • -
      • GNU g++ v/5 or Clang v/3.5 (with C++14 support) and the make utility are required for compiling the Stella source code
      • +
      • GNU g++ v/6 or Clang v/3.9 (with C++14 support) and the make utility are required for compiling the Stella source code

      @@ -536,12 +535,12 @@

      Supported File formats

      -

      Stella supports ROMs ending with extensions .a26, .bin, .rom, .gz, and .zip. - For the last two compressed formats (GZIP and ZIP, respectively), Stella will - automatically decompress the archive, and use the first ROM image it finds in - it (ie, the first one ending in a valid extension). If a ZIP archive contains - many such files, Stella will display a virtual filesystem of the contents - of the archive.

      +

      Stella supports ROMs ending with extensions .a26, .bin, .rom, and .zip. + For the ZIP archive format, Stella will look into the archive and if it + contains only one ROM image file, Stella will automatically load it. If an + archive contains many such files, Stella will display a virtual + filesystem with the contents of the archive. This can be then browsed + like a normal directory.

      Other extensions are also possible, namely to force a specific bankswitch scheme. Normally, the bankswitching scheme for a ROM is determined automatically, @@ -549,7 +548,7 @@ have to do anything yourself. However, it is also possible to force the bankswitch type to use by adding a special filename extension. These extensions are listed in the ROM properties section under - Cartridge.Type -> File Extension.

      + Cart.Type -> File Extension.

      Note: These extensions are the same as those used by the Harmony Cart and Unocart and are not case-sensitive, so you can name your files and have them @@ -775,7 +774,7 @@ Pause/resume emulation Pause -   + Shift-Cmd + p @@ -1028,6 +1027,50 @@ +

      Trackball Controller (uses mouse, left port only)

      + + + + + + + + +
      Left Trackball
      + + + + + + + + + +
      FunctionKey
      Fire ButtonSame as 'Joy0 Fire'
      +
      + +

      Light Gun Controller (uses mouse, left port only)

      + + + + + + + + +
      Left Light Gun
      + + + + + + + + + +
      FunctionKey
      Fire ButtonSame as 'Joy0 Fire'
      +
      +

      Paddle Controller digital emulation (can be remapped)

      @@ -1292,7 +1335,157 @@
      -

      TV effects (can be remapped, only active in TIA mode)

      +

      Audio & Video Keys (can be remapped)

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      FunctionKey (Standard)Key (macOS)
      Toggle soundControl + ]Control + ]
      Decrease volumeAlt + [Cmd + [
      Increase volumeAlt + ]Cmd + ]
      Switch to next larger zoom level in windowed mode, +
      toggle stretching in fullscreen mode
      Alt + =Cmd + =
      Switch to next smaller zoom level in windowed mode, +
      toggle stretching in fullscreen mode
      Alt + -Cmd + -
      Toggle windowed/fullscreen modeAlt + EnterCmd + Enter
      Toggle adapting display refresh rate to game frame rate +
      + Note: Not available for macOS.
      Alt + rCmd + r
      Decrease overscan in fullscreen modeShift + PageDownShift-Fn + Down arrow
      Increase overscan in fullscreen modeShift + PageUpShift-Fn + Up arrow
      Move display down (uses "Display.VCenter")Alt + PageDownCmd-Fn + Down arrow
      Move display up (uses "Display.VCenter")Alt + PageUpCmd-Fn + Up arrow
      Decrease vertical display sizeShift-Alt + PageUpShift-Cmd-Fn + Up arrow
      Increase vertical display sizeShift-Alt + PageDownShift-Cmd-Fn + Down arrow
      Switch to previous display format (NTSC/PAL/SECAM etc.)Shift-Control + fShift-Control + f
      Switch to next display format (NTSC/PAL/SECAM etc.)Control + fControl + f
      Toggle display interpolationControl + iControl + i
      + These settings can also be changed using Global Keys
      +
      + +

      Palettes Keys (can be remapped)

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      FunctionKey (Standard)Key (macOS)
      Select previous palette (Standard/z26/User/Custom)Shift-Control + pShift-Control + p
      Select next palette (Standard/z26/User/Custom)Control + pControl + p
      Select previous palette attributeShift-Alt + 9Shift-Cmd + 9
      Select next palette attributeAlt + 9Cmd + 9
      Decrease selected palette attributeShift-Alt + 0Shift-Cmd + 0
      Increase selected palette attributeAlt + 0Cmd + 0
      + These settings can also be changed using Global Keys
      +
      + +

      TV effects Keys (can be remapped)

      @@ -1301,93 +1494,73 @@ - + + + + + + - + + + + + + - + + + + + + - + + + + + + + + + + + - + + + + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Items marked as (*) will also switch to 'Custom' mode
      Key (macOS)
      Disable TV effectsSelect previous TV effects presetShift-Alt + 1Shift-Cmd + 1
      Select next TV effects preset Alt + 1 Cmd + 1
      Select 'RGB' presetSelect previous 'Custom' mode attribute (*)Shift-Alt + 2Shift-Cmd + 2
      Select next 'Custom' mode attribute (*) Alt + 2 Cmd + 2
      Select 'S-Video' presetDecrease 'Custom' selected attribute value (*)Shift-Alt + 3Shift-Cmd + 3
      Increase 'Custom' selected attribute value (*) Alt + 3 Cmd + 3
      Select 'Composite' presetToggle 'phosphor' modeAlt + pCmd + p
      Decrease 'phosphor' blendShift-Alt + 4Shift-Cmd + 4
      Increase 'phosphor' blend Alt + 4 Cmd + 4
      Select 'Badly adjusted' presetDecrease scanline intensityShift-Alt + 5Shift-Cmd + 5
      Increase scanline intensity Alt + 5 Cmd + 5
      Select 'Custom' presetAlt + 6Cmd + 6
      + These settings can also be changed using Global Keys
      +
      Select previous 'Custom' mode attribute (*)Shift-Alt + 7Shift-Cmd + 7
      Select next 'Custom' mode attribute (*)Alt + 7Cmd + 7
      Decrease 'Custom' selected attribute value (*)Shift-Alt + 8Shift-Cmd + 8
      Increase 'Custom' selected attribute value (*)Alt + 8Cmd + 8
      Toggle 'phosphor' effectAlt + pCmd + p
      Decrease 'phosphor' blend in phosphor modeShift-Alt + 9Shift-Cmd + 9
      Increase 'phosphor' blend in phosphor modeAlt + 9Cmd + 9
      Decrease scanline intensityShift-Alt + 0Shift-Cmd + 0
      Increase scanline intensityAlt + 0Cmd + 0
      - Items marked as (*) are only available in 'Custom' preset mode
      -

      Developer Keys in TIA mode (can be remapped)

      +

      Developer Keys (can be remapped)

      @@ -1503,9 +1676,63 @@ + + +
      Alt + j Cmd + j
      + These settings can also be changed using Global Keys
      +
      -

      Other Keys (can be remapped)

      +

      Global Keys (can be remapped)

      +

      These keys allow selecting and changing settings without having to remember the + dedicated keys. They keys are grouped by Audio & Video and Debug settings.

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      FunctionKey (Standard)Key (macOS)
      Select previous setting groupControl + EndControl-Fn + Left arrow
      Select next setting groupControl + HomeControl-Fn + Right arrow
      Select previous settingEndFn + Left arrow
      Select next settingHomeFn + Right arrow
      Decrease current settingPageDownFn + Down arrow
      Increase current setting + PageUpFn + Up arrow
      +

      Notes: +

        +
      • Only available if UI messages are enabled.
      • +
      • Currently not available settings are automatically skipped.
      • +
      • If a setting was selected via dedicated key, its value can also be changed with the + global keys.
      • +
      +

      + +

      Other Emulation Keys (can be remapped)

      @@ -1513,91 +1740,56 @@ - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -1605,7 +1797,6 @@ - @@ -1617,38 +1808,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1660,13 +1824,21 @@ - - - + + + + + + + + + + + + - @@ -1699,7 +1871,7 @@
      Key (Standard) Key (macOS)
      Switch to next larger zoom level in windowed mode, -
      toggle stretching in fullscreen mode
      Alt + =Cmd + =Load previous game in ROM (multicart ROM, TIA mode)Shift-Control + rShift-Control + r
      Switch to next smaller zoom level in windowed mode, -
      toggle stretching in fullscreen mode
      Alt + -Cmd + -Reload current ROM (singlecart ROM, TIA mode)
      + Load next game in ROM (multicart ROM, TIA mode)
      Control + rControl + r
      Toggle fullscreen/windowed modeAlt + EnterCmd + EnterReload ROM listing (ROM launcher mode)Control + rControl + r
      Increase overscan in fullscreen modeShift + PageUpShift + PageUpEmulate 'frying' effect (TIA mode)BackspaceBackspace
      Decrease overscan in fullscreen modeShift + PageDownShift + PageDownGo to parent directory (UI mode)BackspaceBackspace
      Move display up (uses "Display.VCenter")Alt + PageUpCmd + PageUpDecrease emulation speed (disables 'Turbo' mode)Shift-Control + sShift-Control + s
      Move display down (uses "Display.VCenter")Alt + PageDownCmd + PageDownIncrease emulation speed (disables 'Turbo' mode)Control + sControl + s
      Switch display format in increasing order (NTSC/PAL/SECAM etc.)Control + fControl + fToggle 'Turbo' mode (maximum emulation speed)Control + tControl + t
      Switch display format in decreasing order (NTSC/PAL/SECAM etc.)Shift-Control + fShift-Control + fDecrease autofire rateShift-Control + aShift-Control + a
      Switch palette (Standard/Z26/User)Control + pControl + p
      Toggle display interpolationControl + iControl + i
      Toggle sound on/offControl + ]Control + ]
      Decrease volumeAlt + [Cmd + [
      Increase volumeAlt + ]Cmd + ]Increase autofire rateControl + aControl + a
      Control + 0 Control + 0
      Toggle grab mouse Control + gControl + 1 Control + 1
      Reload current ROM (singlecart ROM, TIA mode)
      - Load next game in ROM (multicart ROM, TIA mode)
      Control + rControl + r
      Reload ROM listing (ROM launcher mode)Control + rControl + r
      Emulate 'frying' effect (TIA mode)BackspaceBackspace
      Go to parent directory (UI mode)BackspaceBackspace
      Save continuous PNG snapshots
      (per interval defined in Snapshot Settings)
      Alt + s Cmd + s
      Save continuous PNG snapshots (every frame) Shift-Alt + sAlt + t Cmd + t
      Enter/Exit the Time Machine dialogShift + t to enter, Shift + t/Escape/Space to exitShift + t to enter, Shift + t/Escape/Space to exitShift + t to enter, Shift + t/Escape to exit and continue with emulationShift + t to enter, Shift + t/Escape to exit and continue with emulation
      Playback the Time Machine from current state (without sound, from the TM dialog only)ShiftShift
      Start/Stop playback (exist/enters the Time Machine dialog)Shift + SpaceShift + Space
      Rewind by one state (enters the Time Machine dialog) Alt + Left arrow
      -

      UI keys in Text Editing areas (cannot be remapped)

      +

      UI Keys in Text Editing areas (cannot be remapped)

      @@ -1828,7 +2000,7 @@ - + @@ -1875,12 +2047,13 @@

      Bottom row (left to right)

      KeyEditor Function
      N/A N/A N/A N/A voice (2600-daptor II)
      SaveKey
      - - + + @@ -1946,13 +2119,59 @@ - + - + + + + + + + + + + + + emulator, a user-defined palette, or a custom palette generated + from user-defined phase shifts. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1960,6 +2179,11 @@ + + + + + + + + + + @@ -2016,32 +2245,39 @@ - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + + + + + + @@ -2064,36 +2300,6 @@ and 'Custom' modes. - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -2192,6 +2399,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + - - + + + + + + + @@ -2321,13 +2551,23 @@ launcher only happens when started with the launcher). + + + + + + + + + + - + @@ -2338,9 +2578,10 @@ - - + + @@ -2348,6 +2589,11 @@ + + + + + @@ -2392,12 +2638,12 @@ - + - - + + @@ -2456,6 +2702,16 @@ + + + + + + + + + + @@ -2522,7 +2778,7 @@ - @@ -2533,27 +2789,27 @@ - + - + - + - + - + @@ -2584,6 +2840,16 @@ + + + + + + + + + + + + + @@ -2741,7 +3010,7 @@

      Options Menu dialog:



      -

      Video Settings dialog:

      +

      Video & Audio Settings dialog (Display):

      ItemDescription
      Current timeShows the time of the currently selected status, +
      Current timeShows the time of the currently selected state, relative to the first one
      'Start/Stop' buttonStarts or stops the Time Machine
      'Continue' buttonExits the dialog and continues emulation
      'Exit' buttonExits the dialog and continues emulation, starting at current state
      'Rewind All' buttonNavigates back to the begin of the timeline
      'Rewind One' buttonNavigates back by one state
      'Playback' buttonStarts playback, starting at the current state (with sound disabled)
      'Unwind One' buttonNavigates forward by one state
      'Unwind All' buttonNavigates forward to the end of the timeline
      'Save All' buttonSaves all Time Machine states to disk
      -center <1|0>
      Centers game window (if possible).Centers all windows (if possible).
      -palette <standard|z26|user>
      -windowedpos <XxY>
      Sets the window position in windowed emulator mode.
      -display <number>
      Sets the display for Stella's emulator.
      -palette <standard|z26|user|custom>
      Set the palette to either normal Stella, the one used in the z26 - emulator, or a user-defined palette.
      -pal.phase_ntsc <number>
      Adjust phase shift of 'custom' NTSC palette.
      -pal.phase_pal <number>
      Adjust phase shift of 'custom' PAL palette.
      -pal.hue <number>
      Adjust hue of current palette (range -1.0 to 1.0).
      -pal.saturation <number>
      Adjust saturation of current palette (range -1.0 to 1.0).
      -pal.contrast <number>
      Adjust contrast of current palette (range -1.0 to 1.0).
      -pal.brightness <number>
      Adjust brightness of current palette (range -1.0 to 1.0).
      -pal.gamma <number>
      Adjust gamma of current palette (range -1.0 to 1.0).
      Control the emulation speed (as a percentage, 10 - 1000).
      -turbo <1|0>
      Enable 'Turbo' mode for maximum emulation speed.
      -uimessages <1|0>
      Enable or disable display of message in the UI. Note that messages @@ -1977,10 +2201,15 @@ Set the volume.
      -audio.device <number>
      Set the audio device (0 = default).
      -audio.preset <1 - 5>
      Set an audio preset. Numbers in sequence represent presets for - 'custom', 'low quality, 'medium lag', 'high quality, medium lag', + 'custom', 'low quality, medium lag', 'high quality, medium lag', 'high quality, low lag' and 'ultra quality, minimal lag'.
      -audio.dpc_pitch <10000 - 30000>
      Set the pitch o f Pitfall II music.Set the pitch of Pitfall II music.
      -tia.zoom <zoom>
      Use the specified zoom level (integer) while in TIA/emulation mode. -
      -tia.zoom <zoom>
      Use the specified zoom level (integer) while in TIA/emulation mode. +
      -tia.vsizeadjust <-5 - 5>
      Adjust the display height of the TIA image -
      -tia.vsizeadjust <-5 - 5>
      Adjust the display height of the TIA image +
      -tia.inter <1|0>
      Use interpolation for the TIA image (results in blending/smoothing - of the image).
      -tia.inter <1|0>
      Use interpolation for the TIA image (results in blending/smoothing + of the image).
      -tia.fs_stretch <1|0>
      Stretch TIA image completely while in fullscreen mode, vs. keeping the correct - aspect ratio.
      -tia.fs_stretch <1|0>
      Stretch TIA image completely while in fullscreen mode, vs. keeping the correct + aspect ratio.
      -tia.fs_refresh <1|0>
      While in fullscreen mode, adapt the display's refresh rate to the game's frame rate + to minimize judder.
      + Note: Not available for macOS.
      -tia.fs_overscan <0 - 10>
      -tv.contrast <number>
      Blargg TV effects 'contrast' (only available in custom mode, - range -1.0 to 1.0).
      -tv.brightness <number>
      Blargg TV effects 'brightness' (only available in custom mode, - range -1.0 to 1.0).
      -tv.hue <number>
      Blargg TV effects 'hue' (only available in custom mode, - range -1.0 to 1.0).
      -tv.saturation <number>
      Blargg TV effects 'saturation' (only available in custom mode, - range -1.0 to 1.0).
      -tv.gamma <number>
      Blargg TV effects 'gamma' (only available in custom mode, - range -1.0 to 1.0).
      -tv.sharpness <number>
      Blargg TV effects 'sharpness' (only available in custom mode, @@ -2177,9 +2383,10 @@
      -joyallow4 <1|0>
      Allow all 4 directions on a joystick to be pressed - simultaneously.
      -psense <number>
      Sensitivity for emulation of paddles when using analog paddles. + Valid range of values is from 1 to 30, with larger numbers causing + faster movement.
      Impact of fast paddle movement on input averaging.
      -dcsense <number>
      Sensitivity for emulation of driving controllers when using a mouse. + Valid range of values is from 1 to 20, with larger numbers causing + faster movement.
      -autofirerate <0 - 30>
      Automatic trigger rate of the fire buttons in Hz (0 = disabled)
      -joyallow4 <1|0>
      Allow all 4 directions on a joystick to be pressed + simultaneously.
      -modcombo <1|0>
      Use modifier(Shift/Alt/Control)-x key combos. This is normally enabled, + since the 'Quit' command is tied to 'Control-q'. However, there are times + when you want to disable them.
      + E.g. a 2-player game is using either the 'f' or 'r' keys for movement, + and pressing Control (for Fire) will perform an unwanted action + associated with Control-r or Control-f default keys.
      -saport <lr|rl>
      Determines how to enumerate the Stelladaptor/2600-daptor devices in the + order they are found: 'lr' means first is left port, second is right port, + 'rl' means the opposite.
      -avoxport <name>
      Set the name of the serial port where an AtariVox is connected.
      -usemouse <always|analog|never>
      Use mouse as a controller as specified by ROM properties in specific case. @@ -2199,24 +2446,6 @@ (paddles, trackball, etc.).
      -grabmouse <1|0>
      Locks the mouse cursor in the game window in emulation mode.
      -cursor <0|1|2|3>
      Set mouse cursor state in UI/emulation modes.
      -dsense <number>
      Sensitivity for emulation of paddles when using a digital device - (ie, joystick digital axis or button, keyboard key, etc.). - Valid range of values is from 1 to 20, with larger numbers causing - faster movement.
      -msense <number>
      Sensitivity for emulation of paddles when using a mouse. @@ -2232,20 +2461,21 @@
      -saport <lr|rl>
      Determines how to enumerate the Stelladaptor/2600-daptor devices in the - order they are found: 'lr' means first is left port, second is right port, - 'rl' means the opposite.
      -dsense <number>
      Sensitivity for emulation of paddles when using a digital device + (ie, joystick digital axis or button, keyboard key, etc.). + Valid range of values is from 1 to 20, with larger numbers causing + faster movement.
      -modcombo <1|0>
      Use modifier(Shift/Alt/Control)-x key combos. This is normally enabled, - since the 'Quit' command is tied to 'Control-q'. However, there are times - when you want to disable them.
      - E.g. a 2-player game is using either the 'f' or 'r' keys for movement, - and pressing Control (for Fire) will perform an unwanted action - associated with Control-r or Control-f default keys.
      -cursor <0|1|2|3>
      Set mouse cursor state in UI/emulation modes.
      -grabmouse <1|0>
      Locks the mouse cursor in the game window in emulation mode.
      -launcherpos <XxY>
      Sets the window position in windowed ROM launcher mode.
      -launcherdisplay <number>
      Sets the display for the ROM launcher.
      -launcherres <WxH>
      Set the size of the ROM launcher.
      -launcherfont <small|medium|large>
      -launcherfont <small|low_medium|medium|large|large12|large14|large16>
      Set the size of the font in the ROM launcher.
      -romviewer <0|1|2>
      Hide ROM Info Viewer in ROM launcher mode (0), or use the - given zoom level (1 or 2).
      -romviewer <float>
      Hide ROM Info Viewer in ROM launcher mode (0) or use the + given zoom level.
      + Note: The zoom level is converted into a percentage in the UI.
      Use the specified palette for UI elements.
      -dialogfont <small|low_medium|medium|large|large12|large14|large16>
      Set the size of the font in the dialogs.
      -dialogpos <0 - 4>
      Set the position of dialogs within Stella windows (0 = center).
      -romdir <dir>
      Set the directory where the ROM launcher will start.Set the path where the ROM launcher will start.
      -avoxport <name>
      Set the name of the serial port where an AtariVox is connected.
      -followlauncher <0|1>
      Make the start path follow ROM launcher navigation.
      Relocate calls out of address range in the disassembler.
      -dbg.pos <XxY>
      Sets the window position in windowed debugger mode.
      -dbg.display <number>
      Sets the display for the debugger.
      -dbg.res <WxH>
      Set the size of the debugger window.
      -bs <type>
      Set "Cartridge.Type" property. See the Game Properties section + Set "Cart.Type" property. See the Game Properties section for valid types.
      -startbank <bank>
      Set "Cartridge.StartBank" property.Set "Cart.StartBank" property.
      -channels <Mono|Stereo>
      Set "Cartridge.Sound" property.Set "Cart.Sound" property.
      -ld <A|B>
      Set "Console.LeftDifficulty" property.Set "Console.LeftDiff" property.
      -rd <A|B>
      Set "Console.RightDifficulty" property.Set "Console.RightDiff" property.
      -tv <Color|BW>
      Set "Console.TelevisionType" property.Set "Console.TVType" property.
      Set "Controller.SwapPaddles" property.
      -pxcenter <-10..30>
      Set "Controller.PaddlesXCenter" property.
      -pycenter <-10..30>
      Set "Controller.PaddlesYCenter" property.
      -ma <Auto|XY>
      Set "Controller.MouseAxis" property. @@ -2627,6 +2893,9 @@
      -<plr.|dev.>stats <1|0>
      Overlay console info on the TIA image during emulation.
      -<plr.|dev.>detectedinfo <1|0>
      Display detected settings info when a ROM is loaded.
      -<plr.|dev.>console <2600|7800>
      Select console for B/W and Pause key handling and RAM initialization.
      @@ -2750,27 +3019,44 @@
      - - - - - - + + - + + - - - - +
      ItemBrief descriptionFor more information,
      see CommandLine
      RendererUse specified rendering mode-video
      PalettePalette for emulation mode-palette
      InterpolationInterpolation for TIA image-tia.inter
      ZoomZoom level for emulation mode -tia.zoom
      V-Size adjustAdjust height of TIA image-tia.vsizeadjust
      Emul. speedEmulation speed-speed
      VSyncEnable vertical synced updates-vsync
      InterpolationEnable interpolation of the TIA image-tia.inter
      ZoomZoom level of the TIA image-tia.zoom
      FullscreenSelf-explanatory - Note that colors may slightly change. This depends on the OS and renderer used.-fullscreen
      StretchIn fullscreen mode, completely fill screen with TIA image-tia.fs_stretch
      StretchIn fullscreen mode, completely fill screen with the TIA image.-tia.fs_stretch
      Adapt display...In fullscreen mode, adapt the display's refresh rate to the game's frame rate to minimize judder. +
      Note: Not available for macOS.
      -tia.fs_refresh
      OverscanIn fullscreen mode, add overscan to the TIA image-tia.fs_overscan
      Fast SuperCharger loadSkip progress loading bars for SuperCharger ROMs-fastscbios
      Show UI messagesOverlay UI messages onscreen-uimessages
      Center windowAttempt to center application windows, else position at last position-center
      Multi-threadingEnable multi-threaded rendering-threads
      V-Size adjustAdjust height of the TIA image-tia.vsizeadjust

      -

      Video Settings dialog (TV Effects):

      +

      Video & Audio Settings dialog (Palettes):

      + + + + + + +
           + + + + + + + + + + +
      ItemBrief descriptionFor more information,
      see CommandLine
      PalettePalette used for emulation mode-palette
      NTSC phaseAdjust phase shift for 'Custom' NTSC palette-pal.phase_ntsc
      PAL phaseAdjust phase shift for 'Custom' PAL palette-pal.phase_pal
      HueAdjust hue of currently selected palette-pal.hue
      SaturationAdjust saturation of currently selected palette-pal.saturation
      ContrastAdjust contrast of currently selected palette-pal.contrast
      BrightnessAdjust brightness of currently selected palette-pal.brightness
      GammaAdjust gamma of currently selected palette-pal.gamma
      +
      +
      + +

      Video & Audio Settings dialog (TV Effects):

      @@ -2779,24 +3065,24 @@
      - + - - - - - + + + + +
      ItemBrief descriptionFor more information,
      see CommandLine
      TV modeDisable TV effects, or select TV preset-tv.filter
      Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.contrast, -tv.hue, etc.
      Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.sharpness, -tv.resolution, etc.
      Phosphor for all ROMsEnable phosphor mode for all ROMs-tv.phosphor
      Blend (phosphor)Blend level to use in phosphor mode for all ROMs (needs to be manually adjusted for your particular hardware)-tv.phosblend
      Scanline intensitySets scanline black-level intensity.
      Note: No scanlines in 1x mode snapshots.
      -tv.scanlines
      Clone CompositeCopy 'Composite' attributes to 'Custom' sliders 
      Clone S-VideoCopy 'S-Video' attributes to 'Custom' sliders 
      Clone RGBCopy 'RGB' attributes to 'Custom' sliders 
      Clone Bad adjustCopy 'Bad Adjust' attributes to 'Custom' sliders 
      RevertRevert attribute sliders to saved 'Custom' settings 
      Clone RGBCopy 'RGB' attributes to 'Custom' TV mode sliders 
      Clone S-VideoCopy 'S-Video' attributes to 'Custom' TV mode sliders 
      Clone CompositeCopy 'Composite' attributes to 'Custom' TV mode sliders 
      Clone Bad adjustCopy 'Bad Adjust' attributes to 'Custom' TV mode sliders 
      RevertRevert attribute sliders to saved 'Custom' TV mode settings 

      -

      Audio Settings dialog:

      +

      Video & Audio Settings dialog (Audio):

      @@ -2806,7 +3092,8 @@ - + + - - + +
      ItemBrief descriptionFor more information,
      see CommandLine
      Enable audioSelf-explanatory-audio.enabled
      VolumeSelf-explanatory-audio.volume
      ModeSelect an audio preset or choose 'custom' for manual configuration-audio.preset
      DeviceUse the specified audio device.-audio.device
      ModeSelect an audio preset or choose 'Custom' for manual configuration.-audio.preset
      Fragment sizeThe number of samples in a single fragment processed by the audio driver. Smaller values mean less latency, but may lead to dropouts (depending on OS and hardware).-audio.fragment_size
      Sample rate Output samples per second. Higher values reduce artifacts from resampling and decrease latency, @@ -2819,8 +3106,8 @@ some games (notably Quadrun). -audio.resampling_quality
      HeadroomNumber of frames to buffer before playback starts. Higher values increase latency, but reduce the potential for dropouts.-audio.headroom
      Buffer sizeMaximum size of the audio buffer. Higher values increase maximum latency, but reduce the potential for dropouts-audio.buffer_size
      Stereo for all ROMsEnables stereo mode for all ROMs.-audio.stereo
      Buffer sizeMaximum size of the audio buffer. Higher values increase maximum latency, but reduce the potential for dropouts.-audio.buffer_size
      Stereo for all ROMsEnable stereo mode for all ROMs.-audio.stereo
      Pitfall II music pitchDefines the pitch of Pitfall II music (which may vary between carts).-audio.dpc_pitch

      @@ -2839,6 +3126,44 @@
      + +

      Emulation dialog:

      + + + + + + +
           + + + + + + + + + + + + + + + + + + +
      ItemBrief descriptionFor more information,
      see CommandLine
      Emulation speedEmulation speed-speed
      VSyncEnable vertical synced updates-vsync
      TurboEnable 'Turbo' mode for maximum emulation speed. This overwrites 'Emulation speed' setting and disables 'VSync'.-turbo
      Multi-threadingEnable multi-threaded rendering-threads
      Fast SuperCharger loadSkip progress loading bars for SuperCharger ROMs-fastscbios
      Show UI messagesOverlay UI messages onscreen-uimessages
      Confirm exiting...Display a popup when emulation is exited-confirmexit
      When entering/exiting emulation: + Automatically save no, current or all Time Machine states when exiting emulation.
      + The latter also loads all states when entering emulation. When this is enabled, you + can always continue your game session from where you exited it. Even including the + Time Machine buffer! +
      -saveonexit
      Automatically change... + Automatically change to the next available save state slot after saving a ROM state file. + -autoslot
      +
      +
      +

      Input Settings dialog:

      @@ -2858,9 +3183,10 @@
      + + - - + @@ -2897,9 +3223,9 @@ - + - +
      ItemBrief descriptionFor more information,
      see CommandLine
      ThemeTheme to use for UI elements (see examples)-uipalette
      Dialogs fontThe font used in the dialogs-dialogfont
      HiDPI modeScale the UI by a factor of two when enabled-hidpi
      Dialogs positionPosition of dialogs with Stella window-dialogpos
      HiDPI modeScales the UI by a factor of two when enabled-hidpi
      Confirm exiting...Display a popup when emulation is exited-confirmexit
      Center windowsAttempt to center application windows, else position at last position-center
      List input delayMaximum delay between keypresses in filelist-widgets before a search string resets. -listdelay
      Mouse wheel scrollNumber of lines a mouse scroll will move in list-widgets-mwheel
      Double-click speedSpeed of mouse double-clicks-mdouble
      Save pathSpecifies where to save snapshots-snapsavedir
      Continuous snapshot intervalInterval (in seconds) between snapshots-ssinterval
      Use actual ROM nameUse the actual ROM filename instead of the internal database name.-snapname
      Use actual ROM nameUse the actual ROM filename instead of the internal database name-snapname
      Overwrite existing filesWhether to overwrite old snapshots-sssingle
      Ignore scaling (1x mode)Save snapshot in 1x mode without scaling-ss1x
      Create pixel-exact image (no zoom/post-processing)Save snapshot using the exact pixels from the TIA image, without zoom or any post-processing effects-ss1x
      @@ -3007,25 +3333,43 @@ - - - + + + - - + - - +
      ItemBrief descriptionFor more information,
      see CommandLine
      Use mouse as ...Allow the mouse to emulate various controllers-usemouse
      Mouse cursor visibilityShow/hide cursor depending on current state-cursor
      Joystick deadzone sizeDeadzone area for axes on joysticks/gamepads-joydeadzone
      Paddle dejitter strengthStrenght of paddle input averaging (base) and reaction to fast paddle movements (diff)-dejitter.base, -dejitter.diff
      (Analog paddle) SensitivitySensitivity of an analog paddle-psense
      Analog paddle) Dejitter averagingStrength of paddle input averaging, suppresses mouse jitter-dejitter.base
      (Analog paddle) Dejitter reactionStrength of paddle reaction to fast paddle movements, suppresses mouse jitter-dejitter.diff
      Digital paddle sensitivitySensitivity used when emulating a paddle using a digital device-dsense
      Mouse paddle sensitivitySensitivity used when emulating a paddle using a mouse-msense
      Trackball sensitivitySensitivity used when emulating a trackball device using a mouse-tsense
      Autofire rateAutomatic trigger rate of the fire buttons in Hz-autofirerate
      Allow all 4 directions ...Allow all 4 joystick directions to be pressed simultaneously-joyallow4
      Grab mouse ...Keep mouse in window in emulation mode
      (only when used as controller)
      - Note: The sensitivity may greatly vary when the mouse is not grabbed.
      -grabmouse
      Use modifier key combosEnable using modifier keys in keyboard actions-modcombo
      Swap Stelladaptor portsSwap the order of the detected Stelladaptors/2600-daptors (see Advanced Configuration - Stelladaptor/2600-daptor Support)-saport
      Joystick databaseShow all joysticks that Stella knows about, with the option to remove them 
      Erase EEPROMErase the whole AtariVox/SaveKey flash memory 
      AVox serial portDescribed in further detail in Advanced Configuration - AtariVox/SaveKey Support -avoxport
      AtariVox serial portDescribed in further detail in Advanced Configuration - AtariVox/SaveKey Support -avoxport
      + +

      Mouse settings can be configured under the 'Mouse' tab, shown below:

      + + + + + + +
           + + + + + + + + +
      ItemBrief descriptionFor more information,
      see CommandLine
      Use mouse as ...Allow the mouse to emulate various controllers-usemouse
      (Sensitivity) PaddleSensitivity used when emulating a paddle using a mouse-msense
      (Sensitivity) TrackballSensitivity used when emulating a trackball device using a mouse-tsense
      (Sensitivity) Driving controllerSensitivity used when emulating a driving controller device using a mouse-dcsense
      Mouse cursor visibilityShow/hide cursor depending on current state-cursor
      Grab mouse ...Keep mouse in window in emulation mode
      (only when used as controller)
      + Note: The sensitivity may greatly vary when the mouse is not grabbed.
      -grabmouse
      +
      +

      ROM Launcher

      @@ -3035,8 +3379,8 @@ launcher and fonts, as well as the 'ROM Info Viewer' can be changed in UI Settings - Launcher dialog, as shown below:

      -

      Most of the options are self-explanatory, except for the 'ROM Info - viewer', which is described below.

      +

      Most of the options are self-explanatory, except for the 'ROM info + width', which is described below.

      ROM Info Viewer

      @@ -3048,27 +3392,21 @@ for each new release of Stella. Note that the snapshots can be any size generated by Stella; they will be resized accordingly.

      -

      Currently, there are several restrictions for this feature:

      -
        -
      1. The ROM Info Viewer can be shown in 1x or 2x mode only.
      2. -
      3. To view snapshots in 1x mode, the ROM launcher window must be sized at - least 640x480. If the launcher isn't large enough, the functionality - will be disabled.
      4. -
      5. To view snapshots in 2x mode, the ROM launcher window must be sized at - least 1000x720. If the launcher isn't large enough, an attempt will - be made to use 1x mode.
      6. -
      + The ROM Info Viewer's width can be defined between 0% (off) and 100%. The + value is relative to the launcher width. For too small or too large values, + Stella will automatically correct the width at runtime so that the ROM names + and the current ROM's information always have enough space.

      The following snapshots illustrate the various font sizes and rom info - zoom levels:

      + widths:

      -

      ROM Info Viewer in 1x mode, UI sized 800x480, small launcher font:

      +

      ROM Info Viewer width at 40%, UI sized 800x480, small launcher font:

      -

      ROM Info Viewer in 1x mode, UI sized 1000x720, medium launcher font:

      +

      ROM Info Viewer width at 32%, UI sized 1000x720, medium launcher font:

      -

      ROM Info Viewer in 2x mode, UI sized 1280x900, large launcher font:

      +

      ROM Info Viewer width at 50% , UI sized 1280x900, large launcher font:

      The text box in the upper right corner can be used to narrow down the @@ -3117,8 +3455,6 @@ - -

    22. Show only ROM files: Selecting this reloads the current listing, showing only files that have a valid ROM extension.
    23. @@ -3273,6 +3609,7 @@ ItemBrief descriptionFor more information,
      see CommandLine Player/Developer settingsSelects the active settings set-dev.settings Console info overlayOverlay console info on the TIA image during emulation.-plr.stats
      -dev.stats + Detected settings infoDisplay detected settings when a ROM is loaded.-plr.detectedinfo
      -dev.detectedinfo ConsoleSelect the console type, this affects Color/B&W/Pause key emulation and zero-page RAM initialization-plr.console
      -dev.console Random startup bankRandomize the startup bank (only for selected bankswitch types)-plr.bankrandom
      -dev.bankrandom Randomize zero-page ...When loading a ROM, randomize all RAM content instead of initializing with all zeroes (for 'Console' = 'Atari 2600' only)-plr.ramrandom
      -dev.ramrandom @@ -3402,21 +3739,6 @@ 'Buffer size'. -plr.tm.horizon
      -dev.tm.horizon - - When entering/exiting emulation: - - Automatically save no, current or all Time Machine states when exiting emulation.
      - The latter also loads all states when entering emulation. When this is enabled, you - can always continue your game session from where you exited it. Even including the - Time Machine buffer! - - -saveonexit - - Automatically change... - - Automatically change to the next available save state slot after saving a ROM state file. - - -autoslot @@ -3692,24 +4014,24 @@ Ms Pac-Man (Stella extended codes):

          ; Comments
      -   "Cartridge.MD5"      "Value"
      -   "Property"           "Value"
      +   "Cart.MD5"  "Value"
      +   "Property"  "Value"
          ""
       
          ; Comments
      -   "Cartridge.MD5"      "Value"
      -   "Property"           "Value"
      +   "Cart.MD5"  "Value"
      +   "Property"  "Value"
          ""
       
          . . .
       
          ; Comments
      -   "Cartridge.MD5"      "Value"
      -   "Property"           "Value"
      +   "Cart.MD5"  "Value"
      +   "Property"  "Value"
          ""

      Every block in the property file must have a unique value for the - Cartridge.MD5 property.

      + Cart.MD5 property.

      Properties

      @@ -3717,11 +4039,13 @@ Ms Pac-Man (Stella extended codes):

      Each block in a property file consists of a set of properties for a single game. Stella supports the properties described below:

      - +

      + +

      - + - - - + + + + @@ -3752,9 +4077,7 @@ Ms Pac-Man (Stella extended codes): - - - + @@ -3776,7 +4099,8 @@ Ms Pac-Man (Stella extended codes): - + + @@ -3786,7 +4110,7 @@ Ms Pac-Man (Stella extended codes): - + @@ -3810,7 +4134,7 @@ Ms Pac-Man (Stella extended codes): @@ -3828,7 +4152,7 @@ Ms Pac-Man (Stella extended codes): - +
      Cartridge.Type:Cart.Type: Indicates the bank-switching type for the game. The value of this property must be either Auto or one of the following (for more information about bank-switching see Kevin Horton's 2600 bankswitching @@ -3738,9 +4062,10 @@ Ms Pac-Man (Stella extended codes):
      32IN1 ¹64-128K Multicart (32 games) .32N, .32N1
      64IN1 ¹64/128K Multicart .64N, .64N1
      128IN1 ¹256/512K Multicart .128, .128N1
      2K 32-2048 byte Atari .2K
      3E 32K Tigervision .3E
      3E+ 3E+ (TJ modified DASH) .3EP, .3E+
      2K 32-2048 bytes Atari .2K
      3E 512K Tigervision + 32K RAM.3E
      3EX 512K Tigervision + 256K RAM.3EX
      3E+ 3E+ (TJ modified 3E) .3EP, .3E+
      3F 512K Tigervision .3F
      4A50 ²64K 4A50 + RAM .4A5, .4A50
      4K 4K Atari .4K
      CDF Chris, Darrell, Fred (includes CDFJ).CDF
      CM ¹Spectravideo CompuMate .CM
      CTY ²CDW - Chetiry .CTY
      CV Commavid extra RAM .CV
      CV+ Extended Commavid extra RAM.CVP
      DASH Boulder Dash 2 .DAS, .DASH
      CV CommaVid extra RAM .CV
      DF CPUWIZ 128K .DF
      DFSC CPUWIZ 128K + RAM.DFS, .DFSC
      DPC Pitfall II .DPC
      FC Amiga Power Play Aracde 16/32K .FC
      FE 8K Decathlon .FE
      MDM Menu Driven Megacart .MDM
      SB 128-256k SUPERbanking .SB
      SB 128-256K SUPERbanking .SB
      TVBOY512K TV Boy (127 games).TVB, .TVBOY
      UA 8K UA Ltd. .UA
      UASW 8K UA Ltd. (swapped banks).UASW
      WD Wickstead Design (Pink Panther) .WD
      Cartridge.StartBank:Cart.StartBank: Indicates which bank to use for reading the reset vector.
      Display.VCenter: Indicates the offset for the vertical center of the display. - The value must be n such that -5 <= n <= 5. + The value must be n such that -20 <= n <= 20.
      Cartridge.Sound:Cart.Sound: Indicates if the game should use 1 or 2 channels for sound output. All original Atari 2600 machines supported 1 channel only, but some homebrew games have been written to take advantage of stereo @@ -3836,32 +4160,39 @@ Ms Pac-Man (Stella extended codes):
      +
      - +

      + +

      + - + - + - +
      Console.TelevisionType:Console.TVType: Indicates the default television setting for the game. The value must be Color or BW.
      Console.LeftDifficulty:Console.LeftDiff: Indicates the default difficulty setting for the left player. The value must be A or B.
      Console.RightDifficulty:Console.RightDiff: Indicates the default difficulty setting for the right player. The value must be A or B.
      +
      - +

      + +

      @@ -3908,6 +4239,16 @@ Ms Pac-Man (Stella extended codes): 'Console.SwapPorts'. The value must be Yes or No. + + + + + + + + + +
      Controller.Left:
      Controller.Right:
      Controller.PaddlesXCenter:Defines the horizontal center of the paddles (range -10..30).
      Controller.PaddlesYCenter:Defines the vertical center of the paddles (range -10..30).
      Controller.MouseAxis: Indicates how the mouse should emulate virtual controllers. @@ -3936,18 +4277,21 @@ Ms Pac-Man (Stella extended codes): how to use the X/Y axis (ie, 02 is paddle0/paddle2). -->
      +
      - +

      + +

      - + - + - + - + - + - +
      Cartridge.Name:Cart.Name: Indicates the actual name of the game. When you save snapshots, load/save state files, or use the ROM Audit Mode functionality, this is the name that will be used for the respective file(s).
      Cartridge.MD5:Cart.MD5: Indicates the MD5 checksum of the ROM image as a string of hexadecimal digits. Stella uses this property while attempting to match a game with its block of properties. If the @@ -3958,27 +4302,37 @@ Ms Pac-Man (Stella extended codes):
      Cartridge.Manufacturer:Cart.Manufacturer: Indicates the game's manufacturer.
      Cartridge.ModelNo:Cart.ModelNo: Indicates the manufacturer's model number for the game.
      Cartridge.Rarity:Cart.Rarity: Indicates how rare a cartridge is, based on the scale described on AtariAge.
      Cartridge.Note:Cart.Note: Contains any special notes about playing the game.
      +

      The buttons at the bottom of the dialogs work as follows: +

        +
      • Defaults: Reset the properties to those built into Stella.
      • +
      • Save: Save the properties for the currently selected ROM only + to a properties file in the users default save directory.
      • +
      • OK: Merge/commit any changes into the ROM properties database, which + contains info on all ROMs.
      • +
      • Cancel: Revert any changes in the dialog, and cancel the operation.
      • +
      +

      The name of the properties file will depend on the version of Stella, as follows:

      @@ -3999,7 +4353,7 @@ Ms Pac-Man (Stella extended codes):
      _BASEDIR_/stella.pro
      -

      Stella will require a restart for changes to this file to take effect.

      +

      Note: For manual changes to the property files Stella will require a restart to take effect.


      Palette Support

      @@ -4022,6 +4376,10 @@ Ms Pac-Man (Stella extended codes): user An external palette file, supplied by the user. + + custom + A palette generate from user-defined phase shift. +

      A user-defined palette has certain restrictions, further described as follows: diff --git a/docs/index_r77.html b/docs/index_r77.html index 6050d1367..cc15b11ab 100644 --- a/docs/index_r77.html +++ b/docs/index_r77.html @@ -58,7 +58,7 @@

      Stella for RetroN 77

      Atari 2600 VCS emulator

      -
      Release 6.1 Beta 1
      +
      Release 6.2.1

      Quick Navigation Guide


      diff --git a/src/cheat/CheatCodeDialog.cxx b/src/cheat/CheatCodeDialog.cxx index 780fbea2f..09ac1cd3c 100644 --- a/src/cheat/CheatCodeDialog.cxx +++ b/src/cheat/CheatCodeDialog.cxx @@ -35,46 +35,49 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font) : Dialog(osystem, parent, font, "Cheat codes") { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonWidth = font.getStringWidth("Defaults") + 20, - buttonHeight = font.getLineHeight() + 4; - const int HBORDER = 10; - const int VBORDER = 10 + _th; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonWidth = font.getStringWidth("One shot ") + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; WidgetArray wid; ButtonWidget* b; // Set real dimensions _w = 45 * fontWidth + HBORDER * 2; - _h = 11 * (lineHeight + 4) + VBORDER; + _h = _th + 11 * (lineHeight + 4) + VBORDER * 2; // List of cheats, with checkboxes to enable/disable - xpos = HBORDER; ypos = VBORDER; + xpos = HBORDER; ypos = _th + VBORDER; myCheatList = - new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - 8, - _h - 2*buttonHeight - VBORDER); + new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - fontWidth, + _h - _th - buttonHeight - VBORDER * 3); myCheatList->setEditable(false); wid.push_back(myCheatList); - xpos += myCheatList->getWidth() + 8; ypos = VBORDER; + xpos += myCheatList->getWidth() + fontWidth; ypos = _th + VBORDER; b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Add" + ELLIPSIS, kAddCheatCmd); wid.push_back(b); - ypos += lineHeight + 8; + ypos += lineHeight + VGAP * 2; myEditButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Edit" + ELLIPSIS, kEditCheatCmd); wid.push_back(myEditButton); - ypos += lineHeight + 8; + ypos += lineHeight + VGAP * 2; myRemoveButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Remove", kRemCheatCmd); wid.push_back(myRemoveButton); - ypos += lineHeight + 8 * 3; + ypos += lineHeight + VGAP * 2 * 3; b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "One shot" + ELLIPSIS, kAddOneShotCmd); diff --git a/src/cheat/CheatManager.cxx b/src/cheat/CheatManager.cxx index e106279c6..3f4db3fb4 100644 --- a/src/cheat/CheatManager.cxx +++ b/src/cheat/CheatManager.cxx @@ -213,10 +213,9 @@ void CheatManager::enable(const string& code, bool enable) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheatManager::loadCheatDatabase() { - const string& cheatfile = myOSystem.cheatFile(); - ifstream in(cheatfile); - if(!in) - return; + stringstream in; + try { myOSystem.cheatFile().read(in); } + catch(...) { return; } string line, md5, cheat; string::size_type one, two, three, four; @@ -253,13 +252,12 @@ void CheatManager::saveCheatDatabase() if(!myListIsDirty) return; - const string& cheatfile = myOSystem.cheatFile(); - ofstream out(cheatfile); - if(!out) - return; - + stringstream out; for(const auto& iter: myCheatMap) out << "\"" << iter.first << "\" " << "\"" << iter.second << "\"" << endl; + + try { myOSystem.cheatFile().write(out); } + catch(...) { return; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/AudioSettings.cxx b/src/common/AudioSettings.cxx index 2881c4cfa..640ba9527 100644 --- a/src/common/AudioSettings.cxx +++ b/src/common/AudioSettings.cxx @@ -154,6 +154,12 @@ uInt32 AudioSettings::volume() const return lboundInt(mySettings.getInt(SETTING_VOLUME), 0); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 AudioSettings::device() const +{ + return mySettings.getInt(SETTING_DEVICE); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool AudioSettings::enabled() const { @@ -285,6 +291,14 @@ void AudioSettings::setVolume(uInt32 volume) normalize(mySettings); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void AudioSettings::setDevice(uInt32 device) +{ + if(!myIsPersistent) return; + + mySettings.setValue(SETTING_DEVICE, device); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AudioSettings::setEnabled(bool isEnabled) { diff --git a/src/common/AudioSettings.hxx b/src/common/AudioSettings.hxx index 95104c74f..d319671c3 100644 --- a/src/common/AudioSettings.hxx +++ b/src/common/AudioSettings.hxx @@ -48,6 +48,7 @@ class AudioSettings static constexpr const char* SETTING_RESAMPLING_QUALITY = "audio.resampling_quality"; static constexpr const char* SETTING_STEREO = "audio.stereo"; static constexpr const char* SETTING_VOLUME = "audio.volume"; + static constexpr const char* SETTING_DEVICE = "audio.device"; static constexpr const char* SETTING_ENABLED = "audio.enabled"; static constexpr const char* SETTING_DPC_PITCH = "audio.dpc_pitch"; @@ -59,6 +60,7 @@ class AudioSettings static constexpr ResamplingQuality DEFAULT_RESAMPLING_QUALITY = ResamplingQuality::lanczos_2; static constexpr bool DEFAULT_STEREO = false; static constexpr uInt32 DEFAULT_VOLUME = 80; + static constexpr uInt32 DEFAULT_DEVICE = 0; static constexpr bool DEFAULT_ENABLED = true; static constexpr uInt32 DEFAULT_DPC_PITCH = 20000; @@ -87,6 +89,8 @@ class AudioSettings uInt32 volume() const; + uInt32 device() const; + bool enabled() const; uInt32 dpcPitch() const; @@ -109,6 +113,8 @@ class AudioSettings void setVolume(uInt32 volume); + void setDevice(uInt32 device); + void setEnabled(bool isEnabled); void setPersistent(bool isPersistent); diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index c5ace0f95..7bd88efc0 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -126,6 +126,21 @@ void FilesystemNodeZIP::setFlags(const string& zipfile, _error = zip_error::NOT_READABLE; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FilesystemNodeZIP::exists() const +{ + if(_realNode && _realNode->exists()) + { + // We need to inspect the actual path, not just the ZIP file itself + myZipHandler->open(_zipFile); + while(myZipHandler->hasNext()) + if(BSPF::startsWithIgnoreCase(myZipHandler->next(), _virtualPath)) + return true; + } + + return false; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode) const { @@ -181,7 +196,34 @@ size_t FilesystemNodeZIP::read(ByteBuffer& image) const while(myZipHandler->hasNext() && !found) found = myZipHandler->next() == _virtualPath; - return found ? uInt32(myZipHandler->decompress(image)) : 0; // TODO: 64bit + return found ? myZipHandler->decompress(image) : 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNodeZIP::read(stringstream& image) const +{ + // For now, we just read into a buffer and store in the stream + // TODO: maybe there's a more efficient way to do this? + ByteBuffer buffer; + size_t size = read(buffer); + if(size > 0) + image.write(reinterpret_cast(buffer.get()), size); + + return size; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNodeZIP::write(const ByteBuffer& buffer, size_t size) const +{ + // TODO: Not yet implemented + throw runtime_error("ZIP file not writable"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNodeZIP::write(const stringstream& buffer) const +{ + // TODO: Not yet implemented + throw runtime_error("ZIP file not writable"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 2a46afb4b..079d3c546 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -42,7 +42,7 @@ class FilesystemNodeZIP : public AbstractFSNode */ explicit FilesystemNodeZIP(const string& path); - bool exists() const override { return _realNode && _realNode->exists(); } + bool exists() const override; const string& getName() const override { return _name; } void setName(const string& name) override { _name = name; } const string& getPath() const override { return _path; } @@ -63,6 +63,9 @@ class FilesystemNodeZIP : public AbstractFSNode AbstractFSNodePtr getParent() const override; size_t read(ByteBuffer& image) const override; + size_t read(stringstream& image) const override; + size_t write(const ByteBuffer& buffer, size_t size) const override; + size_t write(const stringstream& buffer) const override; private: FilesystemNodeZIP(const string& zipfile, const string& virtualpath, diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx index d7b9ecb17..24b038d01 100644 --- a/src/common/FrameBufferSDL2.cxx +++ b/src/common/FrameBufferSDL2.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + #include "SDL_lib.hxx" #include "bspf.hxx" #include "Logger.hxx" @@ -48,8 +50,6 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem) // since the structure may be needed before any FBSurface's have // been created myPixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888); - - myWindowedPos = myOSystem.settings().getPoint("windowedpos"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -101,19 +101,32 @@ void FrameBufferSDL2::queryHardware(vector& fullscreenRes, int numModes = SDL_GetNumDisplayModes(i); ostringstream s; - s << "Supported video modes for display " << i << ":"; - Logger::debug(s.str()); + s << "Supported video modes (" << numModes << ") for display " << i << ":"; + + string lastRes = ""; + for (int m = 0; m < numModes; m++) { SDL_DisplayMode mode; + ostringstream res; SDL_GetDisplayMode(i, m, &mode); - s.str(""); - s << " " << m << ": " << mode.w << "x" << mode.h << "@" << mode.refresh_rate << "Hz"; - if (mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate) - s << " (active)"; - Logger::debug(s.str()); + res << std::setw(4) << mode.w << "x" << std::setw(4) << mode.h; + + if(lastRes != res.str()) + { + Logger::debug(s.str()); + s.str(""); + lastRes = res.str(); + s << " " << lastRes << ": "; + } + s << mode.refresh_rate << "Hz"; + if(mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate) + s << "* "; + else + s << " "; } + Logger::debug(s.str()); } // Now get the maximum windowed desktop resolution @@ -183,27 +196,34 @@ void FrameBufferSDL2::queryHardware(vector& fullscreenRes, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int32 FrameBufferSDL2::getCurrentDisplayIndex() +bool FrameBufferSDL2::isCurrentWindowPositioned() const +{ + ASSERT_MAIN_THREAD; + + return !myCenter + && myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Common::Point FrameBufferSDL2::getCurrentWindowPos() const +{ + ASSERT_MAIN_THREAD; + + Common::Point pos; + + SDL_GetWindowPosition(myWindow, &pos.x, &pos.y); + + return pos; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int32 FrameBufferSDL2::getCurrentDisplayIndex() const { ASSERT_MAIN_THREAD; return SDL_GetWindowDisplayIndex(myWindow); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL2::updateWindowedPos() -{ - ASSERT_MAIN_THREAD; - - // only save if the window is not centered and not in full screen mode - if (!myCenter && myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP)) - { - // save current windowed position - SDL_GetWindowPosition(myWindow, &myWindowedPos.x, &myWindowedPos.y); - myOSystem.settings().setValue("windowedpos", myWindowedPos); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) { @@ -213,31 +233,13 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) if(SDL_WasInit(SDL_INIT_VIDEO) == 0) return false; - Int32 displayIndex = mode.fsIndex; - if (displayIndex == -1) - { - // windowed mode - if (myWindow) - { - // Show it on same screen as the previous window - displayIndex = SDL_GetWindowDisplayIndex(myWindow); - } - if (displayIndex < 0) - { - // fallback to the last used screen if still existing - displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt("display")); - } - } + const bool fullScreen = mode.fsIndex != -1; + bool forceCreateRenderer = false; - // save and get last windowed window's position - updateWindowedPos(); - - // Always recreate renderer (some systems need this) - if(myRenderer) - { - SDL_DestroyRenderer(myRenderer); - myRenderer = nullptr; - } + // Get windowed window's last display + Int32 displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt(getDisplayKey())); + // Get windowed window's last position + myWindowedPos = myOSystem.settings().getPoint(getPositionKey()); int posX, posY; @@ -249,7 +251,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) posX = myWindowedPos.x; posY = myWindowedPos.y; - // make sure the window is at least partially visibile + // Make sure the window is at least partially visibile int x0 = 0, y0 = 0, x1 = 0, y1 = 0; for (int display = SDL_GetNumVideoDisplays() - 1; display >= 0; display--) @@ -267,47 +269,45 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) posX = BSPF::clamp(posX, x0 - Int32(mode.screen.w) + 50, x1 - 50); posY = BSPF::clamp(posY, y0 + 50, y1 - 50); } - uInt32 flags = mode.fsIndex != -1 ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0; - flags |= SDL_WINDOW_ALLOW_HIGHDPI; - // macOS seems to have issues with destroying the window, and wants to - // keep the same handle - // Problem is, doing so on other platforms results in flickering when - // toggling fullscreen windowed mode - // So we have a special case for macOS -#ifndef BSPF_MACOS - // Don't re-create the window if its size hasn't changed, as it's not - // necessary, and causes flashing in fullscreen mode +#ifdef ADAPTABLE_REFRESH_SUPPORT + SDL_DisplayMode adaptedSdlMode; + const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh") + && gameRefreshRate() + // take care of 59.94 Hz + && refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0; + const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode); +#else + const bool adaptRefresh = false; +#endif + const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI + | (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + + // Don't re-create the window if its display and size hasn't changed, + // as it's not necessary, and causes flashing in fullscreen mode if(myWindow) { + const int d = SDL_GetWindowDisplayIndex(myWindow); int w, h; + SDL_GetWindowSize(myWindow, &w, &h); - if(uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h) + if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h + || adaptRefresh) { SDL_DestroyWindow(myWindow); myWindow = nullptr; } } + if(myWindow) { // Even though window size stayed the same, the title may have changed SDL_SetWindowTitle(myWindow, title.c_str()); SDL_SetWindowPosition(myWindow, posX, posY); } -#else - // macOS wants to *never* re-create the window - // This sometimes results in the window being resized *after* it's displayed, - // but at least the code works and doesn't crash - if(myWindow) - { - SDL_SetWindowFullscreen(myWindow, flags); - SDL_SetWindowSize(myWindow, mode.screen.w, mode.screen.h); - SDL_SetWindowPosition(myWindow, posX, posY); - SDL_SetWindowTitle(myWindow, title.c_str()); - } -#endif else { + forceCreateRenderer = true; myWindow = SDL_CreateWindow(title.c_str(), posX, posY, mode.screen.w, mode.screen.h, flags); if(myWindow == nullptr) @@ -316,30 +316,133 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode) Logger::error(msg); return false; } + setWindowIcon(); } - uInt32 renderFlags = SDL_RENDERER_ACCELERATED; - if(myOSystem.settings().getBool("vsync")) // V'synced blits option - renderFlags |= SDL_RENDERER_PRESENTVSYNC; - const string& video = myOSystem.settings().getString("video"); // Render hint - if(video != "") - SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str()); - - myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags); - - detectFeatures(); - determineDimensions(); - - if(myRenderer == nullptr) +#ifdef ADAPTABLE_REFRESH_SUPPORT + if(adaptRefresh) { - string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError()); - Logger::error(msg); + // Switch to mode for adapted refresh rate + if(SDL_SetWindowDisplayMode(myWindow, &adaptedSdlMode) != 0) + { + Logger::error("ERROR: Display refresh rate change failed"); + } + else + { + ostringstream msg; + + msg << "Display refresh rate changed to " << adaptedSdlMode.refresh_rate << " Hz"; + Logger::info(msg.str()); + } + } +#endif + + return createRenderer(forceCreateRenderer); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode) +{ + SDL_DisplayMode sdlMode; + + if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0) + { + Logger::error("ERROR: Display mode could not be retrieved"); return false; } + + const int currentRefreshRate = sdlMode.refresh_rate; + const int wantedRefreshRate = gameRefreshRate(); + // Take care of rounded refresh rates (e.g. 59.94 Hz) + float factor = std::min(float(currentRefreshRate) / wantedRefreshRate, + float(currentRefreshRate) / (wantedRefreshRate - 1)); + // Calculate difference taking care of integer factors (e.g. 100/120) + float bestDiff = std::abs(factor - std::round(factor)) / factor; + bool adapt = false; + + // Display refresh rate should be an integer factor of the game's refresh rate + // Note: Modes are scanned with size being first priority, + // therefore the size will never change. + // Check for integer factors 1 (60/50 Hz) and 2 (120/100 Hz) + for(int m = 1; m <= 2; ++m) + { + SDL_DisplayMode closestSdlMode; + + sdlMode.refresh_rate = wantedRefreshRate * m; + if(SDL_GetClosestDisplayMode(displayIndex, &sdlMode, &closestSdlMode) == nullptr) + { + Logger::error("ERROR: Closest display mode could not be retrieved"); + return adapt; + } + factor = std::min(float(sdlMode.refresh_rate) / sdlMode.refresh_rate, + float(sdlMode.refresh_rate) / (sdlMode.refresh_rate - 1)); + const float diff = std::abs(factor - std::round(factor)) / factor; + if(diff < bestDiff) + { + bestDiff = diff; + adaptedSdlMode = closestSdlMode; + adapt = true; + } + } + //cerr << "refresh rate adapt "; + //if(adapt) + // cerr << "required (" << currentRefreshRate << " Hz -> " << adaptedSdlMode.refresh_rate << " Hz)"; + //else + // cerr << "not required/possible"; + //cerr << endl; + + // Only change if the display supports a better refresh rate + return adapt; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferSDL2::createRenderer(bool force) +{ + // A new renderer is only created when necessary: + // - new myWindow (force = true) + // - no renderer existing + // - different renderer flags + // - different renderer name + bool recreate = force || myRenderer == nullptr; + uInt32 renderFlags = SDL_RENDERER_ACCELERATED; + const string& video = myOSystem.settings().getString("video"); // Render hint + SDL_RendererInfo renderInfo; + + if(myOSystem.settings().getBool("vsync") + && !myOSystem.settings().getBool("turbo")) // V'synced blits option + renderFlags |= SDL_RENDERER_PRESENTVSYNC; + + // check renderer flags and name + recreate |= (SDL_GetRendererInfo(myRenderer, &renderInfo) != 0) + || ((renderInfo.flags & (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != renderFlags + || (video != renderInfo.name)); + + if(recreate) + { + //cerr << "Create new renderer for buffer type #" << int(myBufferType) << endl; + if(myRenderer) + SDL_DestroyRenderer(myRenderer); + + if(video != "") + SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str()); + + myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags); + + detectFeatures(); + determineDimensions(); + + if(myRenderer == nullptr) + { + string msg = "ERROR: Unable to create SDL renderer: " + string(SDL_GetError()); + Logger::error(msg); + return false; + } + } clear(); SDL_RendererInfo renderinfo; + if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0) myOSystem.settings().setValue("video", renderinfo.name); @@ -407,6 +510,36 @@ bool FrameBufferSDL2::fullScreen() const #endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int FrameBufferSDL2::refreshRate() const +{ + ASSERT_MAIN_THREAD; + + const uInt32 displayIndex = SDL_GetWindowDisplayIndex(myWindow); + SDL_DisplayMode sdlMode; + + if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) == 0) + return sdlMode.refresh_rate; + + if(myWindow != nullptr) + Logger::error("Could not retrieve current display mode"); + + return 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int FrameBufferSDL2::gameRefreshRate() const +{ + if(myOSystem.hasConsole()) + { + const string format = myOSystem.console().getFormatString(); + const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60"; + + return isNtsc ? 60 : 50; // The code will take care of 59/49 Hz + } + return 0; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBufferSDL2::renderToScreen() { @@ -419,10 +552,9 @@ void FrameBufferSDL2::renderToScreen() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBufferSDL2::setWindowIcon() { - ASSERT_MAIN_THREAD; - #if !defined(BSPF_MACOS) && !defined(RETRON77) #include "stella_icon.hxx" + ASSERT_MAIN_THREAD; SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(stella_icon, 32, 32, 32, 32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000); diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index 64803e6bb..7904ed0ee 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -95,6 +95,21 @@ class FrameBufferSDL2 : public FrameBuffer */ void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const override; + /** + This method is called to query if the current window is not centered + or fullscreen. + + @return True, if the current window is positioned + */ + bool isCurrentWindowPositioned() const override; + + /** + This method is called to query the video hardware for position of + the current window + + @return The position of the currently displayed window + */ + Common::Point getCurrentWindowPos() const override; /** This method is called to query the video hardware for the index of the display the current window is displayed on @@ -102,12 +117,7 @@ class FrameBufferSDL2 : public FrameBuffer @return the current display index or a negative value if no window is displayed */ - Int32 getCurrentDisplayIndex() override; - - /** - This method is called to preserve the last current windowed position. - */ - void updateWindowedPos() override; + Int32 getCurrentDisplayIndex() const override; /** Clear the frame buffer. @@ -137,12 +147,12 @@ class FrameBufferSDL2 : public FrameBuffer /** Transform from window to renderer coordinates, x direction */ - int scaleX(int x) const { return (x * myRenderW) / myWindowW; } + int scaleX(int x) const override { return (x * myRenderW) / myWindowW; } /** Transform from window to renderer coordinates, y direction */ - int scaleY(int y) const { return (y * myRenderH) / myWindowH; } + int scaleY(int y) const override { return (y * myRenderH) / myWindowH; } protected: ////////////////////////////////////////////////////////////////////// @@ -171,6 +181,25 @@ class FrameBufferSDL2 : public FrameBuffer */ bool setVideoMode(const string& title, const VideoMode& mode) override; + /** + Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode + + @param displayIndex The display which should be checked + @param adaptedSdlMode The best matching mode if the refresh rate should be changed + + @return True if the refresh rate should be changed + */ + bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode); + + /** + Create a new renderer if required + + @param force If true, force new renderer creation + + @return False on any errors, else true + */ + bool createRenderer(bool force); + /** This method is called to create a surface with the given attributes. @@ -223,6 +252,16 @@ class FrameBufferSDL2 : public FrameBuffer */ void determineDimensions(); + /** + Retrieve the current display's refresh rate, or 0 if no window + */ + int refreshRate() const override; + + /** + Retrieve the current game's refresh rate, or 60 if no game + */ + int gameRefreshRate() const; + private: // The SDL video buffer SDL_Window* myWindow{nullptr}; diff --git a/src/common/JoyMap.cxx b/src/common/JoyMap.cxx index 2a20b4a8b..266dd5e74 100644 --- a/src/common/JoyMap.cxx +++ b/src/common/JoyMap.cxx @@ -185,9 +185,35 @@ JoyMap::JoyMappingArray JoyMap::getEventMapping(const Event::Type event, const E // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string JoyMap::saveMapping(const EventMode mode) const { + using MapType = std::pair; + std::vector sortedMap(myMap.begin(), myMap.end()); + + std::sort(sortedMap.begin(), sortedMap.end(), + [](const MapType& a, const MapType& b) + { + // Event::Type first + if(a.second != b.second) + return a.second < b.second; + + if(a.first.button != b.first.button) + return a.first.button < b.first.button; + + if(a.first.axis != b.first.axis) + return a.first.axis < b.first.axis; + + if(a.first.adir != b.first.adir) + return a.first.adir < b.first.adir; + + if(a.first.hat != b.first.hat) + return a.first.hat < b.first.hat; + + return a.first.hdir < b.first.hdir; + } + ); + ostringstream buf; - for (auto item : myMap) + for (auto item : sortedMap) { if (item.first.mode == mode) { diff --git a/src/common/JoyMap.hxx b/src/common/JoyMap.hxx index 6448de1ff..e3cc7ff7a 100644 --- a/src/common/JoyMap.hxx +++ b/src/common/JoyMap.hxx @@ -19,6 +19,7 @@ #define CONTROLLERMAP_HXX #include + #include "Event.hxx" #include "EventHandlerConstants.hxx" diff --git a/src/common/KeyMap.cxx b/src/common/KeyMap.cxx index eca0369ec..47b34dc9c 100644 --- a/src/common/KeyMap.cxx +++ b/src/common/KeyMap.cxx @@ -16,11 +16,12 @@ //============================================================================ #include "KeyMap.hxx" +#include // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void KeyMap::add(const Event::Type event, const Mapping& mapping) { - myMap[convertMod(mapping)] = event; + myMap[convertMod(mapping)] = event; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -32,7 +33,7 @@ void KeyMap::add(const Event::Type event, const EventMode mode, const int key, c // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void KeyMap::erase(const Mapping& mapping) { - myMap.erase(convertMod(mapping)); + myMap.erase(convertMod(mapping)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -170,9 +171,26 @@ KeyMap::MappingArray KeyMap::getEventMapping(const Event::Type event, const Even // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string KeyMap::saveMapping(const EventMode mode) const { + using MapType = std::pair; + std::vector sortedMap(myMap.begin(), myMap.end()); + + std::sort(sortedMap.begin(), sortedMap.end(), + [](const MapType& a, const MapType& b) + { + // Event::Type first + if(a.second != b.second) + return a.second < b.second; + + if(a.first.key != b.first.key) + return a.first.key < b.first.key; + + return a.first.mod < b.first.mod; + } + ); + ostringstream buf; - for (auto item : myMap) + for (auto item : sortedMap) { if (item.first.mode == mode) { diff --git a/src/common/KeyMap.hxx b/src/common/KeyMap.hxx index 94d3b4242..0b7eff2fe 100644 --- a/src/common/KeyMap.hxx +++ b/src/common/KeyMap.hxx @@ -21,6 +21,7 @@ #include #include "Event.hxx" #include "EventHandlerConstants.hxx" +#include "StellaKeys.hxx" /** This class handles keyboard mappings in Stella. diff --git a/src/common/LinkedObjectPool.hxx b/src/common/LinkedObjectPool.hxx index ab4a2fcbd..7c35439e3 100644 --- a/src/common/LinkedObjectPool.hxx +++ b/src/common/LinkedObjectPool.hxx @@ -49,7 +49,7 @@ */ namespace Common { -template +template class LinkedObjectPool { public: diff --git a/src/common/MouseControl.cxx b/src/common/MouseControl.cxx index 35d8941f9..ee960c6bb 100644 --- a/src/common/MouseControl.cxx +++ b/src/common/MouseControl.cxx @@ -124,7 +124,7 @@ MouseControl::MouseControl(Console& console, const string& mode) int m_range = 100; if(!(m_axis >> m_range)) m_range = 100; - Paddles::setPaddleRange(m_range); + Paddles::setDigitalPaddleRange(m_range); // If the mouse isn't used at all, we still need one item in the list if(myModeList.size() == 0) diff --git a/src/common/PJoystickHandler.cxx b/src/common/PJoystickHandler.cxx index e67793078..1af10feac 100644 --- a/src/common/PJoystickHandler.cxx +++ b/src/common/PJoystickHandler.cxx @@ -250,9 +250,9 @@ void PhysicalJoystickHandler::setDefaultAction(int stick, if(updateDefaults) { - // if there is no existing mapping for the event or + // if there is no existing mapping for the event and // the default mapping for the event is unused, set default key for event - if(j->joyMap.getEventMapping(map.event, mode).size() == 0 || + if(j->joyMap.getEventMapping(map.event, mode).size() == 0 && !j->joyMap.check(mode, map.button, map.axis, map.adir, map.hat, map.hdir)) { if (map.hat == JOY_CTRL_NONE) @@ -687,27 +687,32 @@ void PhysicalJoystickHandler::handleAxisEvent(int stick, int axis, int value) } j->axisLastValue[axis] = value; } + #ifdef GUI_SUPPORT else if(myHandler.hasOverlay()) { - // First, clamp the values to simulate digital input - // (the only thing that the underlying code understands) - if(value > Joystick::deadzone()) - value = 32000; - else if(value < -Joystick::deadzone()) - value = -32000; - else - value = 0; - - // Now filter out consecutive, similar values - // (only pass on the event if the state has changed) - if(value != j->axisLastValue[axis]) + // A value change lower than Joystick::deadzone indicates analog input which is ignored + if((abs(j->axisLastValue[axis] - value) > Joystick::deadzone())) { -#ifdef GUI_SUPPORT - myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button); -#endif - j->axisLastValue[axis] = value; + // First, clamp the values to simulate digital input + // (the only thing that the underlying code understands) + if(value > Joystick::deadzone()) + value = 32000; + else if(value < -Joystick::deadzone()) + value = -32000; + else + value = 0; + + // Now filter out consecutive, similar values + // (only pass on the event if the state has changed) + if(value != j->axisLastValue[axis]) + { + myHandler.overlay().handleJoyAxisEvent(stick, JoyAxis(axis), convertAxisValue(value), button); + + } } + j->axisLastValue[axis] = value; } + #endif } } diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index 7197d2426..9a5c91bd5 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -17,13 +17,7 @@ #include "OSystem.hxx" #include "Console.hxx" -#include "Settings.hxx" #include "EventHandler.hxx" -#include "Sound.hxx" -#include "StateManager.hxx" -#include "StellaKeys.hxx" -#include "TIASurface.hxx" -#include "PNGLibrary.hxx" #include "PKeyboardHandler.hxx" #ifdef DEBUGGER_SUPPORT @@ -45,6 +39,7 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler& myHandler(handler) { Int32 version = myOSystem.settings().getInt("event_ver"); + bool updateDefaults = false; // Compare if event list version has changed so that key maps became invalid if (version == Event::VERSION) @@ -59,11 +54,37 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler& myKeyMap.loadMapping(list, EventMode::kKeypadMode); list = myOSystem.settings().getString("keymap_ui"); myKeyMap.loadMapping(list, EventMode::kMenuMode); + updateDefaults = true; } myKeyMap.enableMod() = myOSystem.settings().getBool("modcombo"); - setDefaultMapping(Event::NoType, EventMode::kEmulationMode, true); - setDefaultMapping(Event::NoType, EventMode::kMenuMode, true); + setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults); + setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool PhysicalKeyboardHandler::isMappingUsed(EventMode mode, const EventMapping& map) const +{ + // Menu events can only interfere with + // - other menu events + if(mode == EventMode::kMenuMode) + return myKeyMap.check(EventMode::kMenuMode, map.key, map.mod); + + // Controller events can interfere with + // - other events of the same controller + // - and common emulation events + if(mode != EventMode::kCommonMode) + return myKeyMap.check(mode, map.key, map.mod) + || myKeyMap.check(EventMode::kCommonMode, map.key, map.mod); + + // Common emulation events can interfere with + // - other common emulation events + // - and all controller events + return myKeyMap.check(EventMode::kCommonMode, map.key, map.mod) + || myKeyMap.check(EventMode::kJoystickMode, map.key, map.mod) + || myKeyMap.check(EventMode::kPaddlesMode, map.key, map.mod) + || myKeyMap.check(EventMode::kKeypadMode, map.key, map.mod) + || myKeyMap.check(EventMode::kCompuMateMode, map.key, map.mod); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -80,10 +101,10 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event, if (updateDefaults) { - // if there is no existing mapping for the event or + // if there is no existing mapping for the event and // the default mapping for the event is unused, set default key for event - if (myKeyMap.getEventMapping(map.event, mode).size() == 0 || - !myKeyMap.check(mode, map.key, map.mod)) + if (myKeyMap.getEventMapping(map.event, mode).size() == 0 && + !isMappingUsed(mode, map)) { addMapping(map.event, mode, map.key, StellaMod(map.mod)); } @@ -395,6 +416,7 @@ void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pre { case EventHandlerState::EMULATION: case EventHandlerState::PAUSE: + case EventHandlerState::PLAYBACK: myHandler.handleEvent(myKeyMap.get(EventMode::kEmulationMode, key, mod), pressed, repeated); break; @@ -424,7 +446,11 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::LoadState, KBDK_F11}, {Event::LoadAllStates, KBDK_F11, MOD3}, {Event::TakeSnapshot, KBDK_F12}, +#ifdef BSPF_MACOS + {Event::TogglePauseMode, KBDK_P, KBDM_SHIFT | MOD3}, +#else {Event::TogglePauseMode, KBDK_PAUSE}, +#endif {Event::OptionsMenuMode, KBDK_TAB}, {Event::CmdMenuMode, KBDK_BACKSLASH}, {Event::TimeMachineMode, KBDK_T, KBDM_SHIFT}, @@ -436,45 +462,83 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::Quit, KBDK_Q, KBDM_CTRL}, #endif {Event::ReloadConsole, KBDK_R, KBDM_CTRL}, + {Event::PreviousMultiCartRom, KBDK_R, KBDM_SHIFT | KBDM_CTRL}, {Event::VidmodeDecrease, KBDK_MINUS, MOD3}, {Event::VidmodeIncrease, KBDK_EQUALS, MOD3}, {Event::VCenterDecrease, KBDK_PAGEUP, MOD3}, {Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3}, - {Event::ScanlineAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3}, - {Event::ScanlineAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3}, + {Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3}, + {Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3}, {Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3}, {Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3}, {Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL}, {Event::ToggleFullScreen, KBDK_RETURN, MOD3}, + {Event::ToggleAdaptRefresh, KBDK_R, MOD3}, {Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT}, {Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT}, - {Event::VidmodeStd, KBDK_1, MOD3}, - {Event::VidmodeRGB, KBDK_2, MOD3}, - {Event::VidmodeSVideo, KBDK_3, MOD3}, - {Event::VidModeComposite, KBDK_4, MOD3}, - {Event::VidModeBad, KBDK_5, MOD3}, - {Event::VidModeCustom, KBDK_6, MOD3}, - {Event::PreviousAttribute, KBDK_7, KBDM_SHIFT | MOD3}, - {Event::NextAttribute, KBDK_7, MOD3}, - {Event::DecreaseAttribute, KBDK_8, KBDM_SHIFT | MOD3}, - {Event::IncreaseAttribute, KBDK_8, MOD3}, - {Event::PhosphorDecrease, KBDK_9, KBDM_SHIFT | MOD3}, - {Event::PhosphorIncrease, KBDK_9, MOD3}, + //{Event::VidmodeStd, KBDK_1, MOD3}, + //{Event::VidmodeRGB, KBDK_2, MOD3}, + //{Event::VidmodeSVideo, KBDK_3, MOD3}, + //{Event::VidModeComposite, KBDK_4, MOD3}, + //{Event::VidModeBad, KBDK_5, MOD3}, + //{Event::VidModeCustom, KBDK_6, MOD3}, + {Event::PreviousVideoMode, KBDK_1, KBDM_SHIFT | MOD3}, + {Event::NextVideoMode, KBDK_1, MOD3}, + {Event::PreviousAttribute, KBDK_2, KBDM_SHIFT | MOD3}, + {Event::NextAttribute, KBDK_2, MOD3}, + {Event::DecreaseAttribute, KBDK_3, KBDM_SHIFT | MOD3}, + {Event::IncreaseAttribute, KBDK_3, MOD3}, + {Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3}, + {Event::PhosphorIncrease, KBDK_4, MOD3}, {Event::TogglePhosphor, KBDK_P, MOD3}, - {Event::ScanlinesDecrease, KBDK_0, KBDM_SHIFT | MOD3}, - {Event::ScanlinesIncrease, KBDK_0, MOD3}, + {Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3}, + {Event::ScanlinesIncrease, KBDK_5, MOD3}, + {Event::PreviousPaletteAttribute, KBDK_9, KBDM_SHIFT | MOD3}, + {Event::NextPaletteAttribute, KBDK_9, MOD3}, + {Event::PaletteAttributeDecrease, KBDK_0, KBDM_SHIFT | MOD3}, + {Event::PaletteAttributeIncrease, KBDK_0, MOD3}, {Event::ToggleColorLoss, KBDK_L, KBDM_CTRL}, - {Event::TogglePalette, KBDK_P, KBDM_CTRL}, + {Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL}, + {Event::PaletteIncrease, KBDK_P, KBDM_CTRL}, + +#ifndef BSPF_MACOS + {Event::PreviousSetting, KBDK_END}, + {Event::NextSetting, KBDK_HOME}, + {Event::PreviousSettingGroup, KBDK_END, KBDM_CTRL}, + {Event::NextSettingGroup, KBDK_HOME, KBDM_CTRL}, +#else + // HOME & END keys are swapped on Mac keyboards + {Event::PreviousSetting, KBDK_HOME}, + {Event::NextSetting, KBDK_END}, + {Event::PreviousSettingGroup, KBDK_HOME, KBDM_CTRL}, + {Event::NextSettingGroup, KBDK_END, KBDM_CTRL}, +#endif + {Event::PreviousSetting, KBDK_KP_1}, + {Event::NextSetting, KBDK_KP_7}, + {Event::PreviousSettingGroup, KBDK_KP_1, KBDM_CTRL}, + {Event::NextSettingGroup, KBDK_KP_7, KBDM_CTRL}, + {Event::SettingDecrease, KBDK_PAGEDOWN}, + {Event::SettingDecrease, KBDK_KP_3, KBDM_CTRL}, + {Event::SettingIncrease, KBDK_PAGEUP}, + {Event::SettingIncrease, KBDK_KP_9, KBDM_CTRL}, + {Event::ToggleInter, KBDK_I, KBDM_CTRL}, + {Event::DecreaseSpeed, KBDK_S, KBDM_SHIFT | KBDM_CTRL}, + {Event::IncreaseSpeed, KBDK_S, KBDM_CTRL }, + {Event::ToggleTurbo, KBDK_T, KBDM_CTRL}, {Event::ToggleJitter, KBDK_J, MOD3}, {Event::ToggleFrameStats, KBDK_L, MOD3}, {Event::ToggleTimeMachine, KBDK_T, MOD3}, + #ifdef PNG_SUPPORT {Event::ToggleContSnapshots, KBDK_S, MOD3}, {Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3}, #endif + + {Event::DecreaseAutoFire, KBDK_A, KBDM_SHIFT | KBDM_CTRL}, + {Event::IncreaseAutoFire, KBDK_A, KBDM_CTRL }, {Event::HandleMouseControl, KBDK_0, KBDM_CTRL}, {Event::ToggleGrabMouse, KBDK_G, KBDM_CTRL}, {Event::ToggleSAPortOrder, KBDK_1, KBDM_CTRL}, @@ -506,6 +570,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::Unwind10Menu, KBDK_RIGHT, KBDM_SHIFT | MOD3}, {Event::UnwindAllMenu, KBDK_UP, MOD3}, {Event::HighScoresMenuMode, KBDK_INSERT}, + {Event::TogglePlayBackMode, KBDK_SPACE, KBDM_SHIFT}, #if defined(RETRON77) {Event::ConsoleColorToggle, KBDK_F4}, // back ("COLOR","B/W") diff --git a/src/common/PKeyboardHandler.hxx b/src/common/PKeyboardHandler.hxx index adb9b5106..ede6aa55a 100644 --- a/src/common/PKeyboardHandler.hxx +++ b/src/common/PKeyboardHandler.hxx @@ -87,6 +87,9 @@ class PhysicalKeyboardHandler }; using EventMappingArray = std::vector; + // Checks if the given mapping is used by any event mode + bool isMappingUsed(EventMode mode, const EventMapping& map) const; + void setDefaultKey(EventMapping map, Event::Type event = Event::NoType, EventMode mode = EventMode::kEmulationMode, bool updateDefaults = false); diff --git a/src/common/PNGLibrary.cxx b/src/common/PNGLibrary.cxx index 779f6b0f6..ae7d3390f 100644 --- a/src/common/PNGLibrary.cxx +++ b/src/common/PNGLibrary.cxx @@ -29,6 +29,7 @@ #include "TIASurface.hxx" #include "Version.hxx" #include "PNGLibrary.hxx" +#include "Rect.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PNGLibrary::PNGLibrary(OSystem& osystem) @@ -51,7 +52,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface) throw runtime_error(s); }; - ifstream in(filename, std::ios_base::binary); + std::ifstream in(filename, std::ios_base::binary); if(!in.is_open()) loadImageERROR("No snapshot found"); @@ -88,7 +89,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface) } else if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - loadImageERROR("Greyscale PNG images not supported"); + png_set_gray_to_rgb(png_ptr); } else if(color_type == PNG_COLOR_TYPE_PALETTE) { @@ -124,12 +125,18 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::saveImage(const string& filename, const VariantList& comments) { - ofstream out(filename, std::ios_base::binary); + std::ofstream out(filename, std::ios_base::binary); if(!out.is_open()) throw runtime_error("ERROR: Couldn't create snapshot file"); const FrameBuffer& fb = myOSystem.frameBuffer(); - const Common::Rect& rect = fb.imageRect(); + + const Common::Rect& rectUnscaled = fb.imageRect(); + const Common::Rect rect( + Common::Point(fb.scaleX(rectUnscaled.x()), fb.scaleY(rectUnscaled.y())), + fb.scaleX(rectUnscaled.w()), fb.scaleY(rectUnscaled.h()) + ); + png_uint_32 width = rect.w(), height = rect.h(); // Get framebuffer pixel data (we get ABGR format) @@ -149,7 +156,7 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments) void PNGLibrary::saveImage(const string& filename, const FBSurface& surface, const Common::Rect& rect, const VariantList& comments) { - ofstream out(filename, std::ios_base::binary); + std::ofstream out(filename, std::ios_base::binary); if(!out.is_open()) throw runtime_error("ERROR: Couldn't create snapshot file"); @@ -175,7 +182,7 @@ void PNGLibrary::saveImage(const string& filename, const FBSurface& surface, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::saveImageToDisk(ofstream& out, const vector& rows, +void PNGLibrary::saveImageToDisk(std::ofstream& out, const vector& rows, png_uint_32 width, png_uint_32 height, const VariantList& comments) { png_structp png_ptr = nullptr; @@ -290,7 +297,7 @@ void PNGLibrary::takeSnapshot(uInt32 number) // Figure out the correct snapshot name string filename; bool showmessage = number == 0; - string sspath = myOSystem.snapshotSaveDir() + + string sspath = myOSystem.snapshotSaveDir().getPath() + (myOSystem.settings().getString("snapname") != "int" ? myOSystem.romFile().getNameWithExt("") : myOSystem.console().properties().get(PropType::Cart_Name)); @@ -449,21 +456,21 @@ void PNGLibrary::writeComments(png_structp png_ptr, png_infop info_ptr, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::png_read_data(png_structp ctx, png_bytep area, png_size_t size) { - (static_cast(png_get_io_ptr(ctx)))->read( + (static_cast(png_get_io_ptr(ctx)))->read( reinterpret_cast(area), size); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::png_write_data(png_structp ctx, png_bytep area, png_size_t size) { - (static_cast(png_get_io_ptr(ctx)))->write( + (static_cast(png_get_io_ptr(ctx)))->write( reinterpret_cast(area), size); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PNGLibrary::png_io_flush(png_structp ctx) { - (static_cast(png_get_io_ptr(ctx)))->flush(); + (static_cast(png_get_io_ptr(ctx)))->flush(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/PNGLibrary.hxx b/src/common/PNGLibrary.hxx index fe177ad83..04876d85b 100644 --- a/src/common/PNGLibrary.hxx +++ b/src/common/PNGLibrary.hxx @@ -165,7 +165,7 @@ class PNGLibrary @param height The height of the PNG image @param comments The text comments to add to the PNG image */ - void saveImageToDisk(ofstream& out, const vector& rows, + void saveImageToDisk(std::ofstream& out, const vector& rows, png_uint_32 width, png_uint_32 height, const VariantList& comments); diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx new file mode 100644 index 000000000..030ff4d9e --- /dev/null +++ b/src/common/PaletteHandler.cxx @@ -0,0 +1,723 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include + +#include "Console.hxx" +#include "FrameBuffer.hxx" + +#include "PaletteHandler.hxx" + +PaletteHandler::PaletteHandler(OSystem& system) + : myOSystem(system) +{ + // Load user-defined palette for this ROM + loadUserPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) const +{ + if(name == SETTING_Z26) + return PaletteType::Z26; + + if(name == SETTING_USER && myUserPaletteDefined) + return PaletteType::User; + + if(name == SETTING_CUSTOM) + return PaletteType::Custom; + + return PaletteType::Standard; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string PaletteHandler::toPaletteName(PaletteType type) const +{ + const string SETTING_NAMES[int(PaletteType::NumTypes)] = { + SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM + }; + + return SETTING_NAMES[type]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::cyclePalette(int direction) +{ + const string MESSAGES[PaletteType::NumTypes] = { + "Standard Stella", "Z26", "User-defined", "Custom" + }; + int type = toPaletteType(myOSystem.settings().getString("palette")); + + do { + type = BSPF::clampw(type + direction, int(PaletteType::MinType), int(PaletteType::MaxType)); + } while(type == PaletteType::User && !myUserPaletteDefined); + + const string palette = toPaletteName(PaletteType(type)); + const string message = MESSAGES[type] + " palette"; + + myOSystem.frameBuffer().showMessage(message); + + setPalette(palette); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::showAdjustableMessage() +{ + const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr; + ostringstream msg, buf; + + msg << "Palette " << myAdjustables[myCurrentAdjustable].name; + if(isPhaseShift) + { + const ConsoleTiming timing = myOSystem.console().timing(); + const bool isNTSC = timing == ConsoleTiming::ntsc; + const float value = + myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC; + buf << std::fixed << std::setprecision(1) << value << DEGREE; + myOSystem.frameBuffer().showMessage( + "Palette phase shift", buf.str(), value, + (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT, + (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT); + } + else + { + const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value); + buf << value << "%"; + myOSystem.frameBuffer().showMessage( + msg.str(), buf.str(), value); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::cycleAdjustable(int direction) +{ + const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette"); + bool isPhaseShift; + + do { + myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1); + isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr; + // skip phase shift when 'Custom' palette is not selected + if(!direction && isPhaseShift && !isCustomPalette) + myCurrentAdjustable++; + } while(isPhaseShift && !isCustomPalette); + + showAdjustableMessage(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeAdjustable(int adjustable, int direction) +{ + const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette"); + const bool isPhaseShift = myAdjustables[adjustable].value == nullptr; + + myCurrentAdjustable = adjustable; + if(isPhaseShift && !isCustomPalette) + myCurrentAdjustable++; + + changeCurrentAdjustable(direction); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeCurrentAdjustable(int direction) +{ + if(myAdjustables[myCurrentAdjustable].value == nullptr) + changeColorPhaseShift(direction); + else + { + int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value); + + newVal = BSPF::clamp(newVal + direction * 1, 0, 100); + + *myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal); + + showAdjustableMessage(); + setPalette(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::changeColorPhaseShift(int direction) +{ + const ConsoleTiming timing = myOSystem.console().timing(); + + // SECAM is not supported + if(timing != ConsoleTiming::secam) + { + const bool isNTSC = timing == ConsoleTiming::ntsc; + const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT; + float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL; + + newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_SHIFT, shift + MAX_SHIFT); + + if(isNTSC) + myPhaseNTSC = newPhase; + else + myPhasePAL = newPhase; + + generateCustomPalette(timing); + setPalette(SETTING_CUSTOM); + + showAdjustableMessage(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::loadConfig(const Settings& settings) +{ + // Load adjustables + myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"), + DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT); + myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"), + DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT); + + myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F); + mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F); + myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F); + myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F); + myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::saveConfig(Settings& settings) const +{ + // Save adjustables + settings.setValue("pal.phase_ntsc", myPhaseNTSC); + settings.setValue("pal.phase_pal", myPhasePAL); + + settings.setValue("pal.hue", myHue); + settings.setValue("pal.saturation", mySaturation); + settings.setValue("pal.contrast", myContrast); + settings.setValue("pal.brightness", myBrightness); + settings.setValue("pal.gamma", myGamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setAdjustables(const Adjustable& adjustable) +{ + myPhaseNTSC = adjustable.phaseNtsc / 10.F; + myPhasePAL = adjustable.phasePal / 10.F; + + myHue = scaleFrom100(adjustable.hue); + mySaturation = scaleFrom100(adjustable.saturation); + myContrast = scaleFrom100(adjustable.contrast); + myBrightness = scaleFrom100(adjustable.brightness); + myGamma = scaleFrom100(adjustable.gamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::getAdjustables(Adjustable& adjustable) const +{ + adjustable.phaseNtsc = myPhaseNTSC * 10.F; + adjustable.phasePal = myPhasePAL * 10.F; + + adjustable.hue = scaleTo100(myHue); + adjustable.saturation = scaleTo100(mySaturation); + adjustable.contrast = scaleTo100(myContrast); + adjustable.brightness = scaleTo100(myBrightness); + adjustable.gamma = scaleTo100(myGamma); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette(const string& name) +{ + myOSystem.settings().setValue("palette", name); + + setPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::setPalette() +{ + if(myOSystem.hasConsole()) + { + const string& name = myOSystem.settings().getString("palette"); + + // Look at all the palettes, since we don't know which one is + // currently active + static constexpr BSPF::array2D palettes = {{ + { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette }, + { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 }, + { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette }, + { &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette } + }}; + // See which format we should be using + const ConsoleTiming timing = myOSystem.console().timing(); + const PaletteType paletteType = toPaletteType(name); + // Now consider the current display format + const PaletteArray* palette = palettes[paletteType][int(timing)]; + + if(paletteType == PaletteType::Custom) + generateCustomPalette(timing); + + myOSystem.frameBuffer().setTIAPalette(adjustedPalette(*palette)); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette) +{ + PaletteArray destPalette; + // Constants for saturation and gray scale calculation + constexpr float PR = .2989F; + constexpr float PG = .5870F; + constexpr float PB = .1140F; + // Generate adjust table + constexpr int ADJUST_SIZE = 256; + constexpr int RGB_UNIT = 1 << 8; + constexpr float RGB_OFFSET = 0.5F; + const float hue = myHue; + const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET; + const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT; + const float saturation = mySaturation + 1; + const float gamma = 1.1333F - myGamma * 0.5F; + /* match common PC's 2.2 gamma to TV's 2.65 gamma */ + constexpr float toFloat = 1.F / (ADJUST_SIZE - 1); + std::array adjust; + + for(int i = 0; i < ADJUST_SIZE; i++) + adjust[i] = powf(i * toFloat, gamma) * contrast + brightness; + + // Transform original palette into destination palette + for(size_t i = 0; i < destPalette.size(); i += 2) + { + const uInt32 pixel = palette[i]; + int r = (pixel >> 16) & 0xff; + int g = (pixel >> 8) & 0xff; + int b = (pixel >> 0) & 0xff; + + // adjust hue (different for NTSC and PAL?) and saturation + adjustHueSaturation(r, g, b, hue, saturation); + + // adjust contrast, brightness, gamma + r = adjust[r]; + g = adjust[g]; + b = adjust[b]; + + r = BSPF::clamp(r, 0, 255); + g = BSPF::clamp(g, 0, 255); + b = BSPF::clamp(b, 0, 255); + + destPalette[i] = (r << 16) + (g << 8) + b; + + // Fill the odd numbered palette entries with gray values (calculated + // using the standard RGB -> grayscale conversion formula) + // Used for PAL color-loss data and 'greying out' the frame in the debugger. + const uInt8 lum = static_cast((r * PR) + (g * PG) + (b * PB)); + + destPalette[i + 1] = (lum << 16) + (lum << 8) + lum; + } + return destPalette; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::loadUserPalette() +{ + if (!myOSystem.checkUserPalette(true)) + return; + + ByteBuffer in; + try { myOSystem.paletteFile().read(in); } + catch(...) { return; } + + uInt8* pixbuf = in.get(); + for(int i = 0; i < 128; i++, pixbuf += 3) // NTSC palette + { + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + ourUserNTSCPalette[(i<<1)] = pixel; + } + for(int i = 0; i < 128; i++, pixbuf += 3) // PAL palette + { + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + ourUserPALPalette[(i<<1)] = pixel; + } + + std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels + for(int i = 0; i < 8; i++, pixbuf += 3) // SECAM palette + { + const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); + secam[(i<<1)] = pixel; + secam[(i<<1)+1] = 0; + } + uInt32* ptr = ourUserSECAMPalette.data(); + for(int i = 0; i < 16; ++i) + { + const uInt32* s = secam.data(); + for(int j = 0; j < 16; ++j) + *ptr++ = *s++; + } + + myUserPaletteDefined = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::generateCustomPalette(ConsoleTiming timing) +{ + constexpr int NUM_CHROMA = 16; + constexpr int NUM_LUMA = 8; + constexpr float SATURATION = 0.25F; // default saturation + + float color[NUM_CHROMA][2] = {{0.0F}}; + + if(timing == ConsoleTiming::ntsc) + { + // YIQ is YUV shifted by 33° + constexpr float offset = 33 * BSPF::PI_f / 180; + const float shift = myPhaseNTSC * BSPF::PI_f / 180; + + // color 0 is grayscale + for(int chroma = 1; chroma < NUM_CHROMA; chroma++) + { + color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1)); + color[chroma][1] = SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f); + } + + for(int chroma = 0; chroma < NUM_CHROMA; chroma++) + { + const float I = color[chroma][0]; + const float Q = color[chroma][1]; + + for(int luma = 0; luma < NUM_LUMA; luma++) + { + const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 + + float R = Y + 0.956F * I + 0.621F * Q; + float G = Y - 0.272F * I - 0.647F * Q; + float B = Y - 1.106F * I + 1.703F * Q; + + if(R < 0) R = 0; + if(G < 0) G = 0; + if(B < 0) B = 0; + + R = powf(R, 0.9F); + G = powf(G, 0.9F); + B = powf(B, 0.9F); + + int r = BSPF::clamp(R * 255.F, 0.F, 255.F); + int g = BSPF::clamp(G * 255.F, 0.F, 255.F); + int b = BSPF::clamp(B * 255.F, 0.F, 255.F); + + ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; + } + } + } + else if(timing == ConsoleTiming::pal) + { + constexpr float offset = BSPF::PI_f; + const float shift = myPhasePAL * BSPF::PI_f / 180; + constexpr float fixedShift = 22.5F * BSPF::PI_f / 180; + + // colors 0, 1, 14 and 15 are grayscale + for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++) + { + int idx = NUM_CHROMA - 1 - chroma; + color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma); + if ((idx & 1) == 0) + color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F); + else + color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F); + } + + for(int chroma = 0; chroma < NUM_CHROMA; chroma++) + { + const float U = color[chroma][0]; + const float V = color[chroma][1]; + + for(int luma = 0; luma < NUM_LUMA; luma++) + { + const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90 + + // Most sources + float R = Y + 1.403F * V; + float G = Y - 0.344F * U - 0.714F * V; + float B = Y + 1.770F * U; + // German Wikipedia, huh??? + //float B = Y + 1 / 0.493 * U; + //float R = Y + 1 / 0.877 * V; + //float G = 1.704 * Y - 0.590 * R - 0.194 * B; + + if(R < 0) R = 0.0; + if(G < 0) G = 0.0; + if(B < 0) B = 0.0; + + R = powf(R, 1.2F); + G = powf(G, 1.2F); + B = powf(B, 1.2F); + + int r = BSPF::clamp(R * 255.F, 0.F, 255.F); + int g = BSPF::clamp(G * 255.F, 0.F, 255.F); + int b = BSPF::clamp(B * 255.F, 0.F, 255.F); + + ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b; + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float S) +{ + // Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms + // (C) J. “Fluffy” Shagam + // License: CC BY-SA 4.0 + const float su = S * cosf(-H * BSPF::PI_f); + const float sw = S * sinf(-H * BSPF::PI_f); + const float r = (.299F + .701F * su + .168F * sw) * R + + (.587F - .587F * su + .330F * sw) * G + + (.114F - .114F * su - .497F * sw) * B; + const float g = (.299F - .299F * su - .328F * sw) * R + + (.587F + .413F * su + .035F * sw) * G + + (.114F - .114F * su + .292F * sw) * B; + const float b = (.299F - .300F * su + 1.25F * sw) * R + + (.587F - .588F * su - 1.05F * sw) * G + + (.114F + .886F * su - .203F * sw) * B; + + R = BSPF::clamp(r, 0.F, 255.F); + G = BSPF::clamp(g, 0.F, 255.F); + B = BSPF::clamp(b, 0.F, 255.F); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourNTSCPalette = { + 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0, + 0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0, + 0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0, + 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0, + 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0, + 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0, + 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0, + 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0, + 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0, + 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0, + 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0, + 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0, + 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0, + 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0, + 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0, + 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0, + 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0, + 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0, + 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0, + 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0, + 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0, + 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0, + 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0, + 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0, + 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0, + 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0, + 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0, + 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0, + 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0, + 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0, + 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0, + 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourPALPalette = { + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0 + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1 + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, + 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2 + 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389 + 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3 + 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0, + 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4 + 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac + 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5 + 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0, + 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6 + 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd + 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7 + 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff + 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8 + 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff + 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9 + 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0, + 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a + 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff + 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b + 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0, + 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c + 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff, + 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d + 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0, + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, + 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f + 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourSECAMPalette = { + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = { + 0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0, + 0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0, + 0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0, + 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0, + 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0, + 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0, + 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0, + 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0, + 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0, + 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0, + 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0, + 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0, + 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0, + 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0, + 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0, + 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0, + 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0, + 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0, + 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0, + 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0, + 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0, + 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0, + 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0, + 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0, + 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0, + 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0, + 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0, + 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0, + 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0, + 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0, + 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0, + 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourPALPaletteZ26 = { + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, + 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0, + 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0, + 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0, + 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0, + 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0, + 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0, + 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0, + 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0, + 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0, + 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0, + 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0, + 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0, + 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0, + 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0, + 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0, + 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0, + 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0, + 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0, + 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0, + 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0, + 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0, + 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0, + 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0, + 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0, + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, + 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, + 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = { + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, + 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, + 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserNTSCPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserPALPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourUserSECAMPalette = { 0 }; // filled from external file + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourCustomNTSCPalette = { 0 }; // filled by function + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PaletteArray PaletteHandler::ourCustomPALPalette = { 0 }; // filled by function diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx new file mode 100644 index 000000000..ed46da516 --- /dev/null +++ b/src/common/PaletteHandler.hxx @@ -0,0 +1,261 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef PALETTE_HANDLER_HXX +#define PALETTE_HANDLER_HXX + +#include "bspf.hxx" +#include "OSystem.hxx" +#include "ConsoleTiming.hxx" +#include "EventHandlerConstants.hxx" + +class PaletteHandler +{ + public: + // Setting names of palette types + static constexpr const char* SETTING_STANDARD = "standard"; + static constexpr const char* SETTING_Z26 = "z26"; + static constexpr const char* SETTING_USER = "user"; + static constexpr const char* SETTING_CUSTOM = "custom"; + + // Phase shift default and limits + static constexpr float DEF_NTSC_SHIFT = 26.2F; + static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5 + static constexpr float MAX_SHIFT = 4.5F; + + enum Adjustables { + PHASE_SHIFT, + HUE, + SATURATION, + CONTRAST, + BRIGHTNESS, + GAMMA + }; + + // Externally used adjustment parameters + struct Adjustable { + float phaseNtsc{0.F}, phasePal{0.F}; + uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0}; + }; + + public: + PaletteHandler(OSystem& system); + virtual ~PaletteHandler() = default; + + /** + Cycle through available palettes. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void cyclePalette(int direction = +1); + + /* + Cycle through each palette adjustable. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void cycleAdjustable(int direction = +1); + + /* + Increase or decrease given palette adjustable. + + @param adjustable The adjustable to change + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeAdjustable(int adjustable, int direction); + + /* + Increase or decrease current palette adjustable. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeCurrentAdjustable(int direction = +1); + + // Load adjustables from settings + void loadConfig(const Settings& settings); + + // Save adjustables to settings + void saveConfig(Settings& settings) const; + + // Set adjustables + void setAdjustables(const Adjustable& adjustable); + + // Retrieve current adjustables + void getAdjustables(Adjustable& adjustable) const; + + /** + Sets the palette according to the given palette name. + + @param name The palette to switch to + */ + void setPalette(const string& name); + + /** + Sets the palette from current settings. + */ + void setPalette(); + + private: + static constexpr char DEGREE = 0x1c; + + enum PaletteType { + Standard, + Z26, + User, + Custom, + NumTypes, + MinType = Standard, + MaxType = Custom + }; + + /** + Convert adjustables from/to 100% scale + */ + static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; } + static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); } + + /** + Convert palette settings name to enumeration. + + @param name The given palette's settings name + + @return The palette type + */ + PaletteType toPaletteType(const string& name) const; + + /** + Convert enumeration to palette settings name. + + @param type The given palette type + + @return The palette's settings name + */ + string toPaletteName(PaletteType type) const; + + /** + Display current adjustable with gauge bar message + */ + void showAdjustableMessage(); + + /** + Change the "phase shift" variable. + Note that there are two of these (NTSC and PAL). The currently + active mode will determine which one is used. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeColorPhaseShift(int direction = +1); + + /** + Generates a custom palette, based on user defined phase shifts. + + @param timing Use NTSC or PAL phase shift and generate according palette + */ + void generateCustomPalette(ConsoleTiming timing); + + /** + Create new palette by applying palette adjustments on given palette. + + @param source The palette which should be adjusted + + @return An adjusted palette + */ + PaletteArray adjustedPalette(const PaletteArray& source); + + /** + Adjust hue and saturation for given RGB values. + + @param R The red value to adjust + @param G The green value to adjust + @param B The blue value to adjust + @param H The hue adjustment value + @param S The saturation + */ + void adjustHueSaturation(int& R, int& G, int& B, float H, float S); + + /** + Loads a user-defined palette file (from OSystem::paletteFile), filling the + appropriate user-defined palette arrays. + */ + void loadUserPalette(); + + private: + static constexpr int NUM_ADJUSTABLES = 6; + + OSystem& myOSystem; + + // The currently selected adjustable + uInt32 myCurrentAdjustable{0}; + + struct AdjustableTag { + const char* const name{nullptr}; + float* value{nullptr}; + }; + const std::array myAdjustables = + { { + { "phase shift", nullptr }, + { "hue", &myHue }, + { "saturation", &mySaturation }, + { "contrast", &myContrast }, + { "brightness", &myBrightness }, + { "gamma", &myGamma }, + } }; + + // NTSC and PAL color phase shifts + float myPhaseNTSC{DEF_NTSC_SHIFT}; + float myPhasePAL{DEF_PAL_SHIFT}; + // range -1.0 to +1.0 (as in AtariNTSC) + // Basic parameters + float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees + float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) + float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5) + float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5) + // Advanced parameters + float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5) + + // Indicates whether an external palette was found and + // successfully loaded + bool myUserPaletteDefined{false}; + + // Table of RGB values for NTSC, PAL and SECAM + static const PaletteArray ourNTSCPalette; + static const PaletteArray ourPALPalette; + static const PaletteArray ourSECAMPalette; + + // Table of RGB values for NTSC, PAL and SECAM - Z26 version + static const PaletteArray ourNTSCPaletteZ26; + static const PaletteArray ourPALPaletteZ26; + static const PaletteArray ourSECAMPaletteZ26; + + // Table of RGB values for NTSC, PAL and SECAM - user-defined + static PaletteArray ourUserNTSCPalette; + static PaletteArray ourUserPALPalette; + static PaletteArray ourUserSECAMPalette; + + // Table of RGB values for NTSC, PAL - custom-defined and generated + static PaletteArray ourCustomNTSCPalette; + static PaletteArray ourCustomPALPalette; + + private: + PaletteHandler() = delete; + PaletteHandler(const PaletteHandler&) = delete; + PaletteHandler(PaletteHandler&&) = delete; + PaletteHandler& operator=(const PaletteHandler&) = delete; + PaletteHandler& operator=(const PaletteHandler&&) = delete; +}; + +#endif // PALETTE_HANDLER_HXX diff --git a/src/common/Rect.hxx b/src/common/Rect.hxx index 155151457..5243740f2 100644 --- a/src/common/Rect.hxx +++ b/src/common/Rect.hxx @@ -111,7 +111,8 @@ struct Rect Rect() {} explicit Rect(const Size& s) : bottom(s.h), right(s.w) { assert(valid()); } Rect(uInt32 w, uInt32 h) : bottom(h), right(w) { assert(valid()); } - Rect(const Point& p, uInt32 w, uInt32 h) : top(p.y), left(p.x), bottom(h), right(w) { assert(valid()); } + Rect(const Point& p, uInt32 w, uInt32 h) + : top(p.y), left(p.x), bottom(p.y + h), right(p.x + w) { assert(valid()); } Rect(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) : top(y1), left(x1), bottom(y2), right(x2) { assert(valid()); } uInt32 x() const { return left; } diff --git a/src/common/RewindManager.cxx b/src/common/RewindManager.cxx index d16bbd6c3..70fa481d7 100644 --- a/src/common/RewindManager.cxx +++ b/src/common/RewindManager.cxx @@ -18,6 +18,7 @@ #include #include "OSystem.hxx" +#include "Console.hxx" #include "Serializer.hxx" #include "StateManager.hxx" #include "TIA.hxx" @@ -180,7 +181,8 @@ uInt32 RewindManager::rewindStates(uInt32 numStates) else message = "Rewind not possible"; - if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE) + if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE + && myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK) myOSystem.frameBuffer().showMessage(message); return i; } @@ -214,7 +216,8 @@ uInt32 RewindManager::unwindStates(uInt32 numStates) else message = "Unwind not possible"; - if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE) + if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE + && myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK) myOSystem.frameBuffer().showMessage(message); return i; } diff --git a/src/common/SoundNull.hxx b/src/common/SoundNull.hxx index 87ba7736a..6bd9db54d 100644 --- a/src/common/SoundNull.hxx +++ b/src/common/SoundNull.hxx @@ -18,12 +18,13 @@ #ifndef SOUND_NULL_HXX #define SOUND_NULL_HXX +class OSystem; +class AudioQueue; +class EmulationTiming; + #include "bspf.hxx" #include "Logger.hxx" #include "Sound.hxx" -#include "OSystem.hxx" -#include "AudioQueue.hxx" -#include "EmulationTiming.hxx" /** This class implements a Null sound object, where-by sound generation @@ -96,10 +97,16 @@ class SoundNull : public Sound /** Adjusts the volume of the sound device based on the given direction. - @param direction Increase or decrease the current volume by a predefined - amount based on the direction (1 = increase, -1 =decrease) + @param direction +1 indicates increase, -1 indicates decrease. */ - void adjustVolume(Int8 direction) override { } + void adjustVolume(int direction = 1) override { } + + /** + Sets the audio device. + + @param device The number of the device to select (0 = default). + */ + void setDevice(uInt32 device) override { }; /** This method is called to provide information about the sound device. diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx index 671e5f83c..af99d3f2c 100644 --- a/src/common/SoundSDL2.cxx +++ b/src/common/SoundSDL2.cxx @@ -56,6 +56,8 @@ SoundSDL2::SoundSDL2(OSystem& osystem, AudioSettings& audioSettings) return; } + queryHardware(myDevices); + SDL_zero(myHardwareSpec); if(!openDevice()) return; @@ -76,6 +78,29 @@ SoundSDL2::~SoundSDL2() SDL_QuitSubSystem(SDL_INIT_AUDIO); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundSDL2::queryHardware(VariantList& devices) +{ + ASSERT_MAIN_THREAD; + + int numDevices = SDL_GetNumAudioDevices(0); + + // log the available audio devices + ostringstream s; + s << "Supported audio devices (" << numDevices << "):"; + Logger::debug(s.str()); + + VarList::push_back(devices, "Default", 0); + for(int i = 0; i < numDevices; ++i) { + ostringstream ss; + + ss << " " << i + 1 << ": " << SDL_GetAudioDeviceName(i, 0); + Logger::debug(ss.str()); + + VarList::push_back(devices, SDL_GetAudioDeviceName(i, 0), i + 1); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool SoundSDL2::openDevice() { @@ -91,7 +116,11 @@ bool SoundSDL2::openDevice() if(myIsInitializedFlag) SDL_CloseAudioDevice(myDevice); - myDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &myHardwareSpec, + + myDeviceId = BSPF::clamp(myAudioSettings.device(), 0u, uInt32(myDevices.size() - 1)); + const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr; + + myDevice = SDL_OpenAudioDevice(device, 0, &desired, &myHardwareSpec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); if(myDevice == 0) @@ -126,7 +155,8 @@ void SoundSDL2::open(shared_ptr audioQueue, // Do we need to re-open the sound device? // Only do this when absolutely necessary if(myAudioSettings.sampleRate() != uInt32(myHardwareSpec.freq) || - myAudioSettings.fragmentSize() != uInt32(myHardwareSpec.samples)) + myAudioSettings.fragmentSize() != uInt32(myHardwareSpec.samples) || + myAudioSettings.device() != myDeviceId) openDevice(); myEmulationTiming = emulationTiming; @@ -186,16 +216,31 @@ bool SoundSDL2::mute(bool state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool SoundSDL2::toggleMute() { - bool enabled = myAudioSettings.enabled(); + bool enabled = !myAudioSettings.enabled(); - setEnabled(!enabled); + setEnabled(enabled); myOSystem.console().initializeAudio(); string message = "Sound "; - message += !enabled ? "unmuted" : "muted"; + message += enabled ? "unmuted" : "muted"; myOSystem.frameBuffer().showMessage(message); + //ostringstream strval; + //uInt32 volume; + //// Now show an onscreen message + //if(enabled) + //{ + // volume = myVolume; + // strval << volume << "%"; + //} + //else + //{ + // volume = 0; + // strval << "Muted"; + //} + //myOSystem.frameBuffer().showMessage("Volume", strval.str(), volume); + return enabled; } @@ -214,20 +259,12 @@ void SoundSDL2::setVolume(uInt32 percent) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void SoundSDL2::adjustVolume(Int8 direction) +void SoundSDL2::adjustVolume(int direction) { ostringstream strval; - string message; - Int32 percent = myVolume; - if(direction == -1) - percent -= 2; - else if(direction == 1) - percent += 2; - - if((percent < 0) || (percent > 100)) - return; + percent = BSPF::clamp(percent + direction * 2, 0, 100); setVolume(percent); @@ -241,11 +278,11 @@ void SoundSDL2::adjustVolume(Int8 direction) } // Now show an onscreen message - strval << percent; - message = "Volume set to "; - message += strval.str(); - - myOSystem.frameBuffer().showMessage(message); + if(percent) + strval << percent << "%"; + else + strval << "Off"; + myOSystem.frameBuffer().showMessage("Volume", strval.str(), percent); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -254,6 +291,7 @@ string SoundSDL2::about() const ostringstream buf; buf << "Sound enabled:" << endl << " Volume: " << myVolume << "%" << endl + << " Device: " << myDevices.at(myDeviceId).first << endl << " Channels: " << uInt32(myHardwareSpec.channels) << (myAudioQueue->isStereo() ? " (Stereo)" : " (Mono)") << endl << " Preset: "; diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx index 85fb86031..586e90ff8 100644 --- a/src/common/SoundSDL2.hxx +++ b/src/common/SoundSDL2.hxx @@ -24,12 +24,12 @@ class OSystem; class AudioQueue; class EmulationTiming; class AudioSettings; +class Resampler; #include "SDL_lib.hxx" #include "bspf.hxx" #include "Sound.hxx" -#include "audio/Resampler.hxx" /** This class implements the sound API for SDL. @@ -98,10 +98,9 @@ class SoundSDL2 : public Sound /** Adjusts the volume of the sound device based on the given direction. - @param direction Increase or decrease the current volume by a predefined - amount based on the direction (1 = increase, -1 = decrease) - */ - void adjustVolume(Int8 direction) override; + @param direction +1 indicates increase, -1 indicates decrease. + */ + void adjustVolume(int direction = 1) override; /** This method is called to provide information about the sound device. @@ -109,6 +108,13 @@ class SoundSDL2 : public Sound string about() const override; protected: + /** + This method is called to query the audio devices. + + @param devices List of device names + */ + void queryHardware(VariantList& devices) override; + /** Invoked by the sound callback to process the next sound fragment. The stream is 16-bits (even though the callback is 8-bits), since @@ -140,6 +146,8 @@ class SoundSDL2 : public Sound // Audio specification structure SDL_AudioSpec myHardwareSpec; + uInt32 myDeviceId{0}; + SDL_AudioDeviceID myDevice{0}; shared_ptr myAudioQueue; diff --git a/src/common/Stack.hxx b/src/common/Stack.hxx index aac9c28b2..e3b2afd87 100644 --- a/src/common/Stack.hxx +++ b/src/common/Stack.hxx @@ -27,7 +27,7 @@ */ namespace Common { -template +template class FixedStack { private: diff --git a/src/common/StateManager.cxx b/src/common/StateManager.cxx index 667665054..a4add0889 100644 --- a/src/common/StateManager.cxx +++ b/src/common/StateManager.cxx @@ -299,15 +299,14 @@ void StateManager::saveState(int slot) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void StateManager::changeState(int direction) { - myCurrentSlot += direction; - if (myCurrentSlot < 0) - myCurrentSlot = 9; - else - myCurrentSlot %= 10; + myCurrentSlot = BSPF::clampw(myCurrentSlot + direction, 0, 9); // Print appropriate message ostringstream buf; - buf << "Changed to slot " << myCurrentSlot; + if(direction) + buf << "Changed to state slot " << myCurrentSlot; + else + buf << "State slot " << myCurrentSlot; myOSystem.frameBuffer().showMessage(buf.str()); } diff --git a/src/common/StateManager.hxx b/src/common/StateManager.hxx index 41bed3517..efb9286cb 100644 --- a/src/common/StateManager.hxx +++ b/src/common/StateManager.hxx @@ -18,7 +18,7 @@ #ifndef STATE_MANAGER_HXX #define STATE_MANAGER_HXX -#define STATE_HEADER "06000008state" +#define STATE_HEADER "06020100state" class OSystem; class RewindManager; @@ -115,8 +115,10 @@ class StateManager /** Switches to the next higher or lower state slot (circular queue style). + + @param direction +1 indicates increase, -1 indicates decrease. */ - void changeState(int direction); + void changeState(int direction = +1); /** Toggles auto slot mode. diff --git a/src/common/Vec.hxx b/src/common/Vec.hxx index 10e0c492e..7d102a785 100644 --- a/src/common/Vec.hxx +++ b/src/common/Vec.hxx @@ -22,19 +22,19 @@ namespace Vec { -template +template void append(vector& dst, const vector& src) { dst.insert(dst.cend(), src.cbegin(), src.cend()); } -template +template void insertAt(vector& dst, uInt32 idx, const T& element) { dst.insert(dst.cbegin()+idx, element); } -template +template void removeAt(vector& dst, uInt32 idx) { dst.erase(dst.cbegin()+idx); diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 2c534019a..22801ca3a 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -18,7 +18,7 @@ #ifndef VERSION_HXX #define VERSION_HXX -#define STELLA_VERSION "6.1_rc1" -#define STELLA_BUILD "5657" +#define STELLA_VERSION "6.3_pre" +#define STELLA_BUILD "6091" #endif diff --git a/src/common/ZipHandler.hxx b/src/common/ZipHandler.hxx index 861e1350a..aaf289357 100644 --- a/src/common/ZipHandler.hxx +++ b/src/common/ZipHandler.hxx @@ -297,7 +297,7 @@ class ZipHandler void addToCache(); private: - static constexpr uInt32 DECOMPRESS_BUFSIZE = 16_KB; + static constexpr size_t DECOMPRESS_BUFSIZE = 16_KB; static constexpr uInt32 CACHE_SIZE = 8; // number of open files to cache ZipFilePtr myZip; diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx index d47d076bd..a0d5a920e 100644 --- a/src/common/bspf.hxx +++ b/src/common/bspf.hxx @@ -43,6 +43,7 @@ using uInt64 = uint64_t; #include #include #include +#include #include #include #include @@ -63,8 +64,6 @@ using std::istream; using std::ostream; using std::fstream; using std::iostream; -using std::ifstream; -using std::ofstream; using std::ostringstream; using std::istringstream; using std::stringstream; @@ -84,11 +83,14 @@ using ByteArray = std::vector; using ShortArray = std::vector; using StringList = std::vector; using ByteBuffer = std::unique_ptr; // NOLINT +using DWordBuffer = std::unique_ptr; // NOLINT + +using AdjustFunction = std::function; // We use KB a lot; let's make a literal for it -constexpr uInt32 operator "" _KB(unsigned long long size) +constexpr size_t operator "" _KB(unsigned long long size) { - return static_cast(size * 1024); + return static_cast(size * 1024); } static const string EmptyString(""); @@ -97,6 +99,12 @@ static const string EmptyString(""); #undef PAGE_SIZE #undef PAGE_MASK +// Adaptable refresh is currently not available on MacOS +// In the future, this may expand to other systems +#if !defined(BSPF_MACOS) + #define ADAPTABLE_REFRESH_SUPPORT +#endif + namespace BSPF { static constexpr float PI_f = 3.141592653589793238462643383279502884F; @@ -118,20 +126,39 @@ namespace BSPF static const string ARCH = "NOARCH"; #endif + // Get next power of two greater than or equal to the given value + inline size_t nextPowerOfTwo(size_t size) { + if(size < 2) return 1; + size_t power2 = 1; + while(power2 < size) + power2 <<= 1; + return power2; + } + + // Get next multiple of the given value + // Note that this only works when multiple is a power of two + inline size_t nextMultipleOf(size_t size, size_t multiple) { + return (size + multiple - 1) & ~(multiple - 1); + } + // Make 2D-arrays using std::array less verbose - template + template using array2D = std::array, ROW>; // Combines 'max' and 'min', and clamps value to the upper/lower value // if it is outside the specified range - template inline T clamp(T val, T lower, T upper) + template inline T clamp(T val, T lower, T upper) { return (val < lower) ? lower : (val > upper) ? upper : val; } - template inline void clamp(T& val, T lower, T upper, T setVal) + template inline void clamp(T& val, T lower, T upper, T setVal) { if(val < lower || val > upper) val = setVal; } + template inline T clampw(T val, T lower, T upper) + { + return (val < lower) ? upper : (val > upper) ? lower : val; + } // Convert string to given case inline const string& toUpperCase(string& s) diff --git a/src/common/module.mk b/src/common/module.mk index 71511cbae..fbe4e7e7a 100644 --- a/src/common/module.mk +++ b/src/common/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ src/common/Logger.o \ src/common/main.o \ src/common/MouseControl.o \ + src/common/PaletteHandler.o \ src/common/PhosphorHandler.o \ src/common/PhysicalJoystick.o \ src/common/PJoystickHandler.o \ diff --git a/src/common/repository/KeyValueRepositoryConfigfile.cxx b/src/common/repository/KeyValueRepositoryConfigfile.cxx index fe0efdf64..44a840b81 100644 --- a/src/common/repository/KeyValueRepositoryConfigfile.cxx +++ b/src/common/repository/KeyValueRepositoryConfigfile.cxx @@ -28,8 +28,8 @@ namespace { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const string& filename) - : myFilename(filename) +KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const FilesystemNode& file) + : myFile(file) { } @@ -41,10 +41,14 @@ std::map KeyValueRepositoryConfigfile::load() string line, key, value; string::size_type equalPos, garbage; - ifstream in(myFilename); - if(!in || !in.is_open()) { - Logger::error("ERROR: Couldn't load from settings file " + myFilename); - + stringstream in; + try + { + myFile.read(in); + } + catch(...) + { + Logger::error("ERROR: Couldn't load from settings file " + myFile.getShortPath()); return values; } @@ -79,13 +83,7 @@ std::map KeyValueRepositoryConfigfile::load() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void KeyValueRepositoryConfigfile::save(const std::map& values) { - ofstream out(myFilename); - if(!out || !out.is_open()) { - Logger::error("ERROR: Couldn't save to settings file " + myFilename); - - return; - } - + stringstream out; out << "; Stella configuration file" << endl << ";" << endl << "; Lines starting with ';' are comments and are ignored." << endl @@ -104,4 +102,13 @@ void KeyValueRepositoryConfigfile::save(const std::map& values) // Write out each of the key and value pairs for(const auto& pair: values) out << pair.first << " = " << pair.second << endl; + + try + { + myFile.write(out); + } + catch(...) + { + Logger::error("ERROR: Couldn't save to settings file " + myFile.getShortPath()); + } } diff --git a/src/common/repository/KeyValueRepositoryConfigfile.hxx b/src/common/repository/KeyValueRepositoryConfigfile.hxx index 4e29166f5..e1aecda07 100644 --- a/src/common/repository/KeyValueRepositoryConfigfile.hxx +++ b/src/common/repository/KeyValueRepositoryConfigfile.hxx @@ -18,13 +18,14 @@ #ifndef KEY_VALUE_REPOSITORY_CONFIGFILE_HXX #define KEY_VALUE_REPOSITORY_CONFIGFILE_HXX +#include "FSNode.hxx" #include "KeyValueRepository.hxx" class KeyValueRepositoryConfigfile : public KeyValueRepository { public: - explicit KeyValueRepositoryConfigfile(const string& filename); + explicit KeyValueRepositoryConfigfile(const FilesystemNode& file); std::map load() override; @@ -34,7 +35,7 @@ class KeyValueRepositoryConfigfile : public KeyValueRepository private: - const string& myFilename; + FilesystemNode myFile; }; #endif // KEY_VALUE_REPOSITORY_CONFIGFILE_HXX diff --git a/src/common/sdl_blitter/BilinearBlitter.cxx b/src/common/sdl_blitter/BilinearBlitter.cxx index bae05207c..295d8e8e2 100644 --- a/src/common/sdl_blitter/BilinearBlitter.cxx +++ b/src/common/sdl_blitter/BilinearBlitter.cxx @@ -15,9 +15,9 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "BilinearBlitter.hxx" - +#include "FrameBufferSDL2.hxx" #include "ThreadDebugging.hxx" +#include "BilinearBlitter.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate) diff --git a/src/common/sdl_blitter/BilinearBlitter.hxx b/src/common/sdl_blitter/BilinearBlitter.hxx index e18cba6bf..84c550ad1 100644 --- a/src/common/sdl_blitter/BilinearBlitter.hxx +++ b/src/common/sdl_blitter/BilinearBlitter.hxx @@ -18,8 +18,9 @@ #ifndef BILINEAR_BLITTER_HXX #define BILINEAR_BLITTER_HXX +class FrameBufferSDL2; + #include "Blitter.hxx" -#include "FrameBufferSDL2.hxx" #include "SDL_lib.hxx" class BilinearBlitter : public Blitter { diff --git a/src/common/sdl_blitter/QisBlitter.cxx b/src/common/sdl_blitter/QisBlitter.cxx index 95d958565..c68c4bff9 100644 --- a/src/common/sdl_blitter/QisBlitter.cxx +++ b/src/common/sdl_blitter/QisBlitter.cxx @@ -15,9 +15,9 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "QisBlitter.hxx" - +#include "FrameBufferSDL2.hxx" #include "ThreadDebugging.hxx" +#include "QisBlitter.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - QisBlitter::QisBlitter(FrameBufferSDL2& fb) diff --git a/src/common/sdl_blitter/QisBlitter.hxx b/src/common/sdl_blitter/QisBlitter.hxx index 77ab2b51d..14ee84fcc 100644 --- a/src/common/sdl_blitter/QisBlitter.hxx +++ b/src/common/sdl_blitter/QisBlitter.hxx @@ -18,8 +18,9 @@ #ifndef QIS_BLITTER_HXX #define QIS_BLITTER_HXX +class FrameBufferSDL2; + #include "Blitter.hxx" -#include "FrameBufferSDL2.hxx" #include "SDL_lib.hxx" class QisBlitter : public Blitter { diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx index a0b9ef169..ad57a12f8 100644 --- a/src/common/tv_filters/AtariNTSC.cxx +++ b/src/common/tv_filters/AtariNTSC.cxx @@ -57,9 +57,15 @@ void AtariNTSC::generateKernels() const uInt8* ptr = myRGBPalette.data(); for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry) { + #ifdef BLARGG_PALETTE float r = myImpl.to_float[*ptr++], g = myImpl.to_float[*ptr++], b = myImpl.to_float[*ptr++]; + #else + float r = (*ptr++) / 255.F * rgb_unit + rgb_offset, + g = (*ptr++) / 255.F * rgb_unit + rgb_offset, + b = (*ptr++) / 255.F * rgb_unit + rgb_offset; + #endif float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q ); // Generate kernel @@ -319,8 +325,10 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void AtariNTSC::init(init_t& impl, const Setup& setup) { +#ifdef BLARGG_PALETTE impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset; impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit; +#endif impl.artifacts = setup.artifacts; if ( impl.artifacts > 0 ) @@ -334,6 +342,7 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) initFilters(impl, setup); +#ifdef BLARGG_PALETTE /* generate gamma table */ if (true) /* was (gamma_size > 1) */ { @@ -341,19 +350,22 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) float const gamma = 1.1333F - setup.gamma * 0.5F; /* match common PC's 2.2 gamma to TV's 2.65 gamma */ int i; - for ( i = 0; i < gamma_size; i++ ) - impl.to_float [i] = - powf( i * to_float, gamma ) * impl.contrast + impl.brightness; + for(i = 0; i < gamma_size; i++) + impl.to_float[i] = + powf(i * to_float, gamma) * impl.contrast + impl.brightness; } +#endif /* setup decoder matricies */ { + #ifdef BLARGG_PALETTE float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue; float sat = setup.saturation + 1; hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue); - float s = sinf( hue ) * sat; - float c = cosf( hue ) * sat; + float s = sinf(hue)*sat; + float c = cosf(hue)*sat; + #endif float* out = impl.to_rgb.data(); int n; @@ -366,8 +378,13 @@ void AtariNTSC::init(init_t& impl, const Setup& setup) { float i = *in++; float q = *in++; + #ifdef BLARGG_PALETTE *out++ = i * c - q * s; *out++ = i * s + q * c; + #else + *out++ = i ; + *out++ = q; + #endif } while ( --n2 ); #if 0 // burst_count is always 0 @@ -544,16 +561,32 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const AtariNTSC::Setup AtariNTSC::TV_Composite = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F +#else + 0.0F, 0.15F, 0.0F, 0.0F, 0.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_SVideo = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F +#else + 0.0F, 0.45F, -1.0F, -1.0F, 0.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_RGB = { +#ifdef BLARGG_PALETTE 0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F +#else + 0.2F, 0.70F, -1.0F, -1.0F, -1.0F +#endif }; const AtariNTSC::Setup AtariNTSC::TV_Bad = { +#ifdef BLARGG_PALETTE 0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F +#else + 0.2F, 0.1F, 0.5F, 0.5F, 0.5F +#endif }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx index 4ae7b666f..eb75bce3d 100644 --- a/src/common/tv_filters/AtariNTSC.hxx +++ b/src/common/tv_filters/AtariNTSC.hxx @@ -46,6 +46,8 @@ #include "FrameBufferConstants.hxx" #include "bspf.hxx" +//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined + class AtariNTSC { public: @@ -57,14 +59,18 @@ class AtariNTSC struct Setup { // Basic parameters + #ifdef BLARGG_PALETTE float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0) float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5) float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5) + #endif float sharpness{0.F}; // edge contrast enhancement/blurring // Advanced parameters + #ifdef BLARGG_PALETTE float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5) + #endif float resolution{0.F}; // image resolution float artifacts{0.F}; // artifacts caused by color changes float fringing{0.F}; // color artifacts caused by brightness changes @@ -127,7 +133,9 @@ class AtariNTSC burst_size = entry_size / burst_count, kernel_half = 16, kernel_size = kernel_half * 2 + 1, + #ifdef BLARGG_PALETTE gamma_size = 256, + #endif rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)), rgb_kernel_size = burst_size / alignment_count, @@ -162,16 +170,20 @@ class AtariNTSC struct init_t { std::array to_rgb{0.F}; + #ifdef BLARGG_PALETTE std::array to_float{0.F}; float contrast{0.F}; float brightness{0.F}; + #endif float artifacts{0.F}; float fringing{0.F}; std::array kernel{0.F}; init_t() { to_rgb.fill(0.0); + #ifdef BLARGG_PALETTE to_float.fill(0.0); + #endif kernel.fill(0.0); } }; diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx index 6ec1afc8c..5a61dd140 100644 --- a/src/common/tv_filters/NTSCFilter.cxx +++ b/src/common/tv_filters/NTSCFilter.cxx @@ -20,8 +20,8 @@ #include "NTSCFilter.hxx" -constexpr float scaleFrom100(float x) { return (x/50.F) - 1.F; } -constexpr uInt32 scaleTo100(float x) { return uInt32(50*(x+1.F)); } +constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; } +constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string NTSCFilter::setPreset(Preset preset) @@ -62,9 +62,9 @@ string NTSCFilter::getPreset() const { switch(myPreset) { - case Preset::COMPOSITE: return "COMPOSITE"; - case Preset::SVIDEO: return "S-VIDEO"; case Preset::RGB: return "RGB"; + case Preset::SVIDEO: return "S-VIDEO"; + case Preset::COMPOSITE: return "COMPOSITE"; case Preset::BAD: return "BAD ADJUST"; case Preset::CUSTOM: return "CUSTOM"; default: return "Disabled"; @@ -72,81 +72,81 @@ string NTSCFilter::getPreset() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string NTSCFilter::setNextAdjustable() +void NTSCFilter::selectAdjustable(int direction, + string& text, string& valueText, Int32& value) { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + if(direction == +1) + { + #ifdef BLARGG_PALETTE + myCurrentAdjustable = (myCurrentAdjustable + 1) % 10; + #else + myCurrentAdjustable = (myCurrentAdjustable + 1) % 5; + #endif + } + else if(direction == -1) + { + #ifdef BLARGG_PALETTE + if(myCurrentAdjustable == 0) myCurrentAdjustable = 9; + #else + if(myCurrentAdjustable == 0) myCurrentAdjustable = 4; + #endif + else --myCurrentAdjustable; + } - myCurrentAdjustable = (myCurrentAdjustable + 1) % 10; - ostringstream buf; - buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; + ostringstream msg, val; - return buf.str(); + value = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); + msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type; + val << value << "%"; + + text = msg.str(); + valueText = val.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string NTSCFilter::setPreviousAdjustable() +void NTSCFilter::changeAdjustable(int adjustable, int direction, + string& text, string& valueText, Int32& newValue) { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; - - if(myCurrentAdjustable == 0) myCurrentAdjustable = 9; - else --myCurrentAdjustable; - ostringstream buf; - buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' selected"; - - return buf.str(); + myCurrentAdjustable = adjustable; + changeCurrentAdjustable(direction, text, valueText, newValue); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string NTSCFilter::increaseAdjustable() +void NTSCFilter::changeCurrentAdjustable(int direction, + string& text, string& valueText, Int32& newValue) { - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + //if(myPreset != Preset::CUSTOM) + // return "'Custom' TV mode not selected"; - uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); - newval += 2; if(newval > 100) newval = 100; - *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval); + newValue = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); + newValue = BSPF::clamp(newValue + direction * 1, 0, 100); - ostringstream buf; - buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; + *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newValue); setPreset(myPreset); - return buf.str(); -} -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string NTSCFilter::decreaseAdjustable() -{ - if(myPreset != Preset::CUSTOM) - return "'Custom' TV mode not selected"; + ostringstream msg, val; - uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value); - if(newval < 2) newval = 0; - else newval -= 2; - *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval); + msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type; + val << newValue << "%"; - ostringstream buf; - buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type - << "' set to " << newval; - - setPreset(myPreset); - return buf.str(); + text = msg.str(); + valueText = val.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void NTSCFilter::loadConfig(const Settings& settings) { + // Load adjustables for custom mode +#ifdef BLARGG_PALETTE myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F); myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F); myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F); myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F); - myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F); myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F); +#endif + myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F); myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F); myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F); myCustomSetup.fringing = BSPF::clamp(settings.getFloat("tv.fringing"), -1.0F, 1.0F); @@ -157,12 +157,14 @@ void NTSCFilter::loadConfig(const Settings& settings) void NTSCFilter::saveConfig(Settings& settings) const { // Save adjustables for custom mode +#ifdef BLARGG_PALETTE settings.setValue("tv.hue", myCustomSetup.hue); settings.setValue("tv.saturation", myCustomSetup.saturation); settings.setValue("tv.contrast", myCustomSetup.contrast); settings.setValue("tv.brightness", myCustomSetup.brightness); - settings.setValue("tv.sharpness", myCustomSetup.sharpness); settings.setValue("tv.gamma", myCustomSetup.gamma); +#endif + settings.setValue("tv.sharpness", myCustomSetup.sharpness); settings.setValue("tv.resolution", myCustomSetup.resolution); settings.setValue("tv.artifacts", myCustomSetup.artifacts); settings.setValue("tv.fringing", myCustomSetup.fringing); @@ -174,12 +176,12 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const { switch(preset) { - case Preset::COMPOSITE: - convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break; - case Preset::SVIDEO: - convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break; case Preset::RGB: convertToAdjustable(adjustable, AtariNTSC::TV_RGB); break; + case Preset::SVIDEO: + convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break; + case Preset::COMPOSITE: + convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break; case Preset::BAD: convertToAdjustable(adjustable, AtariNTSC::TV_Bad); break; case Preset::CUSTOM: @@ -192,12 +194,14 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) { - myCustomSetup.hue = scaleFrom100(adjustable.hue); - myCustomSetup.saturation = scaleFrom100(adjustable.saturation); - myCustomSetup.contrast = scaleFrom100(adjustable.contrast); - myCustomSetup.brightness = scaleFrom100(adjustable.brightness); +#ifdef BLARGG_PALETTE + //myCustomSetup.hue = scaleFrom100(adjustable.hue); + //myCustomSetup.saturation = scaleFrom100(adjustable.saturation); + //myCustomSetup.contrast = scaleFrom100(adjustable.contrast); + //myCustomSetup.brightness = scaleFrom100(adjustable.brightness); + //myCustomSetup.gamma = scaleFrom100(adjustable.gamma); +#endif myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness); - myCustomSetup.gamma = scaleFrom100(adjustable.gamma); myCustomSetup.resolution = scaleFrom100(adjustable.resolution); myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts); myCustomSetup.fringing = scaleFrom100(adjustable.fringing); @@ -208,12 +212,14 @@ void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) void NTSCFilter::convertToAdjustable(Adjustable& adjustable, const AtariNTSC::Setup& setup) const { - adjustable.hue = scaleTo100(setup.hue); - adjustable.saturation = scaleTo100(setup.saturation); - adjustable.contrast = scaleTo100(setup.contrast); - adjustable.brightness = scaleTo100(setup.brightness); +#ifdef BLARGG_PALETTE + //adjustable.hue = scaleTo100(setup.hue); + //adjustable.saturation = scaleTo100(setup.saturation); + //adjustable.contrast = scaleTo100(setup.contrast); + //adjustable.brightness = scaleTo100(setup.brightness); + //adjustable.gamma = scaleTo100(setup.gamma); +#endif adjustable.sharpness = scaleTo100(setup.sharpness); - adjustable.gamma = scaleTo100(setup.gamma); adjustable.resolution = scaleTo100(setup.resolution); adjustable.artifacts = scaleTo100(setup.artifacts); adjustable.fringing = scaleTo100(setup.fringing); @@ -224,12 +230,16 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable, AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#ifdef BLARGG_PALETTE const std::array NTSCFilter::ourCustomAdjustables = { { { "contrast", &myCustomSetup.contrast }, { "brightness", &myCustomSetup.brightness }, { "hue", &myCustomSetup.hue }, { "saturation", &myCustomSetup.saturation }, { "gamma", &myCustomSetup.gamma }, +#else +const std::array NTSCFilter::ourCustomAdjustables = { { +#endif { "sharpness", &myCustomSetup.sharpness }, { "resolution", &myCustomSetup.resolution }, { "artifacts", &myCustomSetup.artifacts }, diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx index b4a5e0e3d..b4b3aa713 100644 --- a/src/common/tv_filters/NTSCFilter.hxx +++ b/src/common/tv_filters/NTSCFilter.hxx @@ -47,12 +47,24 @@ class NTSCFilter BAD, CUSTOM }; + enum class Adjustables { + SHARPNESS, + RESOLUTION, + ARTIFACTS, + FRINGING, + BLEEDING, + NUM_ADJUSTABLES + }; /* Normally used in conjunction with custom mode, contains all aspects currently adjustable in NTSC TV emulation. */ struct Adjustable { + #ifdef BLARGG_PALETTE uInt32 hue, saturation, contrast, brightness, gamma, sharpness, resolution, artifacts, fringing, bleed; + #else + uInt32 sharpness, resolution, artifacts, fringing, bleed; + #endif }; public: @@ -86,10 +98,12 @@ class NTSCFilter // Changes are made this way since otherwise 20 key-combinations // would be needed to dynamically change each setting, and now // only 4 combinations are necessary - string setNextAdjustable(); - string setPreviousAdjustable(); - string increaseAdjustable(); - string decreaseAdjustable(); + void selectAdjustable(int direction, + string& text, string& valueText, Int32& value); + void changeAdjustable(int adjustable, int direction, + string& text, string& valueText, Int32& newValue); + void changeCurrentAdjustable(int direction, + string& text, string& valueText, Int32& newValue); // Load and save NTSC-related settings void loadConfig(const Settings& settings); @@ -139,7 +153,11 @@ class NTSCFilter float* value{nullptr}; }; uInt32 myCurrentAdjustable{0}; + #ifdef BLARGG_PALETTE static const std::array ourCustomAdjustables; + #else + static const std::array ourCustomAdjustables; + #endif private: // Following constructors and assignment operators not supported diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 5b54563f5..d62b16b66 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -32,7 +32,10 @@ #include "CartRamWidget.hxx" #include "RomWidget.hxx" #include "Base.hxx" +#include "Device.hxx" #include "exception/EmulationWarning.hxx" +#include "TIA.hxx" +#include "M6532.hxx" using Common::Base; using std::hex; @@ -68,15 +71,18 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) } // Create bank information for each potential bank, and an extra one for ZP RAM - // Banksizes greater than 4096 indicate multi-bank ROMs, but we handle only + // ROM sizes greater than 4096 indicate multi-bank ROMs, but we handle only // 4K pieces at a time - // Banksizes less than 4K use the actual value - size_t banksize = 0; - myConsole.cartridge().getImage(banksize); + // ROM sizes less than 4K use the actual value + size_t romSize = 0; + myConsole.cartridge().getImage(romSize); BankInfo info; - info.size = std::min(banksize, 4_KB); - for(uInt32 i = 0; i < myConsole.cartridge().bankCount(); ++i) + info.size = std::min(romSize, 4_KB); + for(uInt32 i = 0; i < myConsole.cartridge().romBankCount(); ++i) + myBankInfo.push_back(info); + + for(uInt32 i = 0; i < myConsole.cartridge().ramBankCount(); ++i) myBankInfo.push_back(info); info.size = 128; // ZP RAM @@ -85,7 +91,7 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) // We know the address for the startup bank right now myBankInfo[myConsole.cartridge().startBank()].addressList.push_front( myDebugger.dpeek(0xfffc)); - addLabel("Start", myDebugger.dpeek(0xfffc, DATA)); + addLabel("Start", myDebugger.dpeek(0xfffc, Device::DATA)); // TOOD: ::CODE??? // Add system equates for(uInt16 addr = 0x00; addr <= 0x0F; ++addr) @@ -156,6 +162,18 @@ void CartDebug::saveOldState() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartDebug::lastReadAddress() +{ + return mySystem.m6502().lastReadAddress(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartDebug::lastWriteAddress() +{ + return mySystem.m6502().lastWriteAddress(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int CartDebug::lastReadBaseAddress() { @@ -224,12 +242,36 @@ string CartDebug::toString() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartDebug::disassemble(bool force) +bool CartDebug::disassembleAddr(uInt16 address, bool force) +{ + // ROM/RAM bank or ZP-RAM? + int bank = (address & 0x1000) ? getBank(address) : int(myBankInfo.size()) - 1; + + return disassemble(bank, address, force); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDebug::disassemblePC(bool force) +{ + return (disassembleAddr(myDebugger.cpuDebug().pc())); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDebug::disassembleBank(int bank) +{ + BankInfo& info = myBankInfo[bank]; + + info.offset = myConsole.cartridge().bankOrigin(bank); + + return disassemble(bank, info.offset, true); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDebug::disassemble(int bank, uInt16 PC, bool force) { // Test current disassembly; don't re-disassemble if it hasn't changed // Also check if the current PC is in the current list bool bankChanged = myConsole.cartridge().bankChanged(); - uInt16 PC = myDebugger.cpuDebug().pc(); int pcline = addressToLine(PC); bool pcfound = (pcline != -1) && (uInt32(pcline) < myDisassembly.list.size()) && (myDisassembly.list[pcline].disasm[0] != '.'); @@ -241,8 +283,9 @@ bool CartDebug::disassemble(bool force) if(changed) { // Are we disassembling from ROM or ZP RAM? - BankInfo& info = (PC & 0x1000) ? myBankInfo[getBank(PC)] : - myBankInfo[myBankInfo.size()-1]; + BankInfo& info = myBankInfo[bank]; + //(PC & 0x1000) ? myBankInfo[getBank(PC)] : + //myBankInfo[myBankInfo.size()-1]; // If the offset has changed, all old addresses must be 'converted' // For example, if the list contains any $fxxx and the address space is now @@ -304,8 +347,8 @@ bool CartDebug::fillDisassemblyList(BankInfo& info, uInt16 search) const DisassemblyTag& tag = myDisassembly.list[i]; const uInt16 address = tag.address & 0xFFF; - // Exclude 'ROW'; they don't have a valid address - if(tag.type != CartDebug::ROW) + // Exclude 'Device::ROW'; they don't have a valid address + if(tag.type != Device::ROW) { // Create a mapping from addresses to line numbers myAddrToLineList.emplace(address, i); @@ -331,7 +374,7 @@ int CartDebug::addressToLine(uInt16 address) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartDebug::disassemble(uInt16 start, uInt16 lines) const +string CartDebug::disassembleLines(uInt16 start, uInt16 lines) const { // Fill the string with disassembled data start &= 0xFFF; @@ -346,7 +389,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const if((tag.address & 0xfff) >= start) { if(begin == list_size) begin = end; - if(tag.type != CartDebug::ROW) + if(tag.type != Device::ROW) length = std::max(length, uInt32(tag.disasm.length())); --lines; @@ -357,7 +400,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const for(uInt32 i = begin; i < end; ++i) { const CartDebug::DisassemblyTag& tag = myDisassembly.list[i]; - if(tag.type == CartDebug::NONE) + if(tag.type == Device::NONE) continue; else if(tag.address) buffer << std::uppercase << std::hex << std::setw(4) @@ -374,7 +417,7 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartDebug::addDirective(CartDebug::DisasmType type, +bool CartDebug::addDirective(Device::AccessType type, uInt16 start, uInt16 end, int bank) { if(end < start || start == 0 || end == 0) @@ -384,7 +427,7 @@ bool CartDebug::addDirective(CartDebug::DisasmType type, bank = (myDebugger.cpuDebug().pc() & 0x1000) ? getBank(myDebugger.cpuDebug().pc()) : int(myBankInfo.size())-1; - bank = std::min(bank, bankCount()); + bank = std::min(bank, romBankCount()); BankInfo& info = myBankInfo[bank]; DirectiveList& list = info.directiveList; @@ -516,9 +559,9 @@ int CartDebug::getPCBank() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int CartDebug::bankCount() const +int CartDebug::romBankCount() const { - return myConsole.cartridge().bankCount(); + return myConsole.cartridge().romBankCount(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -696,19 +739,20 @@ string CartDebug::loadListFile() // The default naming/location for list files is the ROM dir based on the // actual ROM filename - if(myListFile == "") - { - FilesystemNode lst(myOSystem.romFile().getPathWithExt("") + ".lst"); - if(lst.isFile() && lst.isReadable()) - myListFile = lst.getPath(); - else - return DebuggerParser::red("list file \'" + lst.getShortPath() + "\' not found"); - } + FilesystemNode lst(myOSystem.romFile().getPathWithExt(".lst")); + if(!lst.isReadable()) + return DebuggerParser::red("list file \'" + lst.getShortPath() + "\' not found"); - FilesystemNode node(myListFile); - ifstream in(node.getPath()); - if(!in.is_open()) - return DebuggerParser::red("list file '" + node.getShortPath() + "' not readable"); + stringstream in; + try + { + if(lst.read(in) == 0) + return DebuggerParser::red("list file '" + lst.getShortPath() + "' not found"); + } + catch(...) + { + return DebuggerParser::red("list file '" + lst.getShortPath() + "' not readable"); + } while(!in.eof()) { @@ -747,7 +791,7 @@ string CartDebug::loadListFile() } myDebugger.rom().invalidate(); - return "list file '" + node.getShortPath() + "' loaded OK"; + return "list file '" + lst.getShortPath() + "' loaded OK"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -756,23 +800,24 @@ string CartDebug::loadSymbolFile() // The default naming/location for symbol files is the ROM dir based on the // actual ROM filename - if(mySymbolFile == "") - { - FilesystemNode sym(myOSystem.romFile().getPathWithExt("") + ".sym"); - if(sym.isFile() && sym.isReadable()) - mySymbolFile = sym.getPath(); - else - return DebuggerParser::red("symbol file \'" + sym.getShortPath() + "\' not found"); - } - - FilesystemNode node(mySymbolFile); - ifstream in(node.getPath()); - if(!in.is_open()) - return DebuggerParser::red("symbol file '" + node.getShortPath() + "' not readable"); + FilesystemNode sym(myOSystem.romFile().getPathWithExt(".sym")); + if(!sym.isReadable()) + return DebuggerParser::red("symbol file \'" + sym.getShortPath() + "\' not found"); myUserAddresses.clear(); myUserLabels.clear(); + stringstream in; + try + { + if(sym.read(in) == 0) + return DebuggerParser::red("symbol file '" + sym.getShortPath() + "' not found"); + } + catch(...) + { + return DebuggerParser::red("symbol file '" + sym.getShortPath() + "' not readable"); + } + while(!in.eof()) { string label; @@ -807,28 +852,29 @@ string CartDebug::loadSymbolFile() } myDebugger.rom().invalidate(); - return "symbol file '" + node.getShortPath() + "' loaded OK"; + return "symbol file '" + sym.getShortPath() + "' loaded OK"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::loadConfigFile() { - // The default naming/location for config files is the ROM dir based on the - // actual ROM filename + // The default naming/location for config files is the CFG dir and based + // on the actual ROM filename - if(myCfgFile == "") + FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg")); + FilesystemNode cfg = myOSystem.cfgDir(); cfg /= romNode.getName(); + if(!cfg.isReadable()) + return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not found"); + + stringstream in; + try { - FilesystemNode cfg(myOSystem.romFile().getPathWithExt("") + ".cfg"); - if(cfg.isFile() && cfg.isReadable()) - myCfgFile = cfg.getPath(); - else - return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not found"); + cfg.read(in); + } + catch(...) + { + return "Unable to load directives from " + cfg.getPath(); } - - FilesystemNode node(myCfgFile); - ifstream in(node.getPath()); - if(!in.is_open()) - return "Unable to load directives from " + node.getPath(); // Erase all previous directives for(auto& bi: myBankInfo) @@ -876,37 +922,57 @@ string CartDebug::loadConfigFile() else if(BSPF::startsWithIgnoreCase(directive, "CODE")) { buf >> hex >> start >> hex >> end; - addDirective(CartDebug::CODE, start, end, currentbank); + addDirective(Device::CODE, start, end, currentbank); } else if(BSPF::startsWithIgnoreCase(directive, "GFX")) { buf >> hex >> start >> hex >> end; - addDirective(CartDebug::GFX, start, end, currentbank); + addDirective(Device::GFX, start, end, currentbank); } else if(BSPF::startsWithIgnoreCase(directive, "PGFX")) { buf >> hex >> start >> hex >> end; - addDirective(CartDebug::PGFX, start, end, currentbank); + addDirective(Device::PGFX, start, end, currentbank); + } + else if(BSPF::startsWithIgnoreCase(directive, "COL")) + { + buf >> hex >> start >> hex >> end; + addDirective(Device::COL, start, end, currentbank); + } + else if(BSPF::startsWithIgnoreCase(directive, "PCOL")) + { + buf >> hex >> start >> hex >> end; + addDirective(Device::PCOL, start, end, currentbank); + } + else if(BSPF::startsWithIgnoreCase(directive, "BCOL")) + { + buf >> hex >> start >> hex >> end; + addDirective(Device::BCOL, start, end, currentbank); + } + else if(BSPF::startsWithIgnoreCase(directive, "AUD")) + { + buf >> hex >> start >> hex >> end; + addDirective(Device::AUD, start, end, currentbank); } else if(BSPF::startsWithIgnoreCase(directive, "DATA")) { buf >> hex >> start >> hex >> end; - addDirective(CartDebug::DATA, start, end, currentbank); + addDirective(Device::DATA, start, end, currentbank); } else if(BSPF::startsWithIgnoreCase(directive, "ROW")) { buf >> hex >> start; buf >> hex >> end; - addDirective(CartDebug::ROW, start, end, currentbank); + addDirective(Device::ROW, start, end, currentbank); } } } myDebugger.rom().invalidate(); stringstream retVal; - if(myConsole.cartridge().bankCount() > 1) + if(myConsole.cartridge().romBankCount() > 1) retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n"); - retVal << "config file '" << node.getShortPath() << "' loaded OK"; + retVal << "config file '" << cfg.getShortPath() << "' loaded OK"; return retVal.str(); } @@ -914,69 +980,72 @@ string CartDebug::loadConfigFile() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::saveConfigFile() { - // The default naming/location for config files is the ROM dir based on the - // actual ROM filename - - FilesystemNode cfg; - if(myCfgFile == "") - { - cfg = FilesystemNode(myOSystem.romFile().getPathWithExt("") + ".cfg"); - if(cfg.isFile() && cfg.isWritable()) - myCfgFile = cfg.getPath(); - else - return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not writable"); - } + // The default naming/location for config files is the CFG dir and based + // on the actual ROM filename const string& name = myConsole.properties().get(PropType::Cart_Name); const string& md5 = myConsole.properties().get(PropType::Cart_MD5); - ofstream out(cfg.getPath()); - if(!out.is_open()) - return "Unable to save directives to " + cfg.getShortPath(); - // Store all bank information - out << "//Stella.pro: \"" << name << "\"" << endl - << "//MD5: " << md5 << endl + stringstream out; + out << "// Stella.pro: \"" << name << "\"" << endl + << "// MD5: " << md5 << endl << endl; - for(uInt32 b = 0; b < myConsole.cartridge().bankCount(); ++b) + for(uInt32 b = 0; b < myConsole.cartridge().romBankCount(); ++b) { out << "[" << b << "]" << endl; getBankDirectives(out, myBankInfo[b]); } stringstream retVal; - if(myConsole.cartridge().bankCount() > 1) - retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n"); - retVal << "config file '" << cfg.getShortPath() << "' saved OK"; + try + { + FilesystemNode romNode(myOSystem.romFile().getPathWithExt(".cfg")); + FilesystemNode cfg = myOSystem.cfgDir(); cfg /= romNode.getName(); + if(!cfg.getParent().isWritable()) + return DebuggerParser::red("config file \'" + cfg.getShortPath() + "\' not writable"); + + if(cfg.write(out) == 0) + return "Unable to save directives to " + cfg.getShortPath(); + + if(myConsole.cartridge().romBankCount() > 1) + retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n"); + retVal << "config file '" << cfg.getShortPath() << "' saved OK"; + } + catch(const runtime_error& e) + { + retVal << "Unable to save directives: " << e.what(); + } return retVal.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::saveDisassembly() { - if(myDisasmFile == "") - { - const string& propsname = - myConsole.properties().get(PropType::Cart_Name) + ".asm"; - - myDisasmFile = FilesystemNode(myOSystem.defaultSaveDir() + propsname).getPath(); - } - - FilesystemNode node(myDisasmFile); - ofstream out(node.getPath()); - if(!out.is_open()) - return "Unable to save disassembly to " + node.getShortPath(); + string NTSC_COLOR[16] = { + "BLACK", "YELLOW", "BROWN", "ORANGE", + "RED", "MAUVE", "VIOLET", "PURPLE", + "BLUE", "BLUE_CYAN", "CYAN", "CYAN_GREEN", + "GREEN", "GREEN_YELLOW", "GREEN_BEIGE", "BEIGE" + }; + string PAL_COLOR[16] = { + "BLACK0", "BLACK1", "YELLOW", "GREEN_YELLOW", + "ORANGE", "GREEN", "RED", "CYAN_GREEN", + "MAUVE", "CYAN", "VIOLET", "BLUE_CYAN", + "PURPLE", "BLUE", "BLACKE", "BLACKF" + }; + string SECAM_COLOR[8] = { + "BLACK", "BLUE", "RED", "PURPLE", + "GREEN", "CYAN", "YELLOW", "WHITE" + }; + bool isNTSC = myConsole.timing() == ConsoleTiming::ntsc; + bool isPAL = myConsole.timing() == ConsoleTiming::pal; #define ALIGN(x) setfill(' ') << left << setw(x) // We can't print the header to the disassembly until it's actually // been processed; therefore buffer output to a string first ostringstream buf; - buf << "\n\n;***********************************************************\n" - << "; Bank " << myConsole.cartridge().getBank(); - if (myConsole.cartridge().bankCount() > 1) - buf << " / 0.." << myConsole.cartridge().bankCount() - 1; - buf << "\n;***********************************************************\n\n"; // Use specific settings for disassembly output // This will most likely differ from what you see in the debugger @@ -992,13 +1061,34 @@ string CartDebug::saveDisassembly() Disassembly disasm; disasm.list.reserve(2048); - for(int bank = 0; bank < myConsole.cartridge().bankCount(); ++bank) + uInt16 romBankCount = myConsole.cartridge().romBankCount(); + uInt16 oldBank = myConsole.cartridge().getBank(); + + // prepare for switching banks + myConsole.cartridge().unlockBank(); + uInt32 origin = 0; + + for(int bank = 0; bank < romBankCount; ++bank) { + // TODO: not every CartDebugWidget does it like that, we need a method + myConsole.cartridge().unlockBank(); + myConsole.cartridge().bank(bank); + myConsole.cartridge().lockBank(); + BankInfo& info = myBankInfo[bank]; + + disassembleBank(bank); + // An empty address list means that DiStella can't do a disassembly if(info.addressList.size() == 0) continue; + buf << "\n\n;***********************************************************\n" + << "; Bank " << bank; + if (romBankCount > 1) + buf << " / 0.." << romBankCount - 1; + buf << "\n;***********************************************************\n\n"; + // Disassemble bank disasm.list.clear(); DiStella distella(*this, disasm.list, info, settings, @@ -1007,8 +1097,14 @@ string CartDebug::saveDisassembly() if (myReserved.breakFound) addLabel("Break", myDebugger.dpeek(0xfffe)); - buf << " SEG CODE\n" - << " ORG $" << Base::HEX4 << info.offset << "\n\n"; + buf << " SEG CODE\n"; + + if(romBankCount == 1) + buf << " ORG $" << Base::HEX4 << info.offset << "\n\n"; + else + buf << " ORG $" << Base::HEX4 << origin << "\n" + << " RORG $" << Base::HEX4 << info.offset << "\n\n"; + origin += uInt32(info.size); // Format in 'distella' style for(uInt32 i = 0; i < disasm.list.size(); ++i) @@ -1022,76 +1118,115 @@ string CartDebug::saveDisassembly() switch(tag.type) { - case CartDebug::CODE: - { + case Device::CODE: buf << ALIGN(32) << tag.disasm << tag.ccount.substr(0, 5) << tag.ctotal << tag.ccount.substr(5, 2); if (tag.disasm.find("WSYNC") != std::string::npos) buf << "\n;---------------------------------------"; break; - } - case CartDebug::ROW: - { + + case Device::ROW: buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8*4-1) << "; $" << Base::HEX4 << tag.address << " (*)"; break; - } - case CartDebug::GFX: - { + + case Device::GFX: buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$") << tag.bytes << " ; |"; for(int c = 12; c < 20; ++c) buf << ((tag.disasm[c] == '\x1e') ? "#" : " "); buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (G)"; break; - } - case CartDebug::PGFX: - { + + case Device::PGFX: buf << ".byte " << (settings.gfxFormat == Base::Fmt::_2 ? "%" : "$") << tag.bytes << " ; |"; for(int c = 12; c < 20; ++c) buf << ((tag.disasm[c] == '\x1f') ? "*" : " "); buf << ALIGN(13) << "|" << "$" << Base::HEX4 << tag.address << " (P)"; break; - } - case CartDebug::DATA: - { + + case Device::COL: + buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (C)"; + break; + + case Device::PCOL: + buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (CP)"; + break; + + case Device::BCOL: + buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 15) << "; $" << Base::HEX4 << tag.address << " (CB)"; + break; + + case Device::AUD: + buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (A)"; + break; + + case Device::DATA: buf << ".byte " << ALIGN(32) << tag.disasm.substr(6, 8 * 4 - 1) << "; $" << Base::HEX4 << tag.address << " (D)"; break; - } - case CartDebug::NONE: + + case Device::NONE: default: - { break; - } } // switch buf << "\n"; } } + myConsole.cartridge().unlockBank(); + myConsole.cartridge().bank(oldBank); + myConsole.cartridge().lockBank(); // Some boilerplate, similar to what DiStella adds auto timeinfo = BSPF::localTime(); + stringstream out; out << "; Disassembly of " << myOSystem.romFile().getShortPath() << "\n" << "; Disassembled " << std::put_time(&timeinfo, "%c\n") << "; Using Stella " << STELLA_VERSION << "\n;\n" << "; ROM properties name : " << myConsole.properties().get(PropType::Cart_Name) << "\n" << "; ROM properties MD5 : " << myConsole.properties().get(PropType::Cart_MD5) << "\n" << "; Bankswitch type : " << myConsole.cartridge().about() << "\n;\n" - << "; Legend: * = CODE not yet run (tentative code)\n" - << "; D = DATA directive (referenced in some way)\n" - << "; G = GFX directive, shown as '#' (stored in player, missile, ball)\n" - << "; P = PGFX directive, shown as '*' (stored in playfield)\n" - << "; i = indexed accessed only\n" - << "; c = used by code executed in RAM\n" - << "; s = used by stack\n" - << "; ! = page crossed, 1 cycle penalty\n" + << "; Legend: * = CODE not yet run (tentative code)\n" + << "; D = DATA directive (referenced in some way)\n" + << "; G = GFX directive, shown as '#' (stored in player, missile, ball)\n" + << "; P = PGFX directive, shown as '*' (stored in playfield)\n" + << "; C = COL directive, shown as color constants (stored in player color)\n" + << "; CP = PCOL directive, shown as color constants (stored in playfield color)\n" + << "; CB = BCOL directive, shown as color constants (stored in background color)\n" + << "; A = AUD directive (stored in audio registers)\n" + << "; i = indexed accessed only\n" + << "; c = used by code executed in RAM\n" + << "; s = used by stack\n" + << "; ! = page crossed, 1 cycle penalty\n" << "\n processor 6502\n\n"; + out << "\n;-----------------------------------------------------------\n" + << "; Color constants\n" + << ";-----------------------------------------------------------\n\n"; + + if(isNTSC) + { + for(int i = 0; i < 16; ++i) + out << ALIGN(16) << NTSC_COLOR[i] << " = $" << Base::HEX2 << (i << 4) << "\n"; + } + else if(isPAL) + { + for(int i = 0; i < 16; ++i) + out << ALIGN(16) << PAL_COLOR[i] << " = $" << Base::HEX2 << (i << 4) << "\n"; + } + else + { + for(int i = 0; i < 8; ++i) + out << ALIGN(16) << SECAM_COLOR[i] << " = $" << Base::HEX1 << (i << 1) << "\n"; + } + out << "\n"; + bool addrUsed = false; for(uInt16 addr = 0x00; addr <= 0x0F; ++addr) - addrUsed = addrUsed || myReserved.TIARead[addr] || (mySystem.getAccessFlags(addr) & WRITE); + addrUsed = addrUsed || myReserved.TIARead[addr] || (mySystem.getAccessFlags(addr) & Device::WRITE); for(uInt16 addr = 0x00; addr <= 0x3F; ++addr) - addrUsed = addrUsed || myReserved.TIAWrite[addr] || (mySystem.getAccessFlags(addr) & DATA); + addrUsed = addrUsed || myReserved.TIAWrite[addr] || (mySystem.getAccessFlags(addr) & Device::DATA); for(uInt16 addr = 0x00; addr <= 0x17; ++addr) addrUsed = addrUsed || myReserved.IOReadWrite[addr]; + if(addrUsed) { out << "\n;-----------------------------------------------------------\n" @@ -1103,7 +1238,7 @@ string CartDebug::saveDisassembly() if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr]) out << ALIGN(16) << ourTIAMnemonicR[addr] << "= $" << Base::HEX2 << right << addr << " ; (R)\n"; - else if (mySystem.getAccessFlags(addr) & DATA) + else if (mySystem.getAccessFlags(addr) & Device::DATA) out << ";" << ALIGN(16-1) << ourTIAMnemonicR[addr] << "= $" << Base::HEX2 << right << addr << " ; (Ri)\n"; out << "\n"; @@ -1113,7 +1248,7 @@ string CartDebug::saveDisassembly() if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr]) out << ALIGN(16) << ourTIAMnemonicW[addr] << "= $" << Base::HEX2 << right << addr << " ; (W)\n"; - else if (mySystem.getAccessFlags(addr) & WRITE) + else if (mySystem.getAccessFlags(addr) & Device::WRITE) out << ";" << ALIGN(16-1) << ourTIAMnemonicW[addr] << "= $" << Base::HEX2 << right << addr << " ; (Wi)\n"; out << "\n"; @@ -1128,8 +1263,8 @@ string CartDebug::saveDisassembly() addrUsed = false; for(uInt16 addr = 0x80; addr <= 0xFF; ++addr) addrUsed = addrUsed || myReserved.ZPRAM[addr-0x80] - || (mySystem.getAccessFlags(addr) & (DATA | WRITE)) - || (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE)); + || (mySystem.getAccessFlags(addr) & (Device::DATA | Device::WRITE)) + || (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE)); if(addrUsed) { bool addLine = false; @@ -1138,9 +1273,9 @@ string CartDebug::saveDisassembly() << ";-----------------------------------------------------------\n\n"; for (uInt16 addr = 0x80; addr <= 0xFF; ++addr) { - bool ramUsed = (mySystem.getAccessFlags(addr) & (DATA | WRITE)); - bool codeUsed = (mySystem.getAccessFlags(addr) & CODE); - bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (DATA | WRITE)); + bool ramUsed = (mySystem.getAccessFlags(addr) & (Device::DATA | Device::WRITE)); + bool codeUsed = (mySystem.getAccessFlags(addr) & Device::CODE); + bool stackUsed = (mySystem.getAccessFlags(addr|0x100) & (Device::DATA | Device::WRITE)); if (myReserved.ZPRAM[addr - 0x80] && myUserLabels.find(addr) == myUserLabels.end()) { @@ -1194,10 +1329,22 @@ string CartDebug::saveDisassembly() // And finally, output the disassembly out << buf.str(); + const string& propsname = + myConsole.properties().get(PropType::Cart_Name) + ".asm"; + FilesystemNode node(myOSystem.defaultSaveDir().getPath() + propsname); stringstream retVal; - if(myConsole.cartridge().bankCount() > 1) - retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported, only currently enabled banks disassembled\n"); - retVal << "saved " << node.getShortPath() << " OK"; + try + { + node.write(out); + + if(myConsole.cartridge().romBankCount() > 1) + retVal << DebuggerParser::red("disassembly for multi-bank ROM not fully supported\n"); + retVal << "saved " << node.getShortPath() << " OK"; + } + catch(...) + { + retVal << "Unable to save disassembly to " << node.getShortPath(); + } return retVal.str(); } @@ -1206,22 +1353,40 @@ string CartDebug::saveRom() { const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".a26"; - FilesystemNode node(myOSystem.defaultSaveDir() + rom); - ofstream out(node.getPath(), std::ios::binary); - if(out && myConsole.cartridge().saveROM(out)) + FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom); + if(myConsole.cartridge().saveROM(node)) return "saved ROM as " + node.getShortPath(); else return DebuggerParser::red("failed to save ROM"); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartDebug::saveAccessFile() +{ + stringstream out; + out << myConsole.tia().getAccessCounters(); + out << myConsole.riot().getAccessCounters(); + out << myConsole.cartridge().getAccessCounters(); + + try + { + const string& rom = myConsole.properties().get(PropType::Cart_Name) + ".csv"; + FilesystemNode node(myOSystem.defaultSaveDir().getPath() + rom); + + node.write(out); + return "saved access counters as " + node.getShortPath(); + } + catch(...) + { + } + return DebuggerParser::red("failed to save access counters file"); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::listConfig(int bank) { - if(myConsole.cartridge().bankCount() > 1) - return DebuggerParser::red("config file for multi-bank ROM not yet supported"); - - uInt32 startbank = 0, endbank = bankCount(); - if(bank >= 0 && bank < bankCount()) + uInt32 startbank = 0, endbank = romBankCount(); + if(bank >= 0 && bank < romBankCount()) { startbank = bank; endbank = startbank + 1; @@ -1232,27 +1397,30 @@ string CartDebug::listConfig(int bank) for(uInt32 b = startbank; b < endbank; ++b) { BankInfo& info = myBankInfo[b]; - buf << "[" << b << "]" << endl; + buf << "Bank [" << b << "]" << endl; for(const auto& i: info.directiveList) { - if(i.type != CartDebug::NONE) + if(i.type != Device::NONE) { buf << "(*) "; - disasmTypeAsString(buf, i.type); + AccessTypeAsString(buf, i.type); buf << " " << Base::HEX4 << i.start << " " << Base::HEX4 << i.end << endl; } } getBankDirectives(buf, info); } + if(myConsole.cartridge().romBankCount() > 1) + buf << DebuggerParser::red("config file for multi-bank ROM not fully supported") << endl; + return buf.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::clearConfig(int bank) { - uInt32 startbank = 0, endbank = bankCount(); - if(bank >= 0 && bank < bankCount()) + uInt32 startbank = 0, endbank = romBankCount(); + if(bank >= 0 && bank < romBankCount()) { startbank = bank; endbank = startbank + 1; @@ -1334,15 +1502,15 @@ void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const // Now consider each byte uInt32 prev = info.offset, addr = prev + 1; - DisasmType prevType = disasmTypeAbsolute(mySystem.getAccessFlags(prev)); + Device::AccessType prevType = accessTypeAbsolute(mySystem.getAccessFlags(prev)); for( ; addr < info.offset + info.size; ++addr) { - DisasmType currType = disasmTypeAbsolute(mySystem.getAccessFlags(addr)); + Device::AccessType currType = accessTypeAbsolute(mySystem.getAccessFlags(addr)); // Have we changed to a new type? if(currType != prevType) { - disasmTypeAsString(buf, prevType); + AccessTypeAsString(buf, prevType); buf << " " << Base::HEX4 << prev << " " << Base::HEX4 << (addr-1) << endl; prev = addr; @@ -1353,13 +1521,13 @@ void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const // Grab the last directive, making sure it accounts for all remaining space if(prev != addr) { - disasmTypeAsString(buf, prevType); + AccessTypeAsString(buf, prevType); buf << " " << Base::HEX4 << prev << " " << Base::HEX4 << (addr-1) << endl; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartDebug::addressTypeAsString(ostream& buf, uInt16 addr) const +void CartDebug::accessTypeAsString(ostream& buf, uInt16 addr) const { if(!(addr & 0x1000)) { @@ -1372,70 +1540,88 @@ void CartDebug::addressTypeAsString(ostream& buf, uInt16 addr) const label = myDisLabels[addr & 0xFFF]; buf << endl << "directive: " << Base::toString(directive, Base::Fmt::_2_8) << " "; - disasmTypeAsString(buf, directive); + AccessTypeAsString(buf, directive); buf << endl << "emulation: " << Base::toString(debugger, Base::Fmt::_2_8) << " "; - disasmTypeAsString(buf, debugger); + AccessTypeAsString(buf, debugger); buf << endl << "tentative: " << Base::toString(label, Base::Fmt::_2_8) << " "; - disasmTypeAsString(buf, label); + AccessTypeAsString(buf, label); buf << endl; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartDebug::DisasmType CartDebug::disasmTypeAbsolute(uInt8 flags) const +Device::AccessType CartDebug::accessTypeAbsolute(Device::AccessFlags flags) const { - if(flags & CartDebug::CODE) - return CartDebug::CODE; - else if(flags & CartDebug::TCODE) - return CartDebug::CODE; // TODO - should this be separate?? - else if(flags & CartDebug::GFX) - return CartDebug::GFX; - else if(flags & CartDebug::PGFX) - return CartDebug::PGFX; - else if(flags & CartDebug::DATA) - return CartDebug::DATA; - else if(flags & CartDebug::ROW) - return CartDebug::ROW; + if(flags & Device::CODE) + return Device::CODE; + else if(flags & Device::TCODE) + return Device::CODE; // TODO - should this be separate?? + else if(flags & Device::GFX) + return Device::GFX; + else if(flags & Device::PGFX) + return Device::PGFX; + else if(flags & Device::COL) + return Device::COL; + else if(flags & Device::PCOL) + return Device::PCOL; + else if(flags & Device::BCOL) + return Device::BCOL; + else if(flags & Device::AUD) + return Device::AUD; + else if(flags & Device::DATA) + return Device::DATA; + else if(flags & Device::ROW) + return Device::ROW; else - return CartDebug::NONE; + return Device::NONE; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartDebug::disasmTypeAsString(ostream& buf, DisasmType type) const +void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessType type) const { switch(type) { - case CartDebug::CODE: buf << "CODE"; break; - case CartDebug::TCODE: buf << "TCODE"; break; - case CartDebug::GFX: buf << "GFX"; break; - case CartDebug::PGFX: buf << "PGFX"; break; - case CartDebug::DATA: buf << "DATA"; break; - case CartDebug::ROW: buf << "ROW"; break; - case CartDebug::REFERENCED: - case CartDebug::VALID_ENTRY: - case CartDebug::NONE: break; + case Device::CODE: buf << "CODE"; break; + case Device::TCODE: buf << "TCODE"; break; + case Device::GFX: buf << "GFX"; break; + case Device::PGFX: buf << "PGFX"; break; + case Device::COL: buf << "COL"; break; + case Device::PCOL: buf << "PCOL"; break; + case Device::BCOL: buf << "BCOL"; break; + case Device::AUD: buf << "AUD"; break; + case Device::DATA: buf << "DATA"; break; + case Device::ROW: buf << "ROW"; break; + default: break; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartDebug::disasmTypeAsString(ostream& buf, uInt8 flags) const +void CartDebug::AccessTypeAsString(ostream& buf, Device::AccessFlags flags) const { if(flags) { - if(flags & CartDebug::CODE) + if(flags & Device::CODE) buf << "CODE "; - if(flags & CartDebug::TCODE) + if(flags & Device::TCODE) buf << "TCODE "; - if(flags & CartDebug::GFX) + if(flags & Device::GFX) buf << "GFX "; - if(flags & CartDebug::PGFX) + if(flags & Device::PGFX) buf << "PGFX "; - if(flags & CartDebug::DATA) + if(flags & Device::COL) + buf << "COL "; + if(flags & Device::PCOL) + buf << "PCOL "; + if(flags & Device::BCOL) + buf << "BCOL "; + if(flags & Device::AUD) + buf << "AUD "; + if(flags & Device::DATA) buf << "DATA "; - if(flags & CartDebug::ROW) + if(flags & Device::ROW) buf << "ROW "; - if(flags & CartDebug::REFERENCED) + if(flags & Device::REFERENCED) buf << "*REFERENCED "; - if(flags & CartDebug::VALID_ENTRY) + if(flags & Device::VALID_ENTRY) buf << "*VALID_ENTRY "; } else diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 57a9e1319..4ab326be1 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -31,6 +31,7 @@ using CartMethod = int (CartDebug::*)(); #include "bspf.hxx" #include "DebuggerSystem.hxx" +#include "Device.hxx" class CartState : public DebuggerState { @@ -47,30 +48,8 @@ class CartDebug : public DebuggerSystem friend class DiStella; public: - enum DisasmType { - NONE = 0, - REFERENCED = 1 << 0, /* 0x01, code somewhere in the program references it, - i.e. LDA $F372 referenced $F372 */ - VALID_ENTRY = 1 << 1, /* 0x02, addresses that can have a label placed in front of it. - A good counterexample would be "FF00: LDA $FE00"; $FF01 - would be in the middle of a multi-byte instruction, and - therefore cannot be labelled. */ - - // The following correspond to specific types that can be set within the - // debugger, or specified in a Distella cfg file, and are listed in order - // of decreasing hierarchy - // - CODE = 1 << 7, // 0x80, disassemble-able code segments - TCODE = 1 << 6, // 0x40, (tentative) disassemble-able code segments - GFX = 1 << 5, // 0x20, addresses loaded into GRPx registers - PGFX = 1 << 4, // 0x10, addresses loaded into PFx registers - DATA = 1 << 3, // 0x08, addresses loaded into registers other than GRPx / PFx - ROW = 1 << 2, // 0x04, all other addresses - // special type for poke() - WRITE = TCODE // 0x40, address written to - }; struct DisassemblyTag { - DisasmType type{NONE}; + Device::AccessType type{Device::NONE}; uInt16 address{0}; string label; string disasm; @@ -104,28 +83,55 @@ class CartDebug : public DebuggerSystem CartDebugWidget* getDebugWidget() const { return myDebugWidget; } void setDebugWidget(CartDebugWidget* w) { myDebugWidget = w; } + + // Return the address of the last CPU read + int lastReadAddress(); + // Return the address of the last CPU write + int lastWriteAddress(); + // Return the base (= non-mirrored) address of the last CPU read int lastReadBaseAddress(); // Return the base (= non-mirrored) address of the last CPU write int lastWriteBaseAddress(); - // The following two methods are meant to be used together - // First, a call is made to disassemble(), which updates the disassembly - // list; it will figure out when an actual complete disassembly is - // required, and when the previous results can be used - // - // Later, successive calls to disassemblyList() simply return the - // previous results; no disassembly is done in this case /** - Disassemble from the given address using the Distella disassembler + Disassemble from the given address and its bank using the Distella disassembler + Address-to-label mappings (and vice-versa) are also determined here + + @param address The address to start with + @param force Force a re-disassembly, even if the state hasn't changed + + @return True if disassembly changed from previous call, else false + */ + bool disassembleAddr(uInt16 address, bool force = false); + + /** + Disassemble from the current PC and its bank using the Distella disassembler Address-to-label mappings (and vice-versa) are also determined here @param force Force a re-disassembly, even if the state hasn't changed @return True if disassembly changed from previous call, else false */ - bool disassemble(bool force = false); + bool disassemblePC(bool force = false); + /** + Disassemble the given bank using the Distella disassembler + Address-to-label mappings (and vice-versa) are also determined here + + @param bank The bank to disassemble + + @return True if disassembly changed from previous call, else false + */ + bool disassembleBank(int bank); + + + // First, a call is made to disassemble(), which updates the disassembly + // list, is required; it will figure out when an actual complete + // disassembly is required, and when the previous results can be used + // + // Later, successive calls to disassembly() simply return the + // previous results; no disassembly is done in this case /** Get the results from the most recent call to disassemble() */ @@ -149,7 +155,7 @@ class CartDebug : public DebuggerSystem @return The disassembly represented as a string */ - string disassemble(uInt16 start, uInt16 lines) const; + string disassembleLines(uInt16 start, uInt16 lines) const; /** Add a directive to the disassembler. Directives are basically overrides @@ -157,14 +163,14 @@ class CartDebug : public DebuggerSystem things can't be automatically determined. For now, these directives have exactly the same syntax as in a distella configuration file. - @param type Currently, CODE/DATA/GFX are supported + @param type Currently, CODE/DATA/GFX/PGFX/COL/PCOL/BCOL/AUD/ROW are supported @param start The start address (inclusive) to mark with the given type @param end The end address (inclusive) to mark with the given type @param bank Bank to which these directive apply (0 indicated current bank) @return True if directive was added, else false if it was removed */ - bool addDirective(CartDebug::DisasmType type, uInt16 start, uInt16 end, + bool addDirective(Device::AccessType type, uInt16 start, uInt16 end, int bank = -1); // The following are convenience methods that query the cartridge object @@ -181,7 +187,7 @@ class CartDebug : public DebuggerSystem /** Get the total number of banks supported by the cartridge. */ - int bankCount() const; + int romBankCount() const; /** Add a label and associated address. @@ -231,6 +237,11 @@ class CartDebug : public DebuggerSystem string saveDisassembly(); string saveRom(); + /** + Save access counters file + */ + string saveAccessFile(); + /** Show Distella directives (both set by the user and determined by Distella) for the given bank (or all banks, if no bank is specified). @@ -249,18 +260,21 @@ class CartDebug : public DebuggerSystem */ void getCompletions(const char* in, StringList& list) const; - // Convert given address to corresponding disassembly type and append to buf - void addressTypeAsString(ostream& buf, uInt16 addr) const; + // Convert given address to corresponding access type and append to buf + void accessTypeAsString(ostream& buf, uInt16 addr) const; + + // Convert access enum type to corresponding string and append to buf + void AccessTypeAsString(ostream& buf, Device::AccessType type) const; private: using AddrToLabel = std::map; using LabelToAddr = std::map>; - using AddrTypeArray = std::array; + using AddrTypeArray = std::array; struct DirectiveTag { - DisasmType type{NONE}; + Device::AccessType type{Device::NONE}; uInt16 start{0}; uInt16 end{0}; }; @@ -290,6 +304,18 @@ class CartDebug : public DebuggerSystem }; ReservedEquates myReserved; + /** + Disassemble from the given address using the Distella disassembler + Address-to-label mappings (and vice-versa) are also determined here + + @param bank The current bank to disassemble + @param PC A program counter to start with + @param force Force a re-disassembly, even if the state hasn't changed + + @return True if disassembly changed from previous call, else false + */ + bool disassemble(int bank, uInt16 PC, bool force = false); + // Actually call DiStella to fill the DisassemblyList structure // Return whether the search address was actually in the list bool fillDisassemblyList(BankInfo& bankinfo, uInt16 search); @@ -298,15 +324,12 @@ class CartDebug : public DebuggerSystem // based on its disassembly void getBankDirectives(ostream& buf, BankInfo& info) const; - // Get disassembly enum type from 'flags', taking precendence into account - DisasmType disasmTypeAbsolute(uInt8 flags) const; + // Get access enum type from 'flags', taking precendence into account + Device::AccessType accessTypeAbsolute(Device::AccessFlags flags) const; - // Convert disassembly enum type to corresponding string and append to buf - void disasmTypeAsString(ostream& buf, DisasmType type) const; - - // Convert all disassembly types in 'flags' to corresponding string and + // Convert all access types in 'flags' to corresponding string and // append to buf - void disasmTypeAsString(ostream& buf, uInt8 flags) const; + void AccessTypeAsString(ostream& buf, Device::AccessFlags flags) const; private: const OSystem& myOSystem; @@ -346,9 +369,6 @@ class CartDebug : public DebuggerSystem // The maximum length of all labels currently defined uInt16 myLabelLength{8}; // longest pre-defined label - // Filenames to use for various I/O (currently these are hardcoded) - string myListFile, mySymbolFile, myCfgFile, myDisasmFile, myRomFile; - /// Table of instruction mnemonics static std::array ourTIAMnemonicR; // read mode static std::array ourTIAMnemonicW; // write mode diff --git a/src/debugger/CpuDebug.cxx b/src/debugger/CpuDebug.cxx index 549d512e3..f0bf9be12 100644 --- a/src/debugger/CpuDebug.cxx +++ b/src/debugger/CpuDebug.cxx @@ -20,7 +20,6 @@ #include "M6502.hxx" #include "System.hxx" #include "Debugger.hxx" -#include "CartDebug.hxx" #include "TIADebug.hxx" #include "CpuDebug.hxx" @@ -46,6 +45,7 @@ const DebuggerState& CpuDebug::getState() myState.srcA = my6502.lastSrcAddressA(); myState.srcX = my6502.lastSrcAddressX(); myState.srcY = my6502.lastSrcAddressY(); + myState.dest = my6502.lastWriteAddress(); Debugger::set_bits(myState.PS, myState.PSbits); @@ -66,6 +66,7 @@ void CpuDebug::saveOldState() myOldState.srcA = my6502.lastSrcAddressA(); myOldState.srcX = my6502.lastSrcAddressX(); myOldState.srcY = my6502.lastSrcAddressY(); + myOldState.dest = my6502.lastWriteAddress(); Debugger::set_bits(myOldState.PS, myOldState.PSbits); } diff --git a/src/debugger/CpuDebug.hxx b/src/debugger/CpuDebug.hxx index a9d9bc99c..dd016fe88 100644 --- a/src/debugger/CpuDebug.hxx +++ b/src/debugger/CpuDebug.hxx @@ -31,7 +31,7 @@ class CpuState : public DebuggerState { public: int PC{0}, SP{0}, PS{0}, A{0}, X{0}, Y{0}; - int srcS{0}, srcA{0}, srcX{0}, srcY{0}; + int srcS{0}, srcA{0}, srcX{0}, srcY{0}, dest{0}; BoolArray PSbits; }; diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 1ccf5e3f1..315a45c3b 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -115,7 +115,8 @@ void Debugger::initialize() FBInitStatus Debugger::initializeVideo() { string title = string("Stella ") + STELLA_VERSION + ": Debugger mode"; - return myOSystem.frameBuffer().createDisplay(title, myWidth, myHeight); + return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Debugger, + myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -166,7 +167,7 @@ string Debugger::autoExec(StringList* history) ostringstream buf; // autoexec.script is always run - FilesystemNode autoexec(myOSystem.baseDir() + "autoexec.script"); + FilesystemNode autoexec(myOSystem.baseDir().getPath() + "autoexec.script"); buf << "autoExec():" << endl << myParser->exec(autoexec, history) << endl; @@ -292,9 +293,10 @@ void Debugger::loadAllStates() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Debugger::step() +int Debugger::step(bool save) { - saveOldState(); + if(save) + saveOldState(); uInt64 startCycle = mySystem.cycles(); @@ -302,7 +304,8 @@ int Debugger::step() myOSystem.console().tia().updateScanlineByStep().flushLineCache(); lockSystem(); - addState("step"); + if(save) + addState("step"); return int(mySystem.cycles() - startCycle); } @@ -440,19 +443,19 @@ bool Debugger::writeTrap(uInt16 t) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Debugger::peek(uInt16 addr, uInt8 flags) +uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags) { return mySystem.peek(addr, flags); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Debugger::dpeek(uInt16 addr, uInt8 flags) +uInt16 Debugger::dpeek(uInt16 addr, Device::AccessFlags flags) { return uInt16(mySystem.peek(addr, flags) | (mySystem.peek(addr+1, flags) << 8)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::poke(uInt16 addr, uInt8 value, uInt8 flags) +void Debugger::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags) { mySystem.poke(addr, value, flags); } @@ -464,26 +467,26 @@ M6502& Debugger::m6502() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Debugger::peekAsInt(int addr, uInt8 flags) +int Debugger::peekAsInt(int addr, Device::AccessFlags flags) { return mySystem.peek(uInt16(addr), flags); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Debugger::dpeekAsInt(int addr, uInt8 flags) +int Debugger::dpeekAsInt(int addr, Device::AccessFlags flags) { return mySystem.peek(uInt16(addr), flags) | (mySystem.peek(uInt16(addr+1), flags) << 8); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Debugger::getAccessFlags(uInt16 addr) const +Device::AccessFlags Debugger::getAccessFlags(uInt16 addr) const { return mySystem.getAccessFlags(addr); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::setAccessFlags(uInt16 addr, uInt8 flags) +void Debugger::setAccessFlags(uInt16 addr, Device::AccessFlags flags) { mySystem.setAccessFlags(addr, flags); } @@ -688,6 +691,7 @@ void Debugger::setStartState() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Debugger::setQuitState() { + myDialog->saveConfig(); saveOldState(); // Bus must be unlocked for normal operation when leaving debugger mode @@ -873,7 +877,7 @@ std::array Debugger::ourBuiltinFunctions = { { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Names are defined here, but processed in YaccParser -std::array Debugger::ourPseudoRegisters = { { +std::array Debugger::ourPseudoRegisters = { { // Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = { { "_bank", "Currently selected bank" }, { "_cclocks", "Color clocks on current scanline" }, @@ -881,12 +885,15 @@ std::array Debugger::ourPseudoRegisters = { { { "_cycleslo", "Lower 32 bits of number of cycles since emulation started" }, { "_fcount", "Number of frames since emulation started" }, { "_fcycles", "Number of cycles since frame started" }, - { "_icycles", "Number of cycles of last instruction" }, + { "_icycles", "Number of cycles of last instruction" }, { "_scan", "Current scanline count" }, + { "_scanend", "Scanline count at end of last frame" }, { "_scycles", "Number of cycles in current scanline" }, { "_vblank", "Whether vertical blank is enabled (1 or 0)" }, { "_vsync", "Whether vertical sync is enabled (1 or 0)" } // CPU address access functions: - /*{ "__lastread", "last CPU read address" }, - { "__lastwrite", "last CPU write address" },*/ + /*{ "_lastread", "last CPU read address" }, + { "_lastwrite", "last CPU write address" }, + { "__lastbaseread", "last CPU read base address" }, + { "__lastbasewrite", "last CPU write base address" }*/ } }; diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx index 7e9ad0bc1..6083d556a 100644 --- a/src/debugger/Debugger.hxx +++ b/src/debugger/Debugger.hxx @@ -47,6 +47,7 @@ class RewindManager; #include "DialogContainer.hxx" #include "DebuggerDialog.hxx" #include "FrameBufferConstants.hxx" +#include "Cart.hxx" #include "bspf.hxx" /** @@ -243,18 +244,18 @@ class Debugger : public DialogContainer static Debugger& debugger() { return *myStaticDebugger; } /** Convenience methods to access peek/poke from System */ - uInt8 peek(uInt16 addr, uInt8 flags = 0); - uInt16 dpeek(uInt16 addr, uInt8 flags = 0); - void poke(uInt16 addr, uInt8 value, uInt8 flags = 0); + uInt8 peek(uInt16 addr, Device::AccessFlags flags = Device::NONE); + uInt16 dpeek(uInt16 addr, Device::AccessFlags flags = Device::NONE); + void poke(uInt16 addr, uInt8 value, Device::AccessFlags flags = Device::NONE); /** Convenience method to access the 6502 from System */ M6502& m6502() const; /** These are now exposed so Expressions can use them. */ - int peekAsInt(int addr, uInt8 flags = 0); - int dpeekAsInt(int addr, uInt8 flags = 0); - int getAccessFlags(uInt16 addr) const; - void setAccessFlags(uInt16 addr, uInt8 flags); + int peekAsInt(int addr, Device::AccessFlags flags = Device::NONE); + int dpeekAsInt(int addr, Device::AccessFlags flags = Device::NONE); + Device::AccessFlags getAccessFlags(uInt16 addr) const; + void setAccessFlags(uInt16 addr, Device::AccessFlags flags); uInt32 getBaseAddress(uInt32 addr, bool read); @@ -305,7 +306,7 @@ class Debugger : public DialogContainer */ void setQuitState(); - int step(); + int step(bool save = true); int trace(); void nextScanline(int lines); void nextFrame(int frames); @@ -362,7 +363,7 @@ class Debugger : public DialogContainer string name, help; }; static std::array ourBuiltinFunctions; - static std::array ourPseudoRegisters; + static std::array ourPseudoRegisters; private: // rewind/unwind n states diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 50ff2daae..73f09268f 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -30,6 +30,7 @@ #include "M6502.hxx" #include "Expression.hxx" #include "FSNode.hxx" +#include "OSystem.hxx" #include "Settings.hxx" #include "PromptWidget.hxx" #include "RomWidget.hxx" @@ -111,6 +112,8 @@ string DebuggerParser::run(const string& command) if(validateArgs(i)) { myCommand = i; + if(commands[i].refreshRequired) + debugger.baseDialog()->saveConfig(); commands[i].executor(this); } @@ -129,9 +132,9 @@ string DebuggerParser::exec(const FilesystemNode& file, StringList* history) { if(file.exists()) { - ifstream in(file.getPath()); - if(!in.is_open()) - return red("script file \'" + file.getShortPath() + "\' not found"); + stringstream in; + try { file.read(in); } + catch(...) { return red("script file \'" + file.getShortPath() + "\' not found"); } ostringstream buf; int count = 0; @@ -630,11 +633,7 @@ string DebuggerParser::saveScriptFile(string file) if(file.find_last_of('.') == string::npos) file += ".script"; - FilesystemNode node(debugger.myOSystem.defaultSaveDir() + file); - ofstream out(node.getPath()); - if(!out.is_open()) - return "Unable to save script to " + node.getShortPath(); - + stringstream out; Debugger::FunctionDefMap funcs = debugger.getFunctionDefMap(); for(const auto& f: funcs) if (!debugger.isBuiltinFunction(f.first)) @@ -675,9 +674,42 @@ string DebuggerParser::saveScriptFile(string file) out << endl; } + FilesystemNode node(debugger.myOSystem.defaultSaveDir().getPath() + file); + try + { + node.write(out); + } + catch(...) + { + return "Unable to save script to " + node.getShortPath(); + } + return "saved " + node.getShortPath() + " OK"; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DebuggerParser::executeDirective(Device::AccessType type) +{ + if(argCount != 2) + { + outputCommandError("specify start and end of range only", myCommand); + return; + } + else if(args[1] < args[0]) + { + commandResult << red("start address must be <= end address"); + return; + } + + bool result = debugger.cartDebug().addDirective(type, args[0], args[1]); + + commandResult << (result ? "added " : "removed "); + debugger.cartDebug().AccessTypeAsString(commandResult, type); + commandResult << " directive on range $" + << hex << args[0] << " $" << hex << args[1]; + debugger.rom().invalidate(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // executor methods for commands[] array. All are void, no args. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -689,6 +721,13 @@ void DebuggerParser::executeA() debugger.cpuDebug().setA(uInt8(args[0])); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "aud" +void DebuggerParser::executeAud() +{ + executeDirective(Device::AUD); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "base" void DebuggerParser::executeBase() @@ -720,13 +759,20 @@ void DebuggerParser::executeBase() } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "bcol" +void DebuggerParser::executeBCol() +{ + executeDirective(Device::BCOL); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "break" void DebuggerParser::executeBreak() { uInt16 addr; uInt8 bank; - uInt32 bankCount = debugger.cartDebug().bankCount(); + uInt32 romBankCount = debugger.cartDebug().romBankCount(); if(argCount == 0) addr = debugger.cpuDebug().pc(); @@ -738,7 +784,7 @@ void DebuggerParser::executeBreak() else { bank = args[1]; - if(bank >= bankCount && bank != 0xff) + if(bank >= romBankCount && bank != 0xff) { commandResult << red("invalid bank"); return; @@ -754,12 +800,12 @@ void DebuggerParser::executeBreak() commandResult << "cleared"; commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors"; - if(bankCount > 1) + if(romBankCount > 1) commandResult << " in bank #" << std::dec << int(bank); } else { - for(int i = 0; i < debugger.cartDebug().bankCount(); ++i) + for(int i = 0; i < debugger.cartDebug().romBankCount(); ++i) { bool set = debugger.toggleBreakPoint(addr, i); @@ -772,7 +818,7 @@ void DebuggerParser::executeBreak() commandResult << "cleared"; commandResult << " breakpoint at $" << Base::HEX4 << addr << " + mirrors"; - if(bankCount > 1) + if(romBankCount > 1) commandResult << " in bank #" << std::dec << int(bank); } } @@ -912,22 +958,14 @@ void DebuggerParser::executeCls() // "code" void DebuggerParser::executeCode() { - if(argCount != 2) - { - outputCommandError("specify start and end of range only", myCommand); - return; - } - else if(args[1] < args[0]) - { - commandResult << red("start address must be <= end address"); - return; - } + executeDirective(Device::CODE); +} - bool result = debugger.cartDebug().addDirective( - CartDebug::CODE, args[0], args[1]); - commandResult << (result ? "added" : "removed") << " CODE directive on range $" - << hex << args[0] << " $" << hex << args[1]; - debugger.rom().invalidate(); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "col" +void DebuggerParser::executeCol() +{ + executeDirective(Device::COL); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -953,22 +991,7 @@ void DebuggerParser::executeD() // "data" void DebuggerParser::executeData() { - if(argCount != 2) - { - outputCommandError("specify start and end of range only", myCommand); - return; - } - else if(args[1] < args[0]) - { - commandResult << red("start address must be <= end address"); - return; - } - - bool result = debugger.cartDebug().addDirective( - CartDebug::DATA, args[0], args[1]); - commandResult << (result ? "added" : "removed") << " DATA directive on range $" - << hex << args[0] << " $" << hex << args[1]; - debugger.rom().invalidate(); + executeDirective(Device::DATA); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1067,7 +1090,7 @@ void DebuggerParser::executeDisasm() return; } - commandResult << debugger.cartDebug().disassemble(start, lines); + commandResult << debugger.cartDebug().disassembleLines(start, lines); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1123,7 +1146,7 @@ void DebuggerParser::executeDump() file << ".dump"; FilesystemNode node(file.str()); // cout << "dump " << args[0] << "-" << args[1] << " to " << file.str() << endl; - ofstream ofs(node.getPath(), ofstream::out | ofstream::app); + std::ofstream ofs(node.getPath(), std::ofstream::out | std::ofstream::app); if(!ofs.is_open()) { outputCommandError("Unable to append dump to file " + node.getShortPath(), myCommand); @@ -1204,9 +1227,8 @@ void DebuggerParser::executeExec() if(file.find_last_of('.') == string::npos) file += ".script"; FilesystemNode node(file); - if (!node.exists()) { - node = FilesystemNode(debugger.myOSystem.defaultSaveDir() + file); - } + if (!node.exists()) + node = FilesystemNode(debugger.myOSystem.defaultSaveDir().getPath() + file); if (argCount == 2) { execPrefix = argStrings[1]; @@ -1270,22 +1292,7 @@ void DebuggerParser::executeFunction() // "gfx" void DebuggerParser::executeGfx() { - if(argCount != 2) - { - outputCommandError("specify start and end of range only", myCommand); - return; - } - else if(args[1] < args[0]) - { - commandResult << red("start address must be <= end address"); - return; - } - - bool result = debugger.cartDebug().addDirective( - CartDebug::GFX, args[0], args[1]); - commandResult << (result ? "added" : "removed") << " GFX directive on range $" - << hex << args[0] << " $" << hex << args[1]; - debugger.rom().invalidate(); + executeDirective(Device::GFX); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1460,11 +1467,11 @@ void DebuggerParser::executeListbreaks() { stringstream buf; int count = 0; - uInt32 bankCount = debugger.cartDebug().bankCount(); + uInt32 romBankCount = debugger.cartDebug().romBankCount(); for(const auto& bp : debugger.breakPoints().getBreakpoints()) { - if(bankCount == 1) + if(romBankCount == 1) { buf << debugger.cartDebug().getLabel(bp.addr, true, 4) << " "; if(!(++count % 8)) buf << endl; @@ -1626,26 +1633,18 @@ void DebuggerParser::executePc() debugger.cpuDebug().setPC(args[0]); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "pcol" +void DebuggerParser::executePCol() +{ + executeDirective(Device::PCOL); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "pgfx" void DebuggerParser::executePGfx() { - if(argCount != 2) - { - outputCommandError("specify start and end of range only", myCommand); - return; - } - else if(args[1] < args[0]) - { - commandResult << red("start address must be <= end address"); - return; - } - - bool result = debugger.cartDebug().addDirective( - CartDebug::PGFX, args[0], args[1]); - commandResult << (result ? "added" : "removed") << " PGFX directive on range $" - << hex << args[0] << " $" << hex << args[1]; - debugger.rom().invalidate(); + executeDirective(Device::PGFX); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1722,22 +1721,7 @@ void DebuggerParser::executeRom() // "row" void DebuggerParser::executeRow() { - if(argCount != 2) - { - outputCommandError("specify start and end of range only", myCommand); - return; - } - else if(args[1] < args[0]) - { - commandResult << red("start address must be <= end address"); - return; - } - - bool result = debugger.cartDebug().addDirective( - CartDebug::ROW, args[0], args[1]); - commandResult << (result ? "added" : "removed") << " ROW directive on range $" - << hex << args[0] << " $" << hex << args[1]; - debugger.rom().invalidate(); + executeDirective(Device::ROW); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1756,6 +1740,8 @@ void DebuggerParser::executeRunTo() const CartDebug& cartdbg = debugger.cartDebug(); const CartDebug::DisassemblyList& list = cartdbg.disassembly().list; + debugger.saveOldState(); + uInt32 count = 0, max_iterations = uInt32(list.size()); // Create a progress dialog box to show the progress searching through the @@ -1767,7 +1753,7 @@ void DebuggerParser::executeRunTo() bool done = false; do { - debugger.step(); + debugger.step(false); // Update romlist to point to current PC int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc()); @@ -1799,24 +1785,36 @@ void DebuggerParser::executeRunToPc() const CartDebug& cartdbg = debugger.cartDebug(); const CartDebug::DisassemblyList& list = cartdbg.disassembly().list; + debugger.saveOldState(); + uInt32 count = 0; bool done = false; + constexpr uInt32 max_iterations = 1000000; + // Create a progress dialog box to show the progress searching through the + // disassembly, since this may be a time-consuming operation + ostringstream buf; + buf << "RunTo PC searching through " << max_iterations << " instructions"; + ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str()); + progress.setRange(0, max_iterations, 5); + do { - debugger.step(); + debugger.step(false); // Update romlist to point to current PC int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc()); done = (pcline >= 0) && (list[pcline].address == args[0]); - } while(!done && ++count < list.size()); + progress.setProgress(count); + } while(!done && ++count < max_iterations/*list.size()*/); + progress.close(); if(done) commandResult - << "set PC to " << Base::HEX4 << args[0] << " in " - << dec << count << " disassembled instructions"; + << "Set PC to $" << Base::HEX4 << args[0] << " in " + << dec << count << " instructions"; else commandResult - << "PC " << Base::HEX4 << args[0] << " not reached or found in " - << dec << count << " disassembled instructions"; + << "PC $" << Base::HEX4 << args[0] << " not reached or found in " + << dec << count << " instructions"; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1833,6 +1831,13 @@ void DebuggerParser::executeSave() commandResult << saveScriptFile(argStrings[0]); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "saveaccess" +void DebuggerParser::executeSaveAccess() +{ + commandResult << debugger.cartDebug().saveAccessFile(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "saveconfig" void DebuggerParser::executeSaveconfig() @@ -1947,9 +1952,23 @@ void DebuggerParser::executeStepwhile() } Expression* expr = YaccParser::getResult(); int ncycles = 0; + uInt32 count = 0; + constexpr uInt32 max_iterations = 1000000; + + // Create a progress dialog box to show the progress searching through the + // disassembly, since this may be a time-consuming operation + ostringstream buf; + buf << "stepwhile running through " << max_iterations << " disassembled instructions"; + ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str()); + progress.setRange(0, max_iterations, 5); + do { - ncycles += debugger.step(); - } while (expr->evaluate()); + ncycles += debugger.step(false); + + progress.setProgress(count); + } while (expr->evaluate() && ++count < max_iterations); + + progress.close(); commandResult << "executed " << ncycles << " cycles"; } @@ -2054,18 +2073,18 @@ void DebuggerParser::executeTraps(bool read, bool write, const string& command, if(read) { if(beginRead != endRead) - conditionBuf << "__lastread>=" << Base::toString(beginRead) << "&&__lastread<=" << Base::toString(endRead); + conditionBuf << "__lastbaseread>=" << Base::toString(beginRead) << "&&__lastbaseread<=" << Base::toString(endRead); else - conditionBuf << "__lastread==" << Base::toString(beginRead); + conditionBuf << "__lastbaseread==" << Base::toString(beginRead); } if(read && write) conditionBuf << "||"; if(write) { if(beginWrite != endWrite) - conditionBuf << "__lastwrite>=" << Base::toString(beginWrite) << "&&__lastwrite<=" << Base::toString(endWrite); + conditionBuf << "__lastbasewrite>=" << Base::toString(beginWrite) << "&&__lastbasewrite<=" << Base::toString(endWrite); else - conditionBuf << "__lastwrite==" << Base::toString(beginWrite); + conditionBuf << "__lastbasewrite==" << Base::toString(beginWrite); } // parenthesize provided condition (end) if(hasCond) @@ -2194,7 +2213,7 @@ void DebuggerParser::executeType() for(uInt32 i = beg; i <= end; ++i) { commandResult << Base::HEX4 << i << ": "; - debugger.cartDebug().addressTypeAsString(commandResult, i); + debugger.cartDebug().accessTypeAsString(commandResult, i); commandResult << endl; } } @@ -2300,7 +2319,7 @@ void DebuggerParser::executeZ() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // List of all commands available to the parser -std::array DebuggerParser::commands = { { +std::array DebuggerParser::commands = { { { "a", "Set Accumulator to ", @@ -2311,6 +2330,16 @@ std::array DebuggerParser::commands = { { std::mem_fn(&DebuggerParser::executeA) }, + { + "aud", + "Mark 'AUD' range in disassembly", + "Start and end of range required\nExample: aud f000 f010", + true, + false, + { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeAud) + }, + { "base", "Set default number base to ", @@ -2321,6 +2350,17 @@ std::array DebuggerParser::commands = { { std::mem_fn(&DebuggerParser::executeBase) }, + { + "bcol", + "Mark 'BCOL' range in disassembly", + "Start and end of range required\nExample: bcol f000 f010", + true, + false, + { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeBCol) + }, + + { "break", "Break at
      and ", @@ -2442,6 +2482,16 @@ std::array DebuggerParser::commands = { { std::mem_fn(&DebuggerParser::executeCode) }, + { + "col", + "Mark 'COL' range in disassembly", + "Start and end of range required\nExample: col f000 f010", + true, + false, + { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executeCol) + }, + { "colortest", "Show value xx as TIA color", @@ -2847,6 +2897,16 @@ std::array DebuggerParser::commands = { { std::mem_fn(&DebuggerParser::executePc) }, + { + "pcol", + "Mark 'PCOL' range in disassembly", + "Start and end of range required\nExample: col f000 f010", + true, + false, + { Parameters::ARG_WORD, Parameters::ARG_MULTI_BYTE }, + std::mem_fn(&DebuggerParser::executePCol) + }, + { "pgfx", "Mark 'PGFX' range in disassembly", @@ -2980,6 +3040,16 @@ std::array DebuggerParser::commands = { { std::mem_fn(&DebuggerParser::executeSave) }, + { + "saveaccess", + "Save the access counters to CSV file", + "Example: saveaccess (no parameters)", + false, + false, + { Parameters::ARG_END_ARGS }, + std::mem_fn(&DebuggerParser::executeSaveAccess) + }, + { "saveconfig", "Save Distella config file (with default name)", @@ -3182,7 +3252,7 @@ std::array DebuggerParser::commands = { { { "type", - "Show disassembly type for address xx [yy]", + "Show access type for address xx [yy]", "Example: type f000, type f000 f010", true, false, diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index dced64dfb..44445b307 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -27,6 +27,7 @@ class FilesystemNode; struct Command; #include "bspf.hxx" +#include "Device.hxx" class DebuggerParser { @@ -97,7 +98,7 @@ class DebuggerParser std::array parms; std::function executor; }; - static std::array commands; + static std::array commands; struct Trap { @@ -140,9 +141,13 @@ class DebuggerParser // output the error with the example provided for the command void outputCommandError(const string& errorMsg, int command); + void executeDirective(Device::AccessType type); + // List of available command methods void executeA(); + void executeAud(); void executeBase(); + void executeBCol(); void executeBreak(); void executeBreakif(); void executeBreaklabel(); @@ -155,6 +160,7 @@ class DebuggerParser void executeClearwatches(); void executeCls(); void executeCode(); + void executeCol(); void executeColortest(); void executeD(); void executeData(); @@ -195,6 +201,7 @@ class DebuggerParser void executeN(); void executePalette(); void executePc(); + void executePCol(); void executePGfx(); void executePrint(); void executeRam(); @@ -208,6 +215,7 @@ class DebuggerParser void executeRunToPc(); void executeS(); void executeSave(); + void executeSaveAccess(); void executeSaveallstates(); void executeSaveconfig(); void executeSavedisassembly(); diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index 9ee79c61e..c77d1eabf 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -17,6 +17,7 @@ #include "bspf.hxx" #include "Debugger.hxx" +#include "Device.hxx" #include "DiStella.hxx" using Common::Base; @@ -73,7 +74,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, // Add reserved line equates ostringstream reservedLabel; for (int k = 0; k <= myAppData.end; k++) { - if ((myLabels[k] & (CartDebug::REFERENCED | CartDebug::VALID_ENTRY)) == CartDebug::REFERENCED) { + if ((myLabels[k] & (Device::REFERENCED | Device::VALID_ENTRY)) == Device::REFERENCED) { // If we have a piece of code referenced somewhere else, but cannot // locate the label in code (i.e because the address is inside of a // multi-byte instruction, then we make note of that address for reference @@ -107,70 +108,99 @@ void DiStella::disasm(uInt32 distart, int pass) uInt16 ad; Int32 cycles = 0; AddressingMode addrMode; - int labelFound = 0; + AddressType labelFound = AddressType::INVALID; stringstream nextLine, nextLineBytes; - mySegType = CartDebug::NONE; // create extra lines between code and data + mySegType = Device::NONE; // create extra lines between code and data myDisasmBuf.str(""); /* pc=myAppData.start; */ myPC = distart - myOffset; - while (myPC <= myAppData.end) { - + while(myPC <= myAppData.end) + { // since -1 is used in m6502.m4 for clearing the last peek // and this results into an access at e.g. 0xffff, // we have to fix the consequences here (ugly!). if(myPC == myAppData.end) goto FIX_LAST; - if (checkBits(myPC, CartDebug::GFX | CartDebug::PGFX, - CartDebug::CODE)) { - if (pass == 2) - mark(myPC + myOffset, CartDebug::VALID_ENTRY); - if (pass == 3) + if(checkBits(myPC, Device::GFX | Device::PGFX, + Device::CODE)) + { + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); + if(pass == 3) outputGraphics(); ++myPC; - } else if (checkBits(myPC, CartDebug::DATA, - CartDebug::CODE | CartDebug::GFX | CartDebug::PGFX)) { - if (pass == 2) - mark(myPC + myOffset, CartDebug::VALID_ENTRY); - if (pass == 3) - outputBytes(CartDebug::DATA); + } + else if(checkBits(myPC, Device::COL | Device::PCOL | Device::BCOL, + Device::CODE | Device::GFX | Device::PGFX)) + { + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); + if(pass == 3) + outputColors(); + ++myPC; + } + else if(checkBits(myPC, Device::AUD, + Device::CODE | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL)) + { + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); + if(pass == 3) + outputBytes(Device::AUD); else ++myPC; - } else if (checkBits(myPC, CartDebug::ROW, - CartDebug::CODE | CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX)) { -FIX_LAST: - if (pass == 2) - mark(myPC + myOffset, CartDebug::VALID_ENTRY); - - if (pass == 3) - outputBytes(CartDebug::ROW); + } + else if(checkBits(myPC, Device::DATA, + Device::CODE | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | + Device::AUD)) + { + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); + if(pass == 3) + outputBytes(Device::DATA); else ++myPC; - } else { - // The following sections must be CODE + } + else if(checkBits(myPC, Device::ROW, + Device::CODE | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | + Device::AUD | Device::DATA)) { + FIX_LAST: + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); - // add extra spacing line when switching from non-code to code - if (pass == 3 && mySegType != CartDebug::CODE && mySegType != CartDebug::NONE) { + if(pass == 3) + outputBytes(Device::ROW); + else + ++myPC; + } + else { + // The following sections must be CODE + + // add extra spacing line when switching from non-code to code + if(pass == 3 && mySegType != Device::CODE && mySegType != Device::NONE) { myDisasmBuf << " ' ' "; - addEntry(CartDebug::NONE); - mark(myPC + myOffset, CartDebug::REFERENCED); // add label when switching + addEntry(Device::NONE); + mark(myPC + myOffset, Device::REFERENCED); // add label when switching } - mySegType = CartDebug::CODE; + mySegType = Device::CODE; /* version 2.1 bug fix */ - if (pass == 2) - mark(myPC + myOffset, CartDebug::VALID_ENTRY); + if(pass == 2) + mark(myPC + myOffset, Device::VALID_ENTRY); // get opcode opcode = Debugger::debugger().peek(myPC + myOffset); // get address mode for opcode addrMode = ourLookup[opcode].addr_mode; - if (pass == 3) { - if (checkBit(myPC, CartDebug::REFERENCED)) + if(pass == 3) { + if(checkBit(myPC, Device::REFERENCED)) myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'"; else myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '"; @@ -178,17 +208,17 @@ FIX_LAST: ++myPC; // detect labels inside instructions (e.g. BIT masks) - labelFound = false; - for (Uint8 i = 0; i < ourLookup[opcode].bytes - 1; i++) { - if (checkBit(myPC + i, CartDebug::REFERENCED)) { - labelFound = true; + labelFound = AddressType::INVALID; + for(Uint8 i = 0; i < ourLookup[opcode].bytes - 1; i++) { + if(checkBit(myPC + i, Device::REFERENCED)) { + labelFound = AddressType::ROM; break; } } - if (labelFound) { - if (myOffset >= 0x1000) { + if(labelFound != AddressType::INVALID) { + if(myOffset >= 0x1000) { // the opcode's operand address matches a label address - if (pass == 3) { + if(pass == 3) { // output the byte of the opcode incl. cycles Uint8 nextOpcode = Debugger::debugger().peek(myPC + myOffset); @@ -203,12 +233,13 @@ FIX_LAST: nextLine.str(""); cycles = 0; - addEntry(CartDebug::CODE); // add the new found CODE entry + addEntry(Device::CODE); // add the new found CODE entry } // continue with the label's opcode continue; - } else { - if (pass == 3) { + } + else { + if(pass == 3) { // TODO } } @@ -216,18 +247,18 @@ FIX_LAST: // Undefined opcodes start with a '.' // These are undefined wrt DASM - if (ourLookup[opcode].mnemonic[0] == '.' && pass == 3) { + if(ourLookup[opcode].mnemonic[0] == '.' && pass == 3) { nextLine << ".byte $" << Base::HEX2 << int(opcode) << " ;"; } - if (pass == 3) { + if(pass == 3) { nextLine << ourLookup[opcode].mnemonic; nextLineBytes << Base::HEX2 << int(opcode) << " "; } // Add operand(s) for PC values outside the app data range - if (myPC >= myAppData.end) { - switch (addrMode) { + if(myPC >= myAppData.end) { + switch(addrMode) { case AddressingMode::ABSOLUTE: case AddressingMode::ABSOLUTE_X: case AddressingMode::ABSOLUTE_Y: @@ -235,17 +266,17 @@ FIX_LAST: case AddressingMode::INDIRECT_Y: case AddressingMode::ABS_INDIRECT: { - if (pass == 3) { + if(pass == 3) { /* Line information is already printed; append .byte since last instruction will put recompilable object larger that original binary file */ myDisasmBuf << ".byte $" << Base::HEX2 << int(opcode) << " $" << Base::HEX4 << myPC + myOffset << "'" << Base::HEX2 << int(opcode); - addEntry(CartDebug::DATA); + addEntry(Device::DATA); - if (myPC == myAppData.end) { - if (checkBit(myPC, CartDebug::REFERENCED)) + if(myPC == myAppData.end) { + if(checkBit(myPC, Device::REFERENCED)) myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'"; else myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '"; @@ -254,7 +285,7 @@ FIX_LAST: myDisasmBuf << ".byte $" << Base::HEX2 << int(opcode) << " $" << Base::HEX4 << myPC + myOffset << "'" << Base::HEX2 << int(opcode); - addEntry(CartDebug::DATA); + addEntry(Device::DATA); } } myPCEnd = myAppData.end + myOffset; @@ -267,11 +298,11 @@ FIX_LAST: case AddressingMode::ZERO_PAGE_Y: case AddressingMode::RELATIVE: { - if (pass == 3) { + if(pass == 3) { /* Line information is already printed, but we can remove the Instruction (i.e. BMI) by simply clearing the buffer to print */ myDisasmBuf << ".byte $" << Base::HEX2 << int(opcode); - addEntry(CartDebug::ROW); + addEntry(Device::ROW); nextLine.str(""); nextLineBytes.str(""); } @@ -288,10 +319,10 @@ FIX_LAST: // Add operand(s) ad = d1 = 0; // not WSYNC by default! /* Version 2.1 added the extensions to mnemonics */ - switch (addrMode) { + switch(addrMode) { case AddressingMode::ACCUMULATOR: { - if (pass == 3 && mySettings.aFlag) + if(pass == 3 && mySettings.aFlag) nextLine << " A"; break; } @@ -299,26 +330,29 @@ FIX_LAST: case AddressingMode::ABSOLUTE: { ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - labelFound = mark(ad, CartDebug::REFERENCED); - if (pass == 3) { - if (ad < 0x100 && mySettings.fFlag) + labelFound = mark(ad, Device::REFERENCED); + if(pass == 3) { + if(ad < 0x100 && mySettings.fFlag) nextLine << ".w "; else nextLine << " "; - if (labelFound == 1) { + if(labelFound == AddressType::ROM) { LABEL_A12_HIGH(ad); nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); - } else if (labelFound == 4) { - if (mySettings.rFlag) { + } + else if(labelFound == AddressType::ROM_MIRROR) { + if(mySettings.rFlag) { int tmp = (ad & myAppData.end) + myOffset; LABEL_A12_HIGH(tmp); nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8); - } else { + } + else { nextLine << "$" << Base::HEX4 << ad; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); } - } else { + } + else { LABEL_A12_LOW(ad); nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); } @@ -329,8 +363,8 @@ FIX_LAST: case AddressingMode::ZERO_PAGE: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - labelFound = mark(d1, CartDebug::REFERENCED); - if (pass == 3) { + labelFound = mark(d1, Device::REFERENCED); + if(pass == 3) { nextLine << " "; LABEL_A12_LOW(int(d1)); nextLineBytes << Base::HEX2 << int(d1); @@ -341,7 +375,7 @@ FIX_LAST: case AddressingMode::IMMEDIATE: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - if (pass == 3) { + if(pass == 3) { nextLine << " #$" << Base::HEX2 << int(d1) << " "; nextLineBytes << Base::HEX2 << int(d1); } @@ -351,34 +385,38 @@ FIX_LAST: case AddressingMode::ABSOLUTE_X: { ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - labelFound = mark(ad, CartDebug::REFERENCED); - if (pass == 2 && !checkBit(ad & myAppData.end, CartDebug::CODE)) { + labelFound = mark(ad, Device::REFERENCED); + if(pass == 2 && !checkBit(ad & myAppData.end, Device::CODE)) { // Since we can't know what address is being accessed unless we also // know the current X value, this is marked as ROW instead of DATA // The processing is left here, however, in case future versions of // the code can somehow track access to CPU registers - mark(ad, CartDebug::ROW); - } else if (pass == 3) { - if (ad < 0x100 && mySettings.fFlag) + mark(ad, Device::ROW); + } + else if(pass == 3) { + if(ad < 0x100 && mySettings.fFlag) nextLine << ".wx "; else nextLine << " "; - if (labelFound == 1) { + if(labelFound == AddressType::ROM) { LABEL_A12_HIGH(ad); nextLine << ",x"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); - } else if (labelFound == 4) { - if (mySettings.rFlag) { + } + else if(labelFound == AddressType::ROM_MIRROR) { + if(mySettings.rFlag) { int tmp = (ad & myAppData.end) + myOffset; LABEL_A12_HIGH(tmp); nextLine << ",x"; nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8); - } else { + } + else { nextLine << "$" << Base::HEX4 << ad << ",x"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); } - } else { + } + else { LABEL_A12_LOW(ad); nextLine << ",x"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); @@ -390,34 +428,38 @@ FIX_LAST: case AddressingMode::ABSOLUTE_Y: { ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - labelFound = mark(ad, CartDebug::REFERENCED); - if (pass == 2 && !checkBit(ad & myAppData.end, CartDebug::CODE)) { + labelFound = mark(ad, Device::REFERENCED); + if(pass == 2 && !checkBit(ad & myAppData.end, Device::CODE)) { // Since we can't know what address is being accessed unless we also // know the current Y value, this is marked as ROW instead of DATA // The processing is left here, however, in case future versions of // the code can somehow track access to CPU registers - mark(ad, CartDebug::ROW); - } else if (pass == 3) { - if (ad < 0x100 && mySettings.fFlag) + mark(ad, Device::ROW); + } + else if(pass == 3) { + if(ad < 0x100 && mySettings.fFlag) nextLine << ".wy "; else nextLine << " "; - if (labelFound == 1) { + if(labelFound == AddressType::ROM) { LABEL_A12_HIGH(ad); nextLine << ",y"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); - } else if (labelFound == 4) { - if (mySettings.rFlag) { + } + else if(labelFound == AddressType::ROM_MIRROR) { + if(mySettings.rFlag) { int tmp = (ad & myAppData.end) + myOffset; LABEL_A12_HIGH(tmp); nextLine << ",y"; nextLineBytes << Base::HEX2 << int(tmp & 0xff) << " " << Base::HEX2 << int(tmp >> 8); - } else { + } + else { nextLine << "$" << Base::HEX4 << ad << ",y"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); } - } else { + } + else { LABEL_A12_LOW(ad); nextLine << ",y"; nextLineBytes << Base::HEX2 << int(ad & 0xff) << " " << Base::HEX2 << int(ad >> 8); @@ -429,7 +471,7 @@ FIX_LAST: case AddressingMode::INDIRECT_X: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - if (pass == 3) { + if(pass == 3) { labelFound = mark(d1, 0); // dummy call to get address type nextLine << " ("; LABEL_A12_LOW(d1); @@ -442,7 +484,7 @@ FIX_LAST: case AddressingMode::INDIRECT_Y: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - if (pass == 3) { + if(pass == 3) { labelFound = mark(d1, 0); // dummy call to get address type nextLine << " ("; LABEL_A12_LOW(d1); @@ -455,8 +497,8 @@ FIX_LAST: case AddressingMode::ZERO_PAGE_X: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - labelFound = mark(d1, CartDebug::REFERENCED); - if (pass == 3) { + labelFound = mark(d1, Device::REFERENCED); + if(pass == 3) { nextLine << " "; LABEL_A12_LOW(d1); nextLine << ",x"; @@ -468,8 +510,8 @@ FIX_LAST: case AddressingMode::ZERO_PAGE_Y: { d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - labelFound = mark(d1, CartDebug::REFERENCED); - if (pass == 3) { + labelFound = mark(d1, Device::REFERENCED); + if(pass == 3) { nextLine << " "; LABEL_A12_LOW(d1); nextLine << ",y"; @@ -486,12 +528,13 @@ FIX_LAST: d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; ad = ((myPC + Int8(d1)) & 0xfff) + myOffset; - labelFound = mark(ad, CartDebug::REFERENCED); - if (pass == 3) { - if (labelFound == 1) { + labelFound = mark(ad, Device::REFERENCED); + if(pass == 3) { + if(labelFound == AddressType::ROM) { nextLine << " "; LABEL_A12_HIGH(ad); - } else + } + else nextLine << " $" << Base::HEX4 << ad; nextLineBytes << Base::HEX2 << int(d1); @@ -502,25 +545,36 @@ FIX_LAST: case AddressingMode::ABS_INDIRECT: { ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - labelFound = mark(ad, CartDebug::REFERENCED); - if (pass == 2 && !checkBit(ad & myAppData.end, CartDebug::CODE)) { + labelFound = mark(ad, Device::REFERENCED); + if(pass == 2 && !checkBit(ad & myAppData.end, Device::CODE)) { // Since we can't know what address is being accessed unless we also // know the current X value, this is marked as ROW instead of DATA // The processing is left here, however, in case future versions of // the code can somehow track access to CPU registers - mark(ad, CartDebug::ROW); - } else if (pass == 3) { - if (ad < 0x100 && mySettings.fFlag) + mark(ad, Device::ROW); + } + else if(pass == 3) { + if(ad < 0x100 && mySettings.fFlag) nextLine << ".ind "; else nextLine << " "; } - if (labelFound == 1) { + if(labelFound == AddressType::ROM) { nextLine << "("; LABEL_A12_HIGH(ad); nextLine << ")"; } - // TODO - should we consider case 4?? + else if(labelFound == AddressType::ROM_MIRROR) { + nextLine << "("; + if(mySettings.rFlag) { + int tmp = (ad & myAppData.end) + myOffset; + LABEL_A12_HIGH(tmp); + } + else { + LABEL_A12_LOW(ad); + } + nextLine << ")"; + } else { nextLine << "("; LABEL_A12_LOW(ad); @@ -535,36 +589,37 @@ FIX_LAST: break; } // end switch - if (pass == 3) { + if(pass == 3) { cycles += int(ourLookup[opcode].cycles); // A complete line of disassembly (text, cycle count, and bytes) myDisasmBuf << nextLine.str() << "'" << ";" << std::dec << int(ourLookup[opcode].cycles) << (addrMode == AddressingMode::RELATIVE ? (ad & 0xf00) != ((myPC + myOffset) & 0xf00) ? "/3!" : "/3 " : " "); - if ((opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00 // code block end - || checkBit(myPC, CartDebug::REFERENCED) // referenced address - || (ourLookup[opcode].rw_mode == RWMode::WRITE && d1 == WSYNC)) // strobe WSYNC - && cycles > 0) { - // output cycles for previous code block + if((opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00 // code block end + || checkBit(myPC, Device::REFERENCED) // referenced address + || (ourLookup[opcode].rw_mode == RWMode::WRITE && d1 == WSYNC)) // strobe WSYNC + && cycles > 0) { + // output cycles for previous code block myDisasmBuf << "'= " << std::setw(3) << std::setfill(' ') << std::dec << cycles; cycles = 0; - } else { + } + else { myDisasmBuf << "' "; } myDisasmBuf << "'" << nextLineBytes.str(); - addEntry(CartDebug::CODE); - if (opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00) { + addEntry(Device::CODE); + if(opcode == 0x40 || opcode == 0x60 || opcode == 0x4c || opcode == 0x00) { myDisasmBuf << " ' ' "; - addEntry(CartDebug::NONE); - mySegType = CartDebug::NONE; // prevent extra lines if data follows + addEntry(Device::NONE); + mySegType = Device::NONE; // prevent extra lines if data follows } nextLine.str(""); nextLineBytes.str(""); } - } - } /* while loop */ + } // CODE + } /* while loop */ /* Just in case we are disassembling outside of the address range, force the myPCEnd to EOF */ myPCEnd = myAppData.end + myOffset; @@ -602,20 +657,21 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses) // Note that this is a 'best-effort' approach, since // Distella will normally keep going until the end of the // range or branch is encountered - // However, addresses *specifically* marked as DATA/GFX/PGFX + // However, addresses *specifically* marked as DATA/GFX/PGFX/COL/PCOL/BCOL/AUD // in the emulation core indicate that the CODE range has finished // Therefore, we stop at the first such address encountered for (uInt32 k = pcBeg; k <= myPCEnd; ++k) { - if (checkBits(k, CartDebug::CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX, - CartDebug::CODE)) { + if (checkBits(k, Device::Device::DATA | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | Device::AUD, + Device::CODE)) { //if (Debugger::debugger().getAccessFlags(k) & - // (CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX)) { + // (Device::DATA | Device::GFX | Device::PGFX)) { // TODO: this should never happen, remove when we are sure - // TODO: NOT USED: uInt8 flags = Debugger::debugger().getAccessFlags(k); + // TODO: NOT USED: uInt16 flags = Debugger::debugger().getAccessFlags(k); myPCEnd = k - 1; break; } - mark(k, CartDebug::CODE); + mark(k, Device::CODE); } } @@ -637,7 +693,7 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses) while (myAddressQueue.empty() && it != debuggerAddresses.end()) { uInt16 addr = *it; - if (!checkBit(addr - myOffset, CartDebug::CODE)) { + if (!checkBit(addr - myOffset, Device::CODE)) { myAddressQueue.push(addr); ++it; } else // remove this address, it is redundant @@ -647,8 +703,8 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses) // Stella itself can provide hints on whether an address has ever // been referenced as CODE while (myAddressQueue.empty() && codeAccessPoint <= myAppData.end) { - if ((Debugger::debugger().getAccessFlags(codeAccessPoint + myOffset) & CartDebug::CODE) - && !(myLabels[codeAccessPoint & myAppData.end] & CartDebug::CODE)) { + if ((Debugger::debugger().getAccessFlags(codeAccessPoint + myOffset) & Device::CODE) + && !(myLabels[codeAccessPoint & myAppData.end] & Device::CODE)) { myAddressQueue.push(codeAccessPoint + myOffset); ++codeAccessPoint; break; @@ -660,16 +716,17 @@ void DiStella::disasmPass1(CartDebug::AddressList& debuggerAddresses) for (int k = 0; k <= myAppData.end; k++) { // Let the emulation core know about tentative code - if (checkBit(k, CartDebug::CODE) && - !(Debugger::debugger().getAccessFlags(k + myOffset) & CartDebug::CODE) + if (checkBit(k, Device::CODE) && + !(Debugger::debugger().getAccessFlags(k + myOffset) & Device::CODE) && myOffset != 0) { - Debugger::debugger().setAccessFlags(k + myOffset, CartDebug::TCODE); + Debugger::debugger().setAccessFlags(k + myOffset, Device::TCODE); } // Must be ROW / unused bytes - if (!checkBit(k, CartDebug::CODE | CartDebug::GFX | - CartDebug::PGFX | CartDebug::DATA)) - mark(k + myOffset, CartDebug::ROW); + if (!checkBit(k, Device::CODE | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | Device::AUD | + Device::DATA)) + mark(k + myOffset, Device::ROW); } } @@ -685,7 +742,9 @@ void DiStella::disasmFromAddress(uInt32 distart) while (myPC <= myAppData.end) { // abort when we reach non-code areas - if (checkBits(myPC, CartDebug::CartDebug::DATA | CartDebug::GFX | CartDebug::PGFX, CartDebug::CODE)) { + if (checkBits(myPC, Device::Device::DATA | Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | Device::AUD, + Device::CODE)) { myPCEnd = (myPC - 1) + myOffset; return; } @@ -729,22 +788,22 @@ void DiStella::disasmFromAddress(uInt32 distart) switch (addrMode) { case AddressingMode::ABSOLUTE: ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - mark(ad, CartDebug::REFERENCED); + mark(ad, Device::REFERENCED); // handle JMP/JSR if (ourLookup[opcode].source == AccessMode::ADDR) { // do NOT use flags set by debugger, else known CODE will not analyzed statically. - if (!checkBit(ad & myAppData.end, CartDebug::CODE, false)) { + if (!checkBit(ad & myAppData.end, Device::CODE, false)) { if (ad > 0xfff) myAddressQueue.push((ad & myAppData.end) + myOffset); - mark(ad, CartDebug::CODE); + mark(ad, Device::CODE); } } else - mark(ad, CartDebug::DATA); + mark(ad, Device::DATA); break; case AddressingMode::ZERO_PAGE: d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - mark(d1, CartDebug::REFERENCED); + mark(d1, Device::REFERENCED); break; case AddressingMode::IMMEDIATE: @@ -753,12 +812,12 @@ void DiStella::disasmFromAddress(uInt32 distart) case AddressingMode::ABSOLUTE_X: ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - mark(ad, CartDebug::REFERENCED); + mark(ad, Device::REFERENCED); break; case AddressingMode::ABSOLUTE_Y: ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - mark(ad, CartDebug::REFERENCED); + mark(ad, Device::REFERENCED); break; case AddressingMode::INDIRECT_X: @@ -771,12 +830,12 @@ void DiStella::disasmFromAddress(uInt32 distart) case AddressingMode::ZERO_PAGE_X: d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - mark(d1, CartDebug::REFERENCED); + mark(d1, Device::REFERENCED); break; case AddressingMode::ZERO_PAGE_Y: d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; - mark(d1, CartDebug::REFERENCED); + mark(d1, Device::REFERENCED); break; case AddressingMode::RELATIVE: @@ -785,17 +844,17 @@ void DiStella::disasmFromAddress(uInt32 distart) // indexing into the labels array caused a crash d1 = Debugger::debugger().peek(myPC + myOffset); ++myPC; ad = ((myPC + Int8(d1)) & 0xfff) + myOffset; - mark(ad, CartDebug::REFERENCED); + mark(ad, Device::REFERENCED); // do NOT use flags set by debugger, else known CODE will not analyzed statically. - if (!checkBit(ad - myOffset, CartDebug::CODE, false)) { + if (!checkBit(ad - myOffset, Device::CODE, false)) { myAddressQueue.push(ad); - mark(ad, CartDebug::CODE); + mark(ad, Device::CODE); } break; case AddressingMode::ABS_INDIRECT: ad = Debugger::debugger().dpeek(myPC + myOffset); myPC += 2; - mark(ad, CartDebug::REFERENCED); + mark(ad, Device::REFERENCED); break; default: @@ -804,10 +863,10 @@ void DiStella::disasmFromAddress(uInt32 distart) // mark BRK vector if (opcode == 0x00) { - ad = Debugger::debugger().dpeek(0xfffe, CartDebug::DATA); + ad = Debugger::debugger().dpeek(0xfffe, Device::DATA); if (!myReserved.breakFound) { myAddressQueue.push(ad); - mark(ad, CartDebug::CODE); + mark(ad, Device::CODE); myReserved.breakFound = true; } } @@ -823,7 +882,7 @@ void DiStella::disasmFromAddress(uInt32 distart) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int DiStella::mark(uInt32 address, uInt8 mask, bool directive) +DiStella::AddressType DiStella::mark(uInt32 address, uInt16 mask, bool directive) { /*----------------------------------------------------------------------- For any given offset and code range... @@ -831,81 +890,88 @@ int DiStella::mark(uInt32 address, uInt8 mask, bool directive) If we're between the offset and the end of the code range, we mark the bit in the labels array for that data. The labels array is an array of label info for each code address. If this is the case, - return "1", else... + return "ROM", else... We sweep for hardware/system equates, which are valid addresses, outside the scope of the code/data range. For these, we mark its - corresponding hardware/system array element, and return "2" or "3" + corresponding hardware/system array element, and return "TIA" or "RIOT" (depending on which system/hardware element was accessed). If this was not the case... Next we check if it is a code "mirror". For the 2600, address ranges are limited with 13 bits, so other addresses can exist outside of the standard code/data range. For these, we mark the element in the "labels" - array that corresponds to the mirrored address, and return "4" + array that corresponds to the mirrored address, and return "ROM_MIRROR" - If all else fails, it's not a valid address, so return 0. + If all else fails, it's not a valid address, so return INVALID. A quick example breakdown for a 2600 4K cart: =========================================================== - $00-$3d = system equates (WSYNC, etc...); return 2. - $80-$ff = zero-page RAM (ram_80, etc...); return 5. + $00-$3d = system equates (WSYNC, etc...); return TIA. + $80-$ff = zero-page RAM (ram_80, etc...); return ZP_RAM. $0280-$0297 = system equates (INPT0, etc...); mark the array's element - with the appropriate bit; return 3. + with the appropriate bit; return RIOT. $1000-$1FFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $3000-$3FFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $5000-$5FFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $7000-$7FFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $9000-$9FFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $B000-$BFFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $D000-$DFFF = mark the code/data array for the mirrored address - with the appropriate bit; return 4. + with the appropriate bit; return ROM_MIRROR. $F000-$FFFF = mark the code/data array for the address - with the appropriate bit; return 1. - Anything else = invalid, return 0. + with the appropriate bit; return ROM. + Anything else = invalid, return INVALID. =========================================================== -----------------------------------------------------------------------*/ // Check for equates before ROM/ZP-RAM accesses, because the original logic // of Distella assumed either equates or ROM; it didn't take ZP-RAM into account CartDebug::AddrType type = myDbg.addressType(address); - if (type == CartDebug::AddrType::TIA) { - return 2; - } else if (type == CartDebug::AddrType::IO) { - return 3; - } else if (type == CartDebug::AddrType::ZPRAM && myOffset != 0) { - return 5; - } else if (address >= uInt32(myOffset) && address <= uInt32(myAppData.end + myOffset)) { + if(type == CartDebug::AddrType::TIA) { + return AddressType::TIA; + } + else if(type == CartDebug::AddrType::IO) { + return AddressType::RIOT; + } + else if(type == CartDebug::AddrType::ZPRAM && myOffset != 0) { + return AddressType::ZP_RAM; + } + else if(address >= uInt32(myOffset) && address <= uInt32(myAppData.end + myOffset)) { myLabels[address - myOffset] = myLabels[address - myOffset] | mask; - if (directive) myDirectives[address - myOffset] = mask; - return 1; - } else if (address > 0x1000 && myOffset != 0) // Exclude zero-page accesses + if(directive) + myDirectives[address - myOffset] = mask; + return AddressType::ROM; + } + else if(address > 0x1000 && myOffset != 0) // Exclude zero-page accesses { /* 2K & 4K case */ myLabels[address & myAppData.end] = myLabels[address & myAppData.end] | mask; - if (directive) myDirectives[address & myAppData.end] = mask; - return 4; - } else - return 0; + if(directive) + myDirectives[address & myAppData.end] = mask; + return AddressType::ROM_MIRROR; + } + else + return AddressType::INVALID; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool DiStella::checkBit(uInt16 address, uInt8 mask, bool useDebugger) const +bool DiStella::checkBit(uInt16 address, uInt16 mask, bool useDebugger) const { // The REFERENCED and VALID_ENTRY flags are needed for any inspection of // an address // Since they're set only in the labels array (as the lower two bits), // they must be included in the other bitfields - uInt8 label = myLabels[address & myAppData.end], - lastbits = label & 0x03, - directive = myDirectives[address & myAppData.end] & 0xFC, - debugger = Debugger::debugger().getAccessFlags(address | myOffset) & 0xFC; + uInt16 label = myLabels[address & myAppData.end], + lastbits = label & (Device::REFERENCED | Device::VALID_ENTRY), + directive = myDirectives[address & myAppData.end] & ~(Device::REFERENCED | Device::VALID_ENTRY), + debugger = Debugger::debugger().getAccessFlags(address | myOffset) & ~(Device::REFERENCED | Device::VALID_ENTRY); // Any address marked by a manual directive always takes priority if (directive) @@ -918,7 +984,8 @@ bool DiStella::checkBit(uInt16 address, uInt8 mask, bool useDebugger) const return label & mask; } -bool DiStella::checkBits(uInt16 address, uInt8 mask, uInt8 notMask, bool useDebugger) const +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool DiStella::checkBits(uInt16 address, uInt16 mask, uInt16 notMask, bool useDebugger) const { return checkBit(address, mask, useDebugger) && !checkBit(address, notMask, useDebugger); } @@ -943,7 +1010,7 @@ bool DiStella::check_range(uInt16 beg, uInt16 end) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DiStella::addEntry(CartDebug::DisasmType type) +void DiStella::addEntry(Device::AccessType type) { CartDebug::DisassemblyTag tag; @@ -969,7 +1036,7 @@ void DiStella::addEntry(CartDebug::DisasmType type) if (tag.label == EmptyString) { if (myDisasmBuf.peek() != ' ') getline(myDisasmBuf, tag.label, '\''); - else if (mySettings.showAddresses && tag.type == CartDebug::CODE) { + else if (mySettings.showAddresses && tag.type == Device::CODE) { // Have addresses indented, to differentiate from actual labels tag.label = " " + Base::toString(tag.address, Base::Fmt::_16_4); tag.hllabel = false; @@ -982,7 +1049,7 @@ void DiStella::addEntry(CartDebug::DisasmType type) // variable length labels, cycle counts, etc myDisasmBuf.seekg(11, std::ios::beg); switch (tag.type) { - case CartDebug::CODE: + case Device::CODE: getline(myDisasmBuf, tag.disasm, '\''); getline(myDisasmBuf, tag.ccount, '\''); getline(myDisasmBuf, tag.ctotal, '\''); @@ -993,25 +1060,29 @@ void DiStella::addEntry(CartDebug::DisasmType type) // but it could also indicate that code will *never* be accessed // Since it is impossible to tell the difference, marking the address // in the disassembly at least tells the user about it - if (!(Debugger::debugger().getAccessFlags(tag.address) & CartDebug::CODE) + if (!(Debugger::debugger().getAccessFlags(tag.address) & Device::CODE) && myOffset != 0) { tag.ccount += " *"; - Debugger::debugger().setAccessFlags(tag.address, CartDebug::TCODE); + Debugger::debugger().setAccessFlags(tag.address, Device::TCODE); } break; - case CartDebug::GFX: - case CartDebug::PGFX: + + case Device::GFX: + case Device::PGFX: + case Device::COL: + case Device::PCOL: + case Device::BCOL: + case Device::DATA: + case Device::AUD: getline(myDisasmBuf, tag.disasm, '\''); getline(myDisasmBuf, tag.bytes); break; - case CartDebug::DATA: - getline(myDisasmBuf, tag.disasm, '\''); - getline(myDisasmBuf, tag.bytes); - break; - case CartDebug::ROW: + + case Device::ROW: getline(myDisasmBuf, tag.disasm); break; - case CartDebug::NONE: + + case Device::NONE: default: // should never happen tag.disasm = " "; break; @@ -1026,47 +1097,115 @@ DONE_WITH_ADD: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DiStella::outputGraphics() { - bool isPGfx = checkBit(myPC, CartDebug::PGFX); + bool isPGfx = checkBit(myPC, Device::PGFX); const string& bitString = isPGfx ? "\x1f" : "\x1e"; uInt8 byte = Debugger::debugger().peek(myPC + myOffset); // add extra spacing line when switching from non-graphics to graphics - if (mySegType != CartDebug::GFX && mySegType != CartDebug::NONE) { + if (mySegType != Device::GFX && mySegType != Device::NONE) { myDisasmBuf << " ' ' "; - addEntry(CartDebug::NONE); + addEntry(Device::NONE); } - mySegType = CartDebug::GFX; + mySegType = Device::GFX; - if (checkBit(myPC, CartDebug::REFERENCED)) + if (checkBit(myPC, Device::REFERENCED)) myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'"; else myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '"; myDisasmBuf << ".byte $" << Base::HEX2 << int(byte) << " |"; for (uInt8 i = 0, c = byte; i < 8; ++i, c <<= 1) myDisasmBuf << ((c > 127) ? bitString : " "); - myDisasmBuf << "| $" << Base::HEX4 << myPC + myOffset << "'"; + myDisasmBuf << "| $" << Base::HEX4 << myPC + myOffset << "'"; if (mySettings.gfxFormat == Base::Fmt::_2) myDisasmBuf << Base::toString(byte, Base::Fmt::_2_8); else myDisasmBuf << Base::HEX2 << int(byte); - addEntry(isPGfx ? CartDebug::PGFX : CartDebug::GFX); + addEntry(isPGfx ? Device::PGFX : Device::GFX); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DiStella::outputBytes(CartDebug::DisasmType type) +void DiStella::outputColors() +{ + string NTSC_COLOR[16] = { + "BLACK", "YELLOW", "BROWN", "ORANGE", + "RED", "MAUVE", "VIOLET", "PURPLE", + "BLUE", "BLUE_CYAN", "CYAN", "CYAN_GREEN", + "GREEN", "GREEN_YELLOW", "GREEN_BEIGE", "BEIGE" + }; + string PAL_COLOR[16] = { + "BLACK0", "BLACK1", "YELLOW", "GREEN_YELLOW", + "ORANGE", "GREEN", "RED", "CYAN_GREEN", + "MAUVE", "CYAN", "VIOLET", "BLUE_CYAN", + "PURPLE", "BLUE", "BLACKE", "BLACKF" + }; + string SECAM_COLOR[8] = { + "BLACK", "BLUE", "RED", "PURPLE", + "GREEN", "CYAN", "YELLOW", "WHITE" + }; + + uInt8 byte = Debugger::debugger().peek(myPC + myOffset); + + // add extra spacing line when switching from non-colors to colors + if(mySegType != Device::COL && mySegType != Device::NONE) + { + myDisasmBuf << " ' ' "; + addEntry(Device::NONE); + } + mySegType = Device::COL; + + // output label/address + if(checkBit(myPC, Device::REFERENCED)) + myDisasmBuf << Base::HEX4 << myPC + myOffset << "'L" << Base::HEX4 << myPC + myOffset << "'"; + else + myDisasmBuf << Base::HEX4 << myPC + myOffset << "' '"; + + // output color + string color; + + myDisasmBuf << ".byte "; + if(myDbg.myConsole.timing() == ConsoleTiming::ntsc) + { + color = NTSC_COLOR[byte >> 4]; + myDisasmBuf << color << "|$" << Base::HEX1 << (byte & 0xf); + } + else if(myDbg.myConsole.timing() == ConsoleTiming::pal) + { + color = PAL_COLOR[byte >> 4]; + myDisasmBuf << color << "|$" << Base::HEX1 << (byte & 0xf); + } + else + { + color = SECAM_COLOR[(byte >> 1) & 0x7]; + myDisasmBuf << "$" << Base::HEX1 << (byte >> 4) << "|" << color; + } + myDisasmBuf << std::setw(int(16 - color.length())) << std::setfill(' '); + + // output address + myDisasmBuf << "; $" << Base::HEX4 << myPC + myOffset << " " + << (checkBit(myPC, Device::COL) ? "(Px)" : checkBit(myPC, Device::PCOL) ? "(PF)" : "(BK)"); + + // output color value + myDisasmBuf << "'" << Base::HEX2 << int(byte); + + addEntry(checkBit(myPC, Device::COL) ? Device::COL : + checkBit(myPC, Device::PCOL) ? Device::PCOL : Device::BCOL); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DiStella::outputBytes(Device::AccessType type) { bool isType = true; - bool referenced = checkBit(myPC, CartDebug::REFERENCED); + bool referenced = checkBit(myPC, Device::REFERENCED); bool lineEmpty = true; int numBytes = 0; // add extra spacing line when switching from non-data to data - if (mySegType != CartDebug::DATA && mySegType != CartDebug::NONE) { + if (mySegType != Device::DATA && mySegType != Device::NONE) { myDisasmBuf << " ' ' "; - addEntry(CartDebug::NONE); + addEntry(Device::NONE); } - mySegType = CartDebug::DATA; + mySegType = Device::DATA; while (isType && myPC <= myAppData.end) { if (referenced) { @@ -1097,13 +1236,15 @@ void DiStella::outputBytes(CartDebug::DisasmType type) ++myPC; } isType = checkBits(myPC, type, - CartDebug::CODE | (type != CartDebug::DATA ? CartDebug::DATA : 0) | CartDebug::GFX | CartDebug::PGFX); - referenced = checkBit(myPC, CartDebug::REFERENCED); + Device::CODE | (type != Device::DATA ? Device::DATA : 0) | + Device::GFX | Device::PGFX | + Device::COL | Device::PCOL | Device::BCOL | Device::AUD); + referenced = checkBit(myPC, Device::REFERENCED); } if (!lineEmpty) addEntry(type); /*myDisasmBuf << " ' ' "; - addEntry(CartDebug::NONE);*/ + addEntry(Device::NONE);*/ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/DiStella.hxx b/src/debugger/DiStella.hxx index 16da2b6ba..18a7bf25c 100644 --- a/src/debugger/DiStella.hxx +++ b/src/debugger/DiStella.hxx @@ -22,6 +22,7 @@ #include "Base.hxx" #include "CartDebug.hxx" +#include "Device.hxx" #include "bspf.hxx" /** @@ -71,11 +72,26 @@ class DiStella CartDebug::AddrTypeArray& directives, CartDebug::ReservedEquates& reserved); + private: + /** + Enumeration of the addressing type (RAM, ROM, RIOT, TIA...) + */ + enum class AddressType : int + { + INVALID, + ROM, + TIA, + RIOT, + ROM_MIRROR, + ZP_RAM + }; + + private: // Indicate that a new line of disassembly has been completed // In the original Distella code, this indicated a new line to be printed // Here, we add a new entry to the DisassemblyList - void addEntry(CartDebug::DisasmType type); + void addEntry(Device::AccessType type); // Process directives given in the list // Directives are basically the contents of a distella configuration file @@ -87,32 +103,32 @@ class DiStella void disasmFromAddress(uInt32 distart); bool check_range(uInt16 start, uInt16 end) const; - int mark(uInt32 address, uInt8 mask, bool directive = false); - bool checkBit(uInt16 address, uInt8 mask, bool useDebugger = true) const; - - bool checkBits(uInt16 address, uInt8 mask, uInt8 notMask, bool useDebugger = true) const; + AddressType mark(uInt32 address, uInt16 mask, bool directive = false); + bool checkBit(uInt16 address, uInt16 mask, bool useDebugger = true) const; + bool checkBits(uInt16 address, uInt16 mask, uInt16 notMask, bool useDebugger = true) const; void outputGraphics(); - void outputBytes(CartDebug::DisasmType type); + void outputColors(); + void outputBytes(Device::AccessType type); // Convenience methods to generate appropriate labels - inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, int labfound) + inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound) { if(!myDbg.getLabel(buf, addr, true)) buf << "L" << Common::Base::HEX4 << addr; } - inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, int labfound) + inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, AddressType labfound) { myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == RWMode::READ, 2); - if (labfound == 2) + if (labfound == AddressType::TIA) { if(ourLookup[op].rw_mode == RWMode::READ) myReserved.TIARead[addr & 0x0F] = true; else myReserved.TIAWrite[addr & 0x3F] = true; } - else if (labfound == 3) + else if (labfound == AddressType::RIOT) myReserved.IOReadWrite[(addr & 0xFF) - 0x80] = true; - else if (labfound == 5) + else if (labfound == AddressType::ZP_RAM) myReserved.ZPRAM[(addr & 0xFF) - 0x80] = true; } diff --git a/src/debugger/gui/Cart0840Widget.cxx b/src/debugger/gui/Cart0840Widget.cxx index 6582701bc..eb9275035 100644 --- a/src/debugger/gui/Cart0840Widget.cxx +++ b/src/debugger/gui/Cart0840Widget.cxx @@ -16,80 +16,25 @@ //============================================================================ #include "Cart0840.hxx" -#include "PopUpWidget.hxx" #include "Cart0840Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge0840Widget::Cartridge0840Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge0840& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 2 * 4096; + myHotspotDelta = 0x40; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge0840Widget::description() +{ ostringstream info; - info << "0840 ECONObanking, two 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0x800; i < 2; - ++i, offset += 0x1000, spot += 0x40) - { - uInt16 start = uInt16((cart.myImage[offset+1] << 8) | cart.myImage[offset]); - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $" << spot << ")\n"; - } + info << "0840 ECONObanking, two 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Fred X. Quimby", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($800)"); - VarList::push_back(items, "1 ($840)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($800)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge0840Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge0840Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge0840Widget::bankState() -{ - ostringstream& buf = buffer(); - - static const std::array spot = { "$800", "$840" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/Cart0840Widget.hxx b/src/debugger/gui/Cart0840Widget.hxx index 239f28bf8..00605b262 100644 --- a/src/debugger/gui/Cart0840Widget.hxx +++ b/src/debugger/gui/Cart0840Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGE0840_WIDGET_HXX class Cartridge0840; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge0840Widget : public CartDebugWidget +class Cartridge0840Widget : public CartridgeEnhancedWidget { public: Cartridge0840Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class Cartridge0840Widget : public CartDebugWidget virtual ~Cartridge0840Widget() = default; private: - Cartridge0840& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Fred X. Quimby"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported Cartridge0840Widget() = delete; Cartridge0840Widget(const Cartridge0840Widget&) = delete; diff --git a/src/debugger/gui/Cart2KWidget.cxx b/src/debugger/gui/Cart2KWidget.cxx index e90ed67f2..d87445ed3 100644 --- a/src/debugger/gui/Cart2KWidget.cxx +++ b/src/debugger/gui/Cart2KWidget.cxx @@ -22,15 +22,18 @@ Cartridge2KWidget::Cartridge2KWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge2K& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - // Eventually, we should query this from the debugger/disassembler - size_t size = cart.mySize; - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - start -= start % size; - - ostringstream info; - info << "Standard 2K cartridge, non-bankswitched\n" - << "Accessible @ $" << Common::Base::HEX4 << start << " - " << "$" << (start + size - 1); - addBaseInformation(size, "Atari", info.str()); + initialize(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge2KWidget::description() +{ + ostringstream info; + + info << "Standard 2K cartridge, non-bankswitched\n"; + info << CartridgeEnhancedWidget::description(); + + return info.str(); } diff --git a/src/debugger/gui/Cart2KWidget.hxx b/src/debugger/gui/Cart2KWidget.hxx index 0580078f7..123e3ddf5 100644 --- a/src/debugger/gui/Cart2KWidget.hxx +++ b/src/debugger/gui/Cart2KWidget.hxx @@ -20,9 +20,9 @@ class Cartridge2K; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge2KWidget : public CartDebugWidget +class Cartridge2KWidget : public CartridgeEnhancedWidget { public: Cartridge2KWidget(GuiObject* boss, const GUI::Font& lfont, @@ -32,10 +32,11 @@ class Cartridge2KWidget : public CartDebugWidget virtual ~Cartridge2KWidget() = default; private: - // No implementation for non-bankswitched ROMs - void loadConfig() override { } - void handleCommand(CommandSender* sender, int cmd, int data, int id) override { } + string manufacturer() override { return "Atari"; } + string description() override; + + private: // Following constructors and assignment operators not supported Cartridge2KWidget() = delete; Cartridge2KWidget(const Cartridge2KWidget&) = delete; diff --git a/src/debugger/gui/Cart3EPlusWidget.cxx b/src/debugger/gui/Cart3EPlusWidget.cxx index 74935f22b..cd0fda251 100644 --- a/src/debugger/gui/Cart3EPlusWidget.cxx +++ b/src/debugger/gui/Cart3EPlusWidget.cxx @@ -18,320 +18,230 @@ #include "Cart3EPlus.hxx" #include "EditTextWidget.hxx" #include "PopUpWidget.hxx" -#include "Cart3EPlusWidget.hxx" +#include "CartEnhancedWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge3EPlusWidget::Cartridge3EPlusWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge3EPlus& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), + myCart3EP(cart) { - size_t size = cart.mySize; - - ostringstream info; - info << "3EPlus cartridge - (64K ROM + RAM)\n" - << " 4-64K ROM (1K banks), 32K RAM (512b banks)\n" - << "Each 1K ROM selected by writing to $3F\n" - "Each 512b RAM selected by writing to $3E\n" - " Lower 512b of bank x (R)\n" - " Upper 512b of bank x (+$200) (W)\n" - << "Startup bank = 0/-1/-1/0 (ROM)\n"; - - // Eventually, we should query this from the debugger/disassembler - //uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - // Currently the cart starts at bank 0. If we change that, we have to change this too. - uInt16 start = (cart.myImage[0x400-3] << 8) | cart.myImage[0x400 - 4]; - start -= start % 0x1000; - info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; - - int xpos = 2, - ypos = addBaseInformation(size, "T. Jentzsch", info.str()) + - myLineHeight; - - VariantList bankno; - for(uInt32 i = 0; i < myCart.ROM_BANK_COUNT; ++i) - VarList::push_back(bankno, i, i); - - VariantList banktype; - VarList::push_back(banktype, "ROM", "ROM"); - VarList::push_back(banktype, "RAM", "RAM"); - - for(uInt32 i = 0; i < 4; ++i) - { - int xpos_s, ypos_s = ypos; - - ostringstream label; - label << "Set segment " << i << " as "; - - new StaticTextWidget(boss, _font, xpos, ypos, _font.getStringWidth(label.str()), - myFontHeight, label.str(), TextAlign::Left); - ypos += myLineHeight + 8; - - xpos += 20; - myBankNumber[i] = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("Slot "), - myLineHeight, bankno, "Slot ", - 6*_font.getMaxCharWidth()); - addFocusWidget(myBankNumber[i]); - - xpos += myBankNumber[i]->getWidth(); - myBankType[i] = - new PopUpWidget(boss, _font, xpos, ypos-2, 5*_font.getMaxCharWidth(), - myLineHeight, banktype, " of ", _font.getStringWidth(" of ")); - addFocusWidget(myBankType[i]); - - xpos += myBankType[i]->getWidth() + 10; - - myBankCommit[i] = new ButtonWidget(boss, _font, xpos, ypos-4, - _font.getStringWidth(" Commit "), myButtonHeight, - "Commit", bankEnum[i]); - myBankCommit[i]->setTarget(this); - addFocusWidget(myBankCommit[i]); - - xpos_s = xpos + myBankCommit[i]->getWidth() + 20; - - StaticTextWidget* t; - int addr1 = start + (i*0x400), addr2 = addr1 + 0x1FF; - - label.str(""); - label << Common::Base::HEX4 << addr1 << "-" << Common::Base::HEX4 << addr2; - t = new StaticTextWidget(boss, _font, xpos_s, ypos_s+2, - _font.getStringWidth(label.str()), myFontHeight, label.str(), TextAlign::Left); - - int xoffset = xpos_s+t->getWidth() + 10; - myBankState[2*i] = new EditTextWidget(boss, _font, xoffset, ypos_s, - w - xoffset - 10, myLineHeight, ""); - myBankState[2*i]->setEditable(false, true); - ypos_s += myLineHeight + 4; - - label.str(""); - label << Common::Base::HEX4 << (addr2 + 1) << "-" << Common::Base::HEX4 << (addr2 + 1 + 0x1FF); - new StaticTextWidget(boss, _font, xpos_s, ypos_s+2, - _font.getStringWidth(label.str()), myFontHeight, label.str(), TextAlign::Left); - - myBankState[2*i+1] = new EditTextWidget(boss, _font, xoffset, ypos_s, - w - xoffset - 10, myLineHeight, ""); - myBankState[2*i+1]->setEditable(false, true); - - xpos = 10; - ypos+= 2 * myLineHeight; - } + initialize(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlusWidget::saveOldState() +string Cartridge3EPlusWidget::description() { - myOldState.internalram.clear(); + ostringstream info; + size_t size; + const ByteBuffer& image = myCart.getImage(size); + uInt16 numRomBanks = myCart.romBankCount(); + uInt16 numRamBanks = myCart.ramBankCount(); - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); + info << "3E+ cartridge - (4" << ELLIPSIS << "64K ROM + RAM)\n" + << " " << numRomBanks << " 1K ROM banks + " << numRamBanks << " 512b RAM banks\n" + << " mapped into four segments\n" + "ROM bank & segment selected by writing to $3F\n" + "RAM bank & segment selected by writing to $3E\n" + " Lower 512b of segment for read access\n" + " Upper 512b of segment for write access\n" + "Startup bank = -1/-1/-1/0 (ROM)\n"; + + // Eventually, we should query this from the debugger/disassembler + uInt16 start = (image[0x400 - 3] << 8) | image[0x400 - 4]; + start -= start % 0x1000; + info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Cartridge3EPlusWidget::bankSelect(int& ypos) +{ + size_t size; + const ByteBuffer& image = myCart.getImage(size); + const int VGAP = myFontHeight / 4; + VariantList banktype; + + VarList::push_back(banktype, "ROM", "ROM"); + VarList::push_back(banktype, "RAM", "RAM"); + + myBankWidgets = make_unique(bankSegs()); + + ypos -= VGAP * 2; + + for(uInt32 seg = 0; seg < bankSegs(); ++seg) + { + int xpos = 2, xpos_s, ypos_s = ypos + 1, width; + ostringstream label; + VariantList items; + + label << "Set segment " << seg << " as "; + + new StaticTextWidget(_boss, _font, xpos, ypos, label.str()); + ypos += myLineHeight + VGAP * 2; + + xpos += _font.getMaxCharWidth() * 2; + + CartridgeEnhancedWidget::bankList(std::max(myCart.romBankCount(), myCart.ramBankCount()), + seg, items, width); + myBankWidgets[seg] = + new PopUpWidget(_boss, _font, xpos, ypos - 2, width, + myLineHeight, items, "Bank ", 0, kBankChanged); + myBankWidgets[seg]->setID(seg); + myBankWidgets[seg]->setTarget(this); + addFocusWidget(myBankWidgets[seg]); + + xpos += myBankWidgets[seg]->getWidth(); + myBankType[seg] = + new PopUpWidget(_boss, _font, xpos, ypos - 2, 3 * _font.getMaxCharWidth(), + myLineHeight, banktype, " of ", 0, kRomRamChanged); + myBankType[seg]->setID(seg); + myBankType[seg]->setTarget(this); + addFocusWidget(myBankType[seg]); + + xpos = myBankType[seg]->getRight() + _font.getMaxCharWidth(); + + // add "Commit" button (why required?) + myBankCommit[seg] = new ButtonWidget(_boss, _font, xpos, ypos - 4, + _font.getStringWidth(" Commit "), myButtonHeight, + "Commit", kChangeBank); + myBankCommit[seg]->setID(seg); + myBankCommit[seg]->setTarget(this); + addFocusWidget(myBankCommit[seg]); + + xpos_s = myBankCommit[seg]->getRight() + _font.getMaxCharWidth() * 2; + + StaticTextWidget* t; + uInt16 start = (image[0x400 - 3] << 8) | image[0x400 - 4]; + start -= start % 0x1000; + int addr1 = start + (seg * 0x400), addr2 = addr1 + 0x200; + + label.str(""); + label << "$" << Common::Base::HEX4 << addr1 << "-$" << Common::Base::HEX4 << (addr1 + 0x1FF); + t = new StaticTextWidget(_boss, _font, xpos_s, ypos_s + 2, label.str()); + + int xoffset = t->getRight() + _font.getMaxCharWidth(); + myBankState[2 * seg] = new EditTextWidget(_boss, _font, xoffset, ypos_s, + _w - xoffset - 10, myLineHeight, ""); + myBankState[2 * seg]->setEditable(false, true); + ypos_s += myLineHeight + VGAP; + + label.str(""); + label << "$" << Common::Base::HEX4 << addr2 << "-$" << Common::Base::HEX4 << (addr2 + 0x1FF); + new StaticTextWidget(_boss, _font, xpos_s, ypos_s + 2, label.str()); + + myBankState[2 * seg + 1] = new EditTextWidget(_boss, _font, xoffset, ypos_s, + _w - xoffset - 10, myLineHeight, ""); + myBankState[2 * seg + 1]->setEditable(false, true); + + ypos += myLineHeight + VGAP * 4; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3EPlusWidget::loadConfig() { + CartridgeEnhancedWidget::loadConfig(); updateUIState(); - CartDebugWidget::loadConfig(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3EPlusWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { - uInt16 segment = 0; + const uInt16 segment = id; + switch(cmd) { - case kBank0Changed: - segment = 0; + case kBankChanged: + case kRomRamChanged: + { + const bool isROM = myBankType[segment]->getSelectedTag() == "ROM"; + int bank = myBankWidgets[segment]->getSelected(); + + myBankCommit[segment]->setEnabled((isROM && bank < myCart.romBankCount()) + || (!isROM && bank < myCart.ramBankCount())); break; - case kBank1Changed: - segment = 1; - break; - case kBank2Changed: - segment = 2; - break; - case kBank3Changed: - segment = 3; + } + case kChangeBank: + { + // Ignore bank if either number or type hasn't been selected + if(myBankWidgets[segment]->getSelected() < 0 || + myBankType[segment]->getSelected() < 0) + return; + + uInt8 bank = myBankWidgets[segment]->getSelected(); + + myCart.unlockBank(); + + if(myBankType[segment]->getSelectedTag() == "ROM") + myCart.bank(bank, segment); + else + myCart.bank(bank + myCart.romBankCount(), segment); + + myCart.lockBank(); + invalidate(); + updateUIState(); break; + } default: break; } - - // Ignore bank if either number or type hasn't been selected - if(myBankNumber[segment]->getSelected() < 0 || - myBankType[segment]->getSelected() < 0) - return; - - uInt8 bank = (segment << myCart.BANK_BITS) | - (myBankNumber[segment]->getSelected() & myCart.BIT_BANK_MASK); - - myCart.unlockBank(); - - if(myBankType[segment]->getSelectedTag() == "ROM") - myCart.bankROM(bank); - else - myCart.bankRAM(bank); - - myCart.lockBank(); - invalidate(); - updateUIState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge3EPlusWidget::bankState() -{ - ostringstream& buf = buffer(); - - // In this scheme, consecutive 512b segments are either both ROM or both RAM; - // we only need to look at the lower segment to determine what the 1K bank is - for(int i = 0; i < 4; ++i) - { - uInt16 bank = myCart.bankInUse[i*2]; - - if(bank == myCart.BANK_UNDEFINED) // never accessed - { - buf << " U!"; - } - else - { - int bankno = bank & myCart.BIT_BANK_MASK; - - if(bank & myCart.BITMASK_ROMRAM) // was RAM mapped here? - buf << " RAM " << bankno; - else - buf << " ROM " << bankno; - } - if(i < 3) - buf << " /"; - } - - return buf.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3EPlusWidget::updateUIState() { - // Set description for each 512b bank state (@ each index) + // Set description for each 1K segment state (@ each index) // Set contents for actual banks number and type (@ each even index) - for(int i = 0; i < 8; ++i) + for(int seg = 0; seg < myCart3EP.myBankSegs; ++seg) { - uInt16 bank = myCart.bankInUse[i]; + uInt16 bank = myCart.getSegmentBank(seg); + ostringstream buf; - if(bank == myCart.BANK_UNDEFINED) // never accessed + if(bank >= myCart.romBankCount()) // was RAM mapped here? { - myBankState[i]->setText("Undefined"); - if(i % 2 == 0) - { - myBankNumber[i/2]->clearSelection(); - myBankType[i/2]->clearSelection(); - } + uInt16 ramBank = bank - myCart.romBankCount(); + + buf << "RAM @ $" << Common::Base::HEX4 + << (ramBank << myCart3EP.myBankShift) << " (R)"; + myBankState[seg * 2]->setText(buf.str()); + + buf.str(""); + buf << "RAM @ $" << Common::Base::HEX4 + << ((ramBank << myCart3EP.myBankShift) + myCart3EP.myBankSize) << " (W)"; + myBankState[seg * 2 + 1]->setText(buf.str()); + + myBankWidgets[seg]->setSelectedIndex(ramBank); + myBankType[seg]->setSelected("RAM"); } else { - ostringstream buf; - int bankno = bank & myCart.BIT_BANK_MASK; + buf << "ROM @ $" << Common::Base::HEX4 + << ((bank << myCart3EP.myBankShift)); + myBankState[seg * 2]->setText(buf.str()); - if(bank & myCart.BITMASK_ROMRAM) // was RAM mapped here? - { - if(bank & myCart.BITMASK_LOWERUPPER) // upper is write port - { - buf << "RAM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER) << " (W)"; - myBankState[i]->setText(buf.str()); - } - else - { - buf << "RAM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER) << " (R)"; - myBankState[i]->setText(buf.str()); - } + buf.str(""); + buf << "ROM @ $" << Common::Base::HEX4 + << ((bank << myCart3EP.myBankShift) + myCart3EP.myBankSize); + myBankState[seg * 2 + 1]->setText(buf.str()); - if(i % 2 == 0) - { - myBankNumber[i/2]->setSelected(bankno); - myBankType[i/2]->setSelected("RAM"); - } - } - else - { - if(bank & myCart.BITMASK_LOWERUPPER) // upper is high 512b - { - buf << "ROM " << bankno << " @ $" << Common::Base::HEX4 - << ((bankno << myCart.RAM_BANK_TO_POWER) + myCart.RAM_BANK_SIZE); - myBankState[i]->setText(buf.str()); - } - else - { - buf << "ROM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER); - myBankState[i]->setText(buf.str()); - } - - if(i % 2 == 0) - { - myBankNumber[i/2]->setSelected(bankno); - myBankType[i/2]->setSelected("ROM"); - } - } + myBankWidgets[seg]->setSelectedIndex(bank); + myBankType[seg]->setSelected("ROM"); } } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge3EPlusWidget::internalRamSize() -{ - return 32*1024; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge3EPlusWidget::internalRamRPort(int start) -{ - return 0x0000 + start; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string Cartridge3EPlusWidget::internalRamDescription() { ostringstream desc; + desc << "Accessible 512b at a time via:\n" - << " $f000/$f400/$f800/$fc00 for Read Access\n" - << " $f200/$f600/$fa00/$fe00 for Write Access (+$200)"; + << " $f000/$f400/$f800/$fc00 for read access\n" + << " $f200/$f600/$fa00/$fe00 for write access"; return desc.str(); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge3EPlusWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge3EPlusWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlusWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge3EPlusWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const std::array Cartridge3EPlusWidget::bankEnum = { - kBank0Changed, kBank1Changed, kBank2Changed, kBank3Changed -}; diff --git a/src/debugger/gui/Cart3EPlusWidget.hxx b/src/debugger/gui/Cart3EPlusWidget.hxx index 723003376..44473e0cf 100644 --- a/src/debugger/gui/Cart3EPlusWidget.hxx +++ b/src/debugger/gui/Cart3EPlusWidget.hxx @@ -23,9 +23,9 @@ class ButtonWidget; class EditTextWidget; class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge3EPlusWidget : public CartDebugWidget +class Cartridge3EPlusWidget : public CartridgeEnhancedWidget { public: Cartridge3EPlusWidget(GuiObject* boss, const GUI::Font& lfont, @@ -35,46 +35,33 @@ class Cartridge3EPlusWidget : public CartDebugWidget virtual ~Cartridge3EPlusWidget() = default; private: + string manufacturer() override { return "Thomas Jentzsch"; } + + string description() override; + + void bankSelect(int& ypos) override; + + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void updateUIState(); - private: - Cartridge3EPlus& myCart; + void loadConfig() override; + + string internalRamDescription() override; + + private: + Cartridge3EPlus& myCart3EP; - std::array myBankNumber{nullptr}; std::array myBankType{nullptr}; std::array myBankCommit{nullptr}; std::array myBankState{nullptr}; - struct CartState { - ByteArray internalram; + enum { + kRomRamChanged = 'rrCh', + kChangeBank = 'chBk', }; - CartState myOldState; - - enum BankID { - kBank0Changed = 'b0CH', - kBank1Changed = 'b1CH', - kBank2Changed = 'b2CH', - kBank3Changed = 'b3CH' - }; - static const std::array bankEnum; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported Cartridge3EPlusWidget() = delete; Cartridge3EPlusWidget(const Cartridge3EPlusWidget&) = delete; diff --git a/src/debugger/gui/Cart3EWidget.cxx b/src/debugger/gui/Cart3EWidget.cxx index 3880f2026..910f03368 100644 --- a/src/debugger/gui/Cart3EWidget.cxx +++ b/src/debugger/gui/Cart3EWidget.cxx @@ -23,129 +23,134 @@ Cartridge3EWidget::Cartridge3EWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge3E& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart), - myNumRomBanks(uInt32(cart.mySize >> 11)), - myNumRamBanks(32) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - size_t size = cart.mySize; - - ostringstream info; - info << "3E cartridge - (3F + RAM)\n" - << " 2-256 2K ROM (currently " << myNumRomBanks << "), 32 1K RAM\n" - << "First 2K (ROM) selected by writing to $3F\n" - "First 2K (RAM) selected by writing to $3E\n" - " $F000 - $F3FF (R), $F400 - $F7FF (W)\n" - "Last 2K always points to last 2K of ROM\n"; - if(cart.startBank() < myNumRomBanks) - info << "Startup bank = " << cart.startBank() << " (ROM)\n"; - else - info << "Startup bank = " << (cart.startBank()-myNumRomBanks) << " (RAM)\n"; - - // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - start -= start % 0x1000; - info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; - - int xpos = 2, - ypos = addBaseInformation(size, "TigerVision", info.str()) + myLineHeight; - - VariantList romitems; - for(uInt32 i = 0; i < myNumRomBanks; ++i) - VarList::push_back(romitems, i); - VarList::push_back(romitems, "Inactive", ""); - - VariantList ramitems; - for(uInt32 i = 0; i < myNumRamBanks; ++i) - VarList::push_back(ramitems, i); - VarList::push_back(ramitems, "Inactive", ""); - - ostringstream label; - label << "Set bank ($" << Common::Base::HEX4 << start << " - $" - << (start+0x7FF) << "): "; - - new StaticTextWidget(_boss, _font, xpos, ypos, _font.getStringWidth(label.str()), - myFontHeight, label.str(), TextAlign::Left); - ypos += myLineHeight + 8; - - xpos += 40; - myROMBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($3E) "), - myLineHeight, romitems, "ROM ($3F) ", - _font.getStringWidth("ROM ($3F) "), kROMBankChanged); - myROMBank->setTarget(this); - addFocusWidget(myROMBank); - - xpos += myROMBank->getWidth() + 20; - myRAMBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($3E) "), - myLineHeight, ramitems, "RAM ($3E) ", - _font.getStringWidth("RAM ($3E) "), kRAMBankChanged); - myRAMBank->setTarget(this); - addFocusWidget(myRAMBank); + initialize(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EWidget::saveOldState() +string Cartridge3EWidget::description() { - myOldState.internalram.clear(); + ostringstream info; + size_t size; + const ByteBuffer& image = myCart.getImage(size); + uInt16 numRomBanks = myCart.romBankCount(); + uInt16 numRamBanks = myCart.ramBankCount(); - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - myOldState.bank = myCart.myCurrentBank; + info << "3E cartridge (3F + RAM),\n" + << " " << numRomBanks << " 2K ROM banks, " << numRamBanks << " 1K RAM banks\n" + << "First 2K (ROM) selected by writing to $3F\n" + "First 2K (RAM) selected by writing to $3E\n"; + info << CartridgeEnhancedWidget::ramDescription(); + info << "Last 2K always points to last 2K of ROM\n"; + + if(myCart.startBank() < numRomBanks) + info << "Startup bank = " << myCart.startBank() << " (ROM)\n"; + else + info << "Startup bank = " << (myCart.startBank() - numRomBanks) << " (RAM)\n"; + + // Eventually, we should query this from the debugger/disassembler + uInt16 start = (image[size-3] << 8) | image[size-4]; + start -= start % 0x1000; + info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Cartridge3EWidget::bankList(uInt16 bankCount, int seg, VariantList& items, int& width) +{ + CartridgeEnhancedWidget::bankList(bankCount, seg, items, width); + + VarList::push_back(items, "Inactive", ""); + width = _font.getStringWidth("Inactive"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Cartridge3EWidget::bankSelect(int& ypos) +{ + int xpos = 2; + VariantList items; + int pw; + + myBankWidgets = make_unique(2); + + bankList(myCart.romBankCount(), 0, items, pw); + myBankWidgets[0] = + new PopUpWidget(_boss, _font, xpos, ypos - 2, pw, + myLineHeight, items, "Set bank ", + _font.getStringWidth("Set bank "), kBankChanged); + myBankWidgets[0]->setTarget(this); + myBankWidgets[0]->setID(0); + addFocusWidget(myBankWidgets[0]); + + StaticTextWidget* t = new StaticTextWidget(_boss, _font, myBankWidgets[0]->getRight(), ypos - 1, " (ROM)"); + + xpos = t->getRight() + 20; + items.clear(); + bankList(myCart.ramBankCount(), 0, items, pw); + myBankWidgets[1] = + new PopUpWidget(_boss, _font, xpos, ypos - 2, pw, + myLineHeight, items, "", 0, kRAMBankChanged); + myBankWidgets[1]->setTarget(this); + myBankWidgets[1]->setID(1); + addFocusWidget(myBankWidgets[1]); + + new StaticTextWidget(_boss, _font, myBankWidgets[1]->getRight(), ypos - 1, " (RAM)"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3EWidget::loadConfig() { - if(myCart.myCurrentBank < 256) + uInt16 oldBank = myOldState.banks[0]; + uInt16 bank = myCart.getBank(); + + if(myCart.getBank() < myCart.romBankCount()) { - myROMBank->setSelectedIndex(myCart.myCurrentBank % myNumRomBanks, myOldState.bank != myCart.myCurrentBank); - myRAMBank->setSelectedMax(myOldState.bank >= 256); + myBankWidgets[0]->setSelectedIndex(bank, oldBank != bank); + myBankWidgets[1]->setSelectedMax(oldBank >= myCart.romBankCount()); } else { - myROMBank->setSelectedMax(myOldState.bank < 256); - myRAMBank->setSelectedIndex(myCart.myCurrentBank - 256, myOldState.bank != myCart.myCurrentBank); + myBankWidgets[0]->setSelectedMax(oldBank < myCart.romBankCount()); + myBankWidgets[1]->setSelectedIndex(bank - myCart.romBankCount(), oldBank != bank); } CartDebugWidget::loadConfig(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) +void Cartridge3EWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { uInt16 bank = 0; - if(cmd == kROMBankChanged) + if(cmd == kBankChanged) { - if(myROMBank->getSelected() < int(myNumRomBanks)) + if(myBankWidgets[0]->getSelected() < myCart.romBankCount()) { - bank = myROMBank->getSelected(); - myRAMBank->setSelectedMax(); + bank = myBankWidgets[0]->getSelected(); + myBankWidgets[1]->setSelectedMax(); } else { - bank = 256; // default to first RAM bank - myRAMBank->setSelectedIndex(0); + bank = myCart.romBankCount(); // default to first RAM bank + myBankWidgets[1]->setSelectedIndex(0); } } else if(cmd == kRAMBankChanged) { - if(myRAMBank->getSelected() < int(myNumRamBanks)) + if(myBankWidgets[1]->getSelected() < myCart.ramBankCount()) { - myROMBank->setSelectedMax(); - bank = myRAMBank->getSelected() + 256; + myBankWidgets[0]->setSelectedMax(); + bank = myBankWidgets[1]->getSelected() + myCart.romBankCount(); } else { bank = 0; // default to first ROM bank - myROMBank->setSelectedIndex(0); + myBankWidgets[0]->setSelectedIndex(0); } } - myCart.unlockBank(); myCart.bank(bank); myCart.lockBank(); @@ -156,65 +161,13 @@ void Cartridge3EWidget::handleCommand(CommandSender* sender, string Cartridge3EWidget::bankState() { ostringstream& buf = buffer(); + uInt16 bank = myCart.getBank(); - uInt16& bank = myCart.myCurrentBank; - if(bank < 256) - buf << "ROM bank #" << std::dec << bank % myNumRomBanks << ", RAM inactive"; + if(bank < myCart.romBankCount()) + buf << "ROM bank #" << std::dec << bank % myCart.romBankCount() << ", RAM inactive"; else - buf << "ROM inactive, RAM bank #" << std::dec << bank % myNumRomBanks; + buf << "ROM inactive, RAM bank #" + << std::dec << (bank - myCart.romBankCount()) % myCart.ramBankCount(); return buf.str(); } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge3EWidget::internalRamSize() -{ - return 32*1024; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge3EWidget::internalRamRPort(int start) -{ - return 0x0000 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge3EWidget::internalRamDescription() -{ - ostringstream desc; - desc << "Accessible 1K at a time via:\n" - << " $F000 - $F3FF used for Read Access\n" - << " $F400 - $F7FF used for Write Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge3EWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge3EWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge3EWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} diff --git a/src/debugger/gui/Cart3EWidget.hxx b/src/debugger/gui/Cart3EWidget.hxx index 623a8877e..424d9a577 100644 --- a/src/debugger/gui/Cart3EWidget.hxx +++ b/src/debugger/gui/Cart3EWidget.hxx @@ -19,11 +19,12 @@ #define CARTRIDGE3E_WIDGET_HXX class Cartridge3E; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge3EWidget : public CartDebugWidget +// Note: This class supports 3EX too + +class Cartridge3EWidget : public CartridgeEnhancedWidget { public: Cartridge3EWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,39 +34,28 @@ class Cartridge3EWidget : public CartDebugWidget virtual ~Cartridge3EWidget() = default; private: - Cartridge3E& myCart; - const uInt32 myNumRomBanks{0}; - const uInt32 myNumRamBanks{0}; - PopUpWidget *myROMBank{nullptr}, *myRAMBank{nullptr}; - - struct CartState { - ByteArray internalram; - uInt16 bank; - }; - CartState myOldState; - enum { - kROMBankChanged = 'rmCH', kRAMBankChanged = 'raCH' }; private: - void saveOldState() override; + string manufacturer() override { return "Andrew Davie & Thomas Jentzsch"; } + + string description() override; + + void bankList(uInt16 bankCount, int seg, VariantList& items, int& width) override; + + void bankSelect(int& ypos) override; + + uInt16 bankSegs() override { return 1; } + void loadConfig() override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; string bankState() override; - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - // end of functions for Cartridge RAM tab - + private: // Following constructors and assignment operators not supported Cartridge3EWidget() = delete; Cartridge3EWidget(const Cartridge3EWidget&) = delete; diff --git a/src/debugger/gui/Cart3FWidget.cxx b/src/debugger/gui/Cart3FWidget.cxx index 223e56cc0..a84f0fd4f 100644 --- a/src/debugger/gui/Cart3FWidget.cxx +++ b/src/debugger/gui/Cart3FWidget.cxx @@ -16,79 +16,33 @@ //============================================================================ #include "Cart3F.hxx" -#include "PopUpWidget.hxx" #include "Cart3FWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge3FWidget::Cartridge3FWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge3F& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - size_t size = cart.mySize; + myHotspotDelta = 0; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge3FWidget::description() +{ ostringstream info; - info << "Tigervision 3F cartridge, 2-256 2K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n" - << "First 2K bank selected by writing to $3F\n" - << "Last 2K always points to last 2K of ROM\n"; + size_t size; + const ByteBuffer& image = myCart.getImage(size); + info << "Tigervision 3F cartridge, 2 - 256 2K banks\n" + << "First 2K bank selected by writing to " << hotspotStr() << "\n" + << "Last 2K always points to last 2K of ROM\n" + << "Startup bank = " << myCart.startBank() << " or undetermined\n"; // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; + uInt16 start = (image[size-3] << 8) | image[size-4]; start -= start % 0x1000; - info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; + info << "Bank RORG $" << Common::Base::HEX4 << start << "\n"; - int xpos = 2, - ypos = addBaseInformation(size, "TigerVision", info.str()) + myLineHeight; - - VariantList items; - for(uInt16 i = 0; i < cart.bankCount(); ++i) - VarList::push_back(items, Variant(i).toString() + " ($3F)"); - - ostringstream label; - label << "Set bank ($" << Common::Base::HEX4 << start << " - $" << - (start+0x7FF) << ") "; - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($3F) "), - myLineHeight, items, label.str(), - _font.getStringWidth(label.str()), kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3FWidget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(0), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3FWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge3FWidget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Bank = #" << std::dec << myCart.myCurrentBank << ", hotspot = $3F"; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/Cart3FWidget.hxx b/src/debugger/gui/Cart3FWidget.hxx index 859184057..ad24d8e56 100644 --- a/src/debugger/gui/Cart3FWidget.hxx +++ b/src/debugger/gui/Cart3FWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGE3F_WIDGET_HXX class Cartridge3F; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge3FWidget : public CartDebugWidget +class Cartridge3FWidget : public CartridgeEnhancedWidget { public: Cartridge3FWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,13 @@ class Cartridge3FWidget : public CartDebugWidget virtual ~Cartridge3FWidget() = default; private: - Cartridge3F& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "TigerVision"; } - enum { kBankChanged = 'bkCH' }; + string description() override; + + uInt16 bankSegs() override { return 1; } private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported Cartridge3FWidget() = delete; Cartridge3FWidget(const Cartridge3FWidget&) = delete; diff --git a/src/debugger/gui/Cart4KSCWidget.cxx b/src/debugger/gui/Cart4KSCWidget.cxx index 8729c077f..b6bc05d51 100644 --- a/src/debugger/gui/Cart4KSCWidget.cxx +++ b/src/debugger/gui/Cart4KSCWidget.cxx @@ -15,8 +15,6 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "Cart4KSC.hxx" #include "Cart4KSCWidget.hxx" @@ -24,87 +22,18 @@ Cartridge4KSCWidget::Cartridge4KSCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge4KSC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[0xFFD] << 8) | cart.myImage[0xFFC]; - start -= start % 0x1000; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge4KSCWidget::description() +{ ostringstream info; - info << "4KSC cartridge, non-bankswitched\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Accessible @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF); - addBaseInformation(4096, "homebrew intermediate format", info.str()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4KSCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge4KSCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Cartridge4KSCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge4KSCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge4KSCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& Cartridge4KSCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4KSCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge4KSCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Cartridge4KSCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + info << "4KSC cartridge, non-bankswitched\n"; + info << CartridgeEnhancedWidget::description(); + + return info.str(); } diff --git a/src/debugger/gui/Cart4KSCWidget.hxx b/src/debugger/gui/Cart4KSCWidget.hxx index 6a6ee2d8c..624a5623a 100644 --- a/src/debugger/gui/Cart4KSCWidget.hxx +++ b/src/debugger/gui/Cart4KSCWidget.hxx @@ -20,9 +20,9 @@ class Cartridge4KSC; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class Cartridge4KSCWidget : public CartDebugWidget +class Cartridge4KSCWidget : public CartridgeEnhancedWidget { public: Cartridge4KSCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -32,30 +32,11 @@ class Cartridge4KSCWidget : public CartDebugWidget virtual ~Cartridge4KSCWidget() = default; private: - Cartridge4KSC& myCart; - struct CartState { - ByteArray internalram; - }; - CartState myOldState; + string manufacturer() override { return "homebrew intermediate format"; } + + string description() override; private: - // No implementation for non-bankswitched ROMs - void loadConfig() override { } - void handleCommand(CommandSender* sender, int cmd, int data, int id) override { } - - void saveOldState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported Cartridge4KSCWidget() = delete; Cartridge4KSCWidget(const Cartridge4KSCWidget&) = delete; diff --git a/src/debugger/gui/Cart4KWidget.cxx b/src/debugger/gui/Cart4KWidget.cxx index ed4ef7218..deca594fb 100644 --- a/src/debugger/gui/Cart4KWidget.cxx +++ b/src/debugger/gui/Cart4KWidget.cxx @@ -22,15 +22,29 @@ Cartridge4KWidget::Cartridge4KWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, Cartridge4K& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[0xFFD] << 8) | cart.myImage[0xFFC]; - start -= start % 0x1000; + initialize(); - ostringstream info; - info << "Standard 4K cartridge, non-bankswitched\n" - << "Accessible @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF); - addBaseInformation(4096, "Atari", info.str()); + //// Eventually, we should query this from the debugger/disassembler + //uInt16 start = (cart.myImage[0xFFD] << 8) | cart.myImage[0xFFC]; + //start -= start % 0x1000; + + //ostringstream info; + //info << "Standard 4K cartridge, non-bankswitched\n" + // << "Accessible @ $" << Common::Base::HEX4 << start << " - " + // << "$" << (start + 0xFFF); + //addBaseInformation(4096, "Atari", info.str()); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge4KWidget::description() +{ + ostringstream info; + + info << "Standard 4K cartridge, non-bankswitched\n"; + info << CartridgeEnhancedWidget::description(); + + return info.str(); +} + diff --git a/src/debugger/gui/Cart4KWidget.hxx b/src/debugger/gui/Cart4KWidget.hxx index 3ba39a3d9..3fd18eb66 100644 --- a/src/debugger/gui/Cart4KWidget.hxx +++ b/src/debugger/gui/Cart4KWidget.hxx @@ -20,9 +20,9 @@ class Cartridge4K; -#include "CartDebugWidget.hxx" +#include "CartEnhanced.hxx" -class Cartridge4KWidget : public CartDebugWidget +class Cartridge4KWidget : public CartridgeEnhancedWidget { public: Cartridge4KWidget(GuiObject* boss, const GUI::Font& lfont, @@ -32,10 +32,11 @@ class Cartridge4KWidget : public CartDebugWidget virtual ~Cartridge4KWidget() = default; private: - // No implementation for non-bankswitched ROMs - void loadConfig() override { } - void handleCommand(CommandSender* sender, int cmd, int data, int id) override { } + string manufacturer() override { return "Atari"; } + string description() override; + + private: // Following constructors and assignment operators not supported Cartridge4KWidget() = delete; Cartridge4KWidget(const Cartridge4KWidget&) = delete; diff --git a/src/debugger/gui/CartARWidget.cxx b/src/debugger/gui/CartARWidget.cxx index 6037849f6..ec4c4037a 100644 --- a/src/debugger/gui/CartARWidget.cxx +++ b/src/debugger/gui/CartARWidget.cxx @@ -16,6 +16,9 @@ //============================================================================ #include "CartAR.hxx" +#include "OSystem.hxx" +#include "Debugger.hxx" +#include "CartDebug.hxx" #include "PopUpWidget.hxx" #include "CartARWidget.hxx" diff --git a/src/debugger/gui/CartBFSCWidget.cxx b/src/debugger/gui/CartBFSCWidget.cxx index 819e72b39..15f10ff62 100644 --- a/src/debugger/gui/CartBFSCWidget.cxx +++ b/src/debugger/gui/CartBFSCWidget.cxx @@ -15,221 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartBFSC.hxx" -#include "PopUpWidget.hxx" #include "CartBFSCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeBFSCWidget::CartridgeBFSCWidget( - GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, - int x, int y, int w, int h, CartridgeBFSC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w, int h, CartridgeBFSC& cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 64 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeBFSCWidget::description() +{ ostringstream info; - info << "256K BFSC + RAM, 64 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xF80; i < 64; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << (start + 0x100) - << " - " << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "256K BFSC + RAM, 64 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "CPUWIZ", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FF80)"); - VarList::push_back(items, " 1 ($FF81)"); - VarList::push_back(items, " 2 ($FF82)"); - VarList::push_back(items, " 3 ($FF83)"); - VarList::push_back(items, " 4 ($FF84)"); - VarList::push_back(items, " 5 ($FF85)"); - VarList::push_back(items, " 6 ($FF86)"); - VarList::push_back(items, " 7 ($FF87)"); - VarList::push_back(items, " 8 ($FF88)"); - VarList::push_back(items, " 9 ($FF89)"); - VarList::push_back(items, "10 ($FF8A)"); - VarList::push_back(items, "11 ($FF8B)"); - VarList::push_back(items, "12 ($FF8C)"); - VarList::push_back(items, "13 ($FF8D)"); - VarList::push_back(items, "14 ($FF8E)"); - VarList::push_back(items, "15 ($FF8F)"); - VarList::push_back(items, "16 ($FF90)"); - VarList::push_back(items, "17 ($FF91)"); - VarList::push_back(items, "18 ($FF92)"); - VarList::push_back(items, "19 ($FF93)"); - VarList::push_back(items, "20 ($FF94)"); - VarList::push_back(items, "21 ($FF95)"); - VarList::push_back(items, "22 ($FF96)"); - VarList::push_back(items, "23 ($FF97)"); - VarList::push_back(items, "24 ($FF98)"); - VarList::push_back(items, "25 ($FF99)"); - VarList::push_back(items, "26 ($FF9A)"); - VarList::push_back(items, "27 ($FF9B)"); - VarList::push_back(items, "28 ($FF9C)"); - VarList::push_back(items, "29 ($FF9D)"); - VarList::push_back(items, "30 ($FF9E)"); - VarList::push_back(items, "31 ($FF9F)"); - VarList::push_back(items, "32 ($FFA0)"); - VarList::push_back(items, "33 ($FFA1)"); - VarList::push_back(items, "34 ($FFA2)"); - VarList::push_back(items, "35 ($FFA3)"); - VarList::push_back(items, "36 ($FFA4)"); - VarList::push_back(items, "37 ($FFA5)"); - VarList::push_back(items, "38 ($FFA6)"); - VarList::push_back(items, "39 ($FFA7)"); - VarList::push_back(items, "40 ($FFA8)"); - VarList::push_back(items, "41 ($FFA9)"); - VarList::push_back(items, "42 ($FFAA)"); - VarList::push_back(items, "43 ($FFAB)"); - VarList::push_back(items, "44 ($FFAC)"); - VarList::push_back(items, "45 ($FFAD)"); - VarList::push_back(items, "46 ($FFAE)"); - VarList::push_back(items, "47 ($FFAF)"); - VarList::push_back(items, "48 ($FFB0)"); - VarList::push_back(items, "49 ($FFB1)"); - VarList::push_back(items, "50 ($FFB2)"); - VarList::push_back(items, "51 ($FFB3)"); - VarList::push_back(items, "52 ($FFB4)"); - VarList::push_back(items, "53 ($FFB5)"); - VarList::push_back(items, "54 ($FFB6)"); - VarList::push_back(items, "55 ($FFB7)"); - VarList::push_back(items, "56 ($FFB8)"); - VarList::push_back(items, "57 ($FFB9)"); - VarList::push_back(items, "58 ($FFBA)"); - VarList::push_back(items, "59 ($FFBB)"); - VarList::push_back(items, "60 ($FFBC)"); - VarList::push_back(items, "61 ($FFBD)"); - VarList::push_back(items, "62 ($FFBE)"); - VarList::push_back(items, "63 ($FFBF)"); - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("63 ($FFBF)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeBFSCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FF80", "$FF81", "$FF82", "$FF83", "$FF84", "$FF85", "$FF86", "$FF87", - "$FF88", "$FF89", "$FF8A", "$FF8B", "$FF8C", "$FF8D", "$FF8E", "$FF8F", - "$FF90", "$FF91", "$FF92", "$FF93", "$FF94", "$FF95", "$FF96", "$FF97", - "$FF98", "$FF99", "$FF9A", "$FF9B", "$FF9C", "$FF9D", "$FF9E", "$FF9F", - "$FFA0", "$FFA1", "$FFA2", "$FFA3", "$FFA4", "$FFA5", "$FFA6", "$FFA7", - "$FFA8", "$FFA9", "$FFAA", "$FFAB", "$FFAC", "$FFAD", "$FFAE", "$FFAF", - "$FFB0", "$FFB1", "$FFB2", "$FFB3", "$FFB4", "$FFB5", "$FFB6", "$FFB7", - "$FFB8", "$FFB9", "$FFBA", "$FFBB", "$FFBC", "$FFBD", "$FFBE", "$FFBF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeBFSCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeBFSCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeBFSCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeBFSCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeBFSCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeBFSCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeBFSCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartBFSCWidget.hxx b/src/debugger/gui/CartBFSCWidget.hxx index 3068672f0..739f41388 100644 --- a/src/debugger/gui/CartBFSCWidget.hxx +++ b/src/debugger/gui/CartBFSCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEBFSC_WIDGET_HXX class CartridgeBFSC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeBFSCWidget : public CartDebugWidget +class CartridgeBFSCWidget : public CartridgeEnhancedWidget { public: CartridgeBFSCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,35 +32,11 @@ class CartridgeBFSCWidget : public CartDebugWidget virtual ~CartridgeBFSCWidget() = default; private: - CartridgeBFSC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "CPUWIZ"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeBFSCWidget() = delete; CartridgeBFSCWidget(const CartridgeBFSCWidget&) = delete; diff --git a/src/debugger/gui/CartBFWidget.cxx b/src/debugger/gui/CartBFWidget.cxx index 96ddc5662..cbaabf076 100644 --- a/src/debugger/gui/CartBFWidget.cxx +++ b/src/debugger/gui/CartBFWidget.cxx @@ -16,151 +16,24 @@ //============================================================================ #include "CartBF.hxx" -#include "PopUpWidget.hxx" #include "CartBFWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeBFWidget::CartridgeBFWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeBF& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 64 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeBFWidget::description() +{ ostringstream info; - info << "BF cartridge, 64 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xF80; i < 64; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "256K BF cartridge, 64 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "CPUWIZ", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FF80)"); - VarList::push_back(items, " 1 ($FF81)"); - VarList::push_back(items, " 2 ($FF82)"); - VarList::push_back(items, " 3 ($FF83)"); - VarList::push_back(items, " 4 ($FF84)"); - VarList::push_back(items, " 5 ($FF85)"); - VarList::push_back(items, " 6 ($FF86)"); - VarList::push_back(items, " 7 ($FF87)"); - VarList::push_back(items, " 8 ($FF88)"); - VarList::push_back(items, " 9 ($FF89)"); - VarList::push_back(items, "10 ($FF8A)"); - VarList::push_back(items, "11 ($FF8B)"); - VarList::push_back(items, "12 ($FF8C)"); - VarList::push_back(items, "13 ($FF8D)"); - VarList::push_back(items, "14 ($FF8E)"); - VarList::push_back(items, "15 ($FF8F)"); - VarList::push_back(items, "16 ($FF90)"); - VarList::push_back(items, "17 ($FF91)"); - VarList::push_back(items, "18 ($FF92)"); - VarList::push_back(items, "19 ($FF93)"); - VarList::push_back(items, "20 ($FF94)"); - VarList::push_back(items, "21 ($FF95)"); - VarList::push_back(items, "22 ($FF96)"); - VarList::push_back(items, "23 ($FF97)"); - VarList::push_back(items, "24 ($FF98)"); - VarList::push_back(items, "25 ($FF99)"); - VarList::push_back(items, "26 ($FF9A)"); - VarList::push_back(items, "27 ($FF9B)"); - VarList::push_back(items, "28 ($FF9C)"); - VarList::push_back(items, "29 ($FF9D)"); - VarList::push_back(items, "30 ($FF9E)"); - VarList::push_back(items, "31 ($FF9F)"); - VarList::push_back(items, "32 ($FFA0)"); - VarList::push_back(items, "33 ($FFA1)"); - VarList::push_back(items, "34 ($FFA2)"); - VarList::push_back(items, "35 ($FFA3)"); - VarList::push_back(items, "36 ($FFA4)"); - VarList::push_back(items, "37 ($FFA5)"); - VarList::push_back(items, "38 ($FFA6)"); - VarList::push_back(items, "39 ($FFA7)"); - VarList::push_back(items, "40 ($FFA8)"); - VarList::push_back(items, "41 ($FFA9)"); - VarList::push_back(items, "42 ($FFAA)"); - VarList::push_back(items, "43 ($FFAB)"); - VarList::push_back(items, "44 ($FFAC)"); - VarList::push_back(items, "45 ($FFAD)"); - VarList::push_back(items, "46 ($FFAE)"); - VarList::push_back(items, "47 ($FFAF)"); - VarList::push_back(items, "48 ($FFB0)"); - VarList::push_back(items, "49 ($FFB1)"); - VarList::push_back(items, "50 ($FFB2)"); - VarList::push_back(items, "51 ($FFB3)"); - VarList::push_back(items, "52 ($FFB4)"); - VarList::push_back(items, "53 ($FFB5)"); - VarList::push_back(items, "54 ($FFB6)"); - VarList::push_back(items, "55 ($FFB7)"); - VarList::push_back(items, "56 ($FFB8)"); - VarList::push_back(items, "57 ($FFB9)"); - VarList::push_back(items, "58 ($FFBA)"); - VarList::push_back(items, "59 ($FFBB)"); - VarList::push_back(items, "60 ($FFBC)"); - VarList::push_back(items, "61 ($FFBD)"); - VarList::push_back(items, "62 ($FFBE)"); - VarList::push_back(items, "63 ($FFBF)"); - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("64 ($FFBF)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFWidget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeBFWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FF80", "$FF81", "$FF82", "$FF83", "$FF84", "$FF85", "$FF86", "$FF87", - "$FF88", "$FF89", "$FF8A", "$FF8B", "$FF8C", "$FF8D", "$FF8E", "$FF8F", - "$FF90", "$FF91", "$FF92", "$FF93", "$FF94", "$FF95", "$FF96", "$FF97", - "$FF98", "$FF99", "$FF9A", "$FF9B", "$FF9C", "$FF9D", "$FF9E", "$FF9F", - "$FFA0", "$FFA1", "$FFA2", "$FFA3", "$FFA4", "$FFA5", "$FFA6", "$FFA7", - "$FFA8", "$FFA9", "$FFAA", "$FFAB", "$FFAC", "$FFAD", "$FFAE", "$FFAF", - "$FFB0", "$FFB1", "$FFB2", "$FFB3", "$FFB4", "$FFB5", "$FFB6", "$FFB7", - "$FFB8", "$FFB9", "$FFBA", "$FFBB", "$FFBC", "$FFBD", "$FFBE", "$FFBF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartBFWidget.hxx b/src/debugger/gui/CartBFWidget.hxx index d084dbbc3..b67391c63 100644 --- a/src/debugger/gui/CartBFWidget.hxx +++ b/src/debugger/gui/CartBFWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEBF_WIDGET_HXX class CartridgeBF; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeBFWidget : public CartDebugWidget +class CartridgeBFWidget : public CartridgeEnhancedWidget { public: CartridgeBFWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeBFWidget : public CartDebugWidget virtual ~CartridgeBFWidget() = default; private: - CartridgeBF& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "CPUWIZ"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeBFWidget() = delete; CartridgeBFWidget(const CartridgeBFWidget&) = delete; diff --git a/src/debugger/gui/CartBUSWidget.cxx b/src/debugger/gui/CartBUSWidget.cxx index b9c25a77d..8f6a9b22b 100644 --- a/src/debugger/gui/CartBUSWidget.cxx +++ b/src/debugger/gui/CartBUSWidget.cxx @@ -238,7 +238,7 @@ void CartridgeBUSWidget::saveOldState() } for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myBUSRAM[i]); + myOldState.internalram.push_back(myCart.myRAM[i]); myOldState.samplepointer.push_back(myCart.getSample()); } @@ -438,18 +438,18 @@ const ByteArray& CartridgeBUSWidget::internalRamCurrent(int start, int count) { myRamCurrent.clear(); for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myBUSRAM[start + i]); + myRamCurrent.push_back(myCart.myRAM[start + i]); return myRamCurrent; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeBUSWidget::internalRamSetValue(int addr, uInt8 value) { - myCart.myBUSRAM[addr] = value; + myCart.myRAM[addr] = value; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeBUSWidget::internalRamGetValue(int addr) { - return myCart.myBUSRAM[addr]; + return myCart.myRAM[addr]; } diff --git a/src/debugger/gui/CartCDFWidget.cxx b/src/debugger/gui/CartCDFWidget.cxx index 60b68d5c4..8c4fdf2fc 100644 --- a/src/debugger/gui/CartCDFWidget.cxx +++ b/src/debugger/gui/CartCDFWidget.cxx @@ -232,7 +232,7 @@ void CartridgeCDFWidget::saveOldState() } for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myCDFRAM[i]); + myOldState.internalram.push_back(myCart.myRAM[i]); myOldState.samplepointer.push_back(myCart.getSample()); } @@ -437,20 +437,20 @@ const ByteArray& CartridgeCDFWidget::internalRamCurrent(int start, int count) { myRamCurrent.clear(); for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myCDFRAM[start + i]); + myRamCurrent.push_back(myCart.myRAM[start + i]); return myRamCurrent; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeCDFWidget::internalRamSetValue(int addr, uInt8 value) { - myCart.myCDFRAM[addr] = value; + myCart.myRAM[addr] = value; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeCDFWidget::internalRamGetValue(int addr) { - return myCart.myCDFRAM[addr]; + return myCart.myRAM[addr]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/CartCMWidget.cxx b/src/debugger/gui/CartCMWidget.cxx index 8fa72f0bb..e4d11ba55 100644 --- a/src/debugger/gui/CartCMWidget.cxx +++ b/src/debugger/gui/CartCMWidget.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "CartCM.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" #include "RiotDebug.hxx" diff --git a/src/debugger/gui/CartCTYWidget.cxx b/src/debugger/gui/CartCTYWidget.cxx index 76230fa21..659fb9bea 100644 --- a/src/debugger/gui/CartCTYWidget.cxx +++ b/src/debugger/gui/CartCTYWidget.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" #include "CartCTY.hxx" diff --git a/src/debugger/gui/CartCVPlusWidget.cxx b/src/debugger/gui/CartCVPlusWidget.cxx deleted file mode 100644 index cab27d3e5..000000000 --- a/src/debugger/gui/CartCVPlusWidget.cxx +++ /dev/null @@ -1,157 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include "Debugger.hxx" -#include "CartDebug.hxx" -#include "CartCVPlus.hxx" -#include "PopUpWidget.hxx" -#include "CartCVPlusWidget.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeCVPlusWidget::CartridgeCVPlusWidget( - GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, - int x, int y, int w, int h, CartridgeCVPlus& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) -{ - size_t size = cart.mySize; - - ostringstream info; - info << "LS_Dracon CV+ cartridge, 1K RAM, 2-256 2K ROM\n" - << "1024 bytes RAM @ $F000 - $F7FF\n" - << " $F000 - $F3FF (R), $F400 - $F7FF (W)\n" - << "2048 bytes ROM @ $F800 - $FFFF, by writing to $3D\n" - << "Startup bank = " << cart.startBank() << "\n"; - - int xpos = 2, - ypos = addBaseInformation(size, "LS_Dracon / Stephen Anthony", - info.str()) + myLineHeight; - - VariantList items; - for(uInt16 i = 0; i < cart.bankCount(); ++i) - VarList::push_back(items, Variant(i).toString() + " ($3D)"); - - ostringstream label; - label << "Set bank ($F800 - $FFFF) "; - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("xxx ($3D)"), - myLineHeight, items, label.str(), - _font.getStringWidth(label.str()), kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlusWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlusWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeCVPlusWidget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Bank = " << std::dec << myCart.myCurrentBank << ", hotspot = $3D"; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlusWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeCVPlusWidget::internalRamSize() -{ - return 1024; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeCVPlusWidget::internalRamRPort(int start) -{ - return 0xF000 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeCVPlusWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F3FF used for Read Access\n" - << "$F400 - $F7FF used for Write Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeCVPlusWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeCVPlusWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlusWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeCVPlusWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeCVPlusWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF000, false); -} diff --git a/src/debugger/gui/CartCVWidget.cxx b/src/debugger/gui/CartCVWidget.cxx index bae69cfba..f76718375 100644 --- a/src/debugger/gui/CartCVWidget.cxx +++ b/src/debugger/gui/CartCVWidget.cxx @@ -24,88 +24,18 @@ CartridgeCVWidget::CartridgeCVWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeCV& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - // Eventually, we should query this from the debugger/disassembler - uInt16 size = 2048; - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - start -= start % size; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeCVWidget::description() +{ ostringstream info; - info << "CV 2K ROM + 1K RAM , non-bankswitched\n" - << "1024 bytes RAM @ $F000 - $F7FF\n" - << " $F000 - $F3FF (R), $F400 - $F7FF (W)\n" - << "ROM accessible @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + size - 1); - addBaseInformation(cart.mySize, "CommaVid", info.str()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeCVWidget::internalRamSize() -{ - return 1024; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeCVWidget::internalRamRPort(int start) -{ - return 0xF000 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeCVWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F3FF used for Read Access\n" - << "$F400 - $F7FF used for Write Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeCVWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeCVWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeCVWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeCVWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF000, false); + info << "CV 2K ROM + 1K RAM, non-bankswitched\n"; + info << CartridgeEnhancedWidget::description(); + + return info.str(); } diff --git a/src/debugger/gui/CartCVWidget.hxx b/src/debugger/gui/CartCVWidget.hxx index f9d59812b..63fc6f237 100644 --- a/src/debugger/gui/CartCVWidget.hxx +++ b/src/debugger/gui/CartCVWidget.hxx @@ -20,9 +20,9 @@ class CartridgeCV; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeCVWidget : public CartDebugWidget +class CartridgeCVWidget : public CartridgeEnhancedWidget { public: CartridgeCVWidget(GuiObject* boss, const GUI::Font& lfont, @@ -32,30 +32,11 @@ class CartridgeCVWidget : public CartDebugWidget virtual ~CartridgeCVWidget() = default; private: - CartridgeCV& myCart; - struct CartState { - ByteArray internalram; - }; - CartState myOldState; + string manufacturer() override { return "CommaVid"; } + + string description() override; private: - // No implementation for non-bankswitched ROMs - void loadConfig() override { } - void handleCommand(CommandSender* sender, int cmd, int data, int id) override { } - - void saveOldState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeCVWidget() = delete; CartridgeCVWidget(const CartridgeCVWidget&) = delete; diff --git a/src/debugger/gui/CartDASHWidget.cxx b/src/debugger/gui/CartDASHWidget.cxx deleted file mode 100644 index a3dfa1109..000000000 --- a/src/debugger/gui/CartDASHWidget.cxx +++ /dev/null @@ -1,371 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include "CartDASH.hxx" -#include "EditTextWidget.hxx" -#include "PopUpWidget.hxx" -#include "CartDASHWidget.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeDASHWidget::CartridgeDASHWidget( - GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, - int x, int y, int w, int h, CartridgeDASH& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) -{ - size_t size = cart.mySize; - - ostringstream info; - info << "DASH cartridge - (64K ROM + RAM)\n" - << " 4-64K ROM (1K banks), 32K RAM (512b banks)\n" - << "Each 1K ROM selected by writing to $3F\n" - "Each 512b RAM selected by writing to $3E\n" - " First 512B of bank x (R)\n" - " First 512B of bank x+4 (+$800) (W)\n" - << "Startup bank = 0/-1/-1/0 (ROM)\n"; - - // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - start -= start % 0x1000; - info << "Bank RORG" << " = $" << Common::Base::HEX4 << start << "\n"; - - int xpos = 2, - ypos = addBaseInformation(size, "A. Davie & T. Jentzsch", info.str()) + - myLineHeight; - - VariantList bankno; - for(uInt32 i = 0; i < myCart.ROM_BANK_COUNT; ++i) - VarList::push_back(bankno, i, i); - - VariantList banktype; - VarList::push_back(banktype, "ROM", "ROM"); - VarList::push_back(banktype, "RAM", "RAM"); - - for(uInt32 i = 0; i < 4; ++i) - { - int xpos_s, ypos_s = ypos; - - ostringstream label; - label << "Set segment " << i << " as: "; - - new StaticTextWidget(boss, _font, xpos, ypos, _font.getStringWidth(label.str()), - myFontHeight, label.str(), TextAlign::Left); - ypos += myLineHeight + 8; - - xpos += 20; - myBankNumber[i] = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("Slot "), - myLineHeight, bankno, "Slot ", - 6*_font.getMaxCharWidth()); - addFocusWidget(myBankNumber[i]); - - xpos += myBankNumber[i]->getWidth(); - myBankType[i] = - new PopUpWidget(boss, _font, xpos, ypos-2, 5*_font.getMaxCharWidth(), - myLineHeight, banktype, " of ", _font.getStringWidth(" of ")); - addFocusWidget(myBankType[i]); - - xpos += myBankType[i]->getWidth() + 10; - - myBankCommit[i] = new ButtonWidget(boss, _font, xpos, ypos-4, - _font.getStringWidth(" Commit "), myButtonHeight, - "Commit", bankEnum[i]); - myBankCommit[i]->setTarget(this); - addFocusWidget(myBankCommit[i]); - - xpos_s = xpos + myBankCommit[i]->getWidth() + 20; - - StaticTextWidget* t; - int addr1 = start + (i*0x400), addr2 = addr1 + 0x1FF; - - label.str(""); - label << Common::Base::HEX4 << addr1 << "-" << Common::Base::HEX4 << addr2; - t = new StaticTextWidget(boss, _font, xpos_s, ypos_s+2, - _font.getStringWidth(label.str()), myFontHeight, label.str(), TextAlign::Left); - - int xoffset = xpos_s+t->getWidth() + 10; - myBankState[2*i] = new EditTextWidget(boss, _font, xoffset, ypos_s, - w - xoffset - 10, myLineHeight, ""); - myBankState[2*i]->setEditable(false, true); - ypos_s += myLineHeight + 4; - - label.str(""); - label << Common::Base::HEX4 << (addr2 + 1) << "-" << Common::Base::HEX4 << (addr2 + 1 + 0x1FF); - new StaticTextWidget(boss, _font, xpos_s, ypos_s+2, - _font.getStringWidth(label.str()), myFontHeight, label.str(), TextAlign::Left); - - myBankState[2*i+1] = new EditTextWidget(boss, _font, xoffset, ypos_s, - w - xoffset - 10, myLineHeight, ""); - myBankState[2*i+1]->setEditable(false, true); - - xpos = 10; - ypos+= 2 * myLineHeight; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASHWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASHWidget::loadConfig() -{ - updateUIState(); - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASHWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - uInt16 segment = 0; - switch(cmd) - { - case kBank0Changed: - segment = 0; - break; - case kBank1Changed: - segment = 1; - break; - case kBank2Changed: - segment = 2; - break; - case kBank3Changed: - segment = 3; - break; - default: - break; - } - - // Ignore bank if either number or type hasn't been selected - if(myBankNumber[segment]->getSelected() < 0 || - myBankType[segment]->getSelected() < 0) - return; - - uInt8 bank = (segment << myCart.BANK_BITS) | - (myBankNumber[segment]->getSelected() & myCart.BIT_BANK_MASK); - - myCart.unlockBank(); - - if(myBankType[segment]->getSelectedTag() == "ROM") - myCart.bankROM(bank); - else - myCart.bankRAM(bank); - - myCart.lockBank(); - invalidate(); - updateUIState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDASHWidget::bankState() -{ - ostringstream& buf = buffer(); - int lastROMBank = -1; - bool lastSlotRAM = false; - - for(int i = 0; i < 8; ++i) - { - uInt16 bank = myCart.bankInUse[i]; - - if(bank == myCart.BANK_UNDEFINED) // never accessed - { - buf << " U!"; - } - else - { - int bankno = bank & myCart.BIT_BANK_MASK; - - if(bank & myCart.BITMASK_ROMRAM) // was RAM mapped here? - { - // RAM will always need a '+' placed somewhere, since it always - // consists of 512B segments - bool inFirstSlot = (i % 2 == 0); - if(!(inFirstSlot || lastSlotRAM)) - { - lastSlotRAM = false; - buf << " +"; - } - - if(bank & myCart.BITMASK_LOWERUPPER) // upper is write port - buf << " RAM " << bankno << "W"; - else - buf << " RAM " << bankno << "R"; - - if(inFirstSlot) - { - buf << " +"; - lastSlotRAM = true; - } - } - else - { - // ROM can be contiguous, since 2 512B segments can form a single - // 1K bank; in this case we only show the info once - bool highBankSame = (i % 2 == 1) && (bankno == lastROMBank); - if(!highBankSame) - { - buf << " ROM " << bankno; - lastROMBank = bankno; - } - else - lastROMBank = -1; - - lastSlotRAM = false; - } - } - - if((i+1) % 2 == 0 && i < 7) - buf << " /"; - } - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASHWidget::updateUIState() -{ - // Set contents for actual banks number and type - for(int i = 0; i < 4; ++i) - { - uInt16 segment = myCart.segmentInUse[i]; - - if(segment == myCart.BANK_UNDEFINED) - { - myBankNumber[i]->clearSelection(); - myBankType[i]->clearSelection(); - } - else - { - int bankno = segment & myCart.BIT_BANK_MASK; - const string& banktype = (segment & myCart.BITMASK_ROMRAM) ? "RAM" : "ROM"; - - myBankNumber[i]->setSelected(bankno); - myBankType[i]->setSelected(banktype); - } - } - - // Set description for each 512b bank state - for(int i = 0; i < 8; ++i) - { - uInt16 bank = myCart.bankInUse[i]; - - if(bank == myCart.BANK_UNDEFINED) // never accessed - { - myBankState[i]->setText("Undefined"); - } - else - { - ostringstream buf; - int bankno = bank & myCart.BIT_BANK_MASK; - - if(bank & myCart.BITMASK_ROMRAM) // was RAM mapped here? - { - if(bank & myCart.BITMASK_LOWERUPPER) // upper is write port - { - buf << "RAM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER) << " (W)"; - myBankState[i]->setText(buf.str()); - } - else - { - buf << "RAM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER) << " (R)"; - myBankState[i]->setText(buf.str()); - } - } - else - { - if(bank & myCart.BITMASK_LOWERUPPER) // upper is high 512b - { - buf << "ROM " << bankno << " @ $" << Common::Base::HEX4 - << ((bankno << myCart.RAM_BANK_TO_POWER) + myCart.RAM_BANK_SIZE); - myBankState[i]->setText(buf.str()); - } - else - { - buf << "ROM " << bankno << " @ $" << Common::Base::HEX4 - << (bankno << myCart.RAM_BANK_TO_POWER); - myBankState[i]->setText(buf.str()); - } - } - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeDASHWidget::internalRamSize() -{ - return 32*1024; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeDASHWidget::internalRamRPort(int start) -{ - return 0x0000 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDASHWidget::internalRamDescription() -{ - ostringstream desc; - desc << "Accessible 512b at a time via:\n" - << " $F000/$F200/$F400/etc used for Read Access\n" - << " $F800/$FA00/$FC00/etc used for Write Access (+$800)"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeDASHWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeDASHWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASHWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeDASHWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const std::array CartridgeDASHWidget::bankEnum = { - kBank0Changed, kBank1Changed, kBank2Changed, kBank3Changed -}; diff --git a/src/debugger/gui/CartDASHWidget.hxx b/src/debugger/gui/CartDASHWidget.hxx deleted file mode 100644 index e738c2292..000000000 --- a/src/debugger/gui/CartDASHWidget.hxx +++ /dev/null @@ -1,86 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef CARTRIDGEDASH_WIDGET_HXX -#define CARTRIDGEDASH_WIDGET_HXX - -class CartridgeDASH; -class ButtonWidget; -class EditTextWidget; -class PopUpWidget; - -#include "CartDebugWidget.hxx" - -class CartridgeDASHWidget : public CartDebugWidget -{ - public: - CartridgeDASHWidget(GuiObject* boss, const GUI::Font& lfont, - const GUI::Font& nfont, - int x, int y, int w, int h, - CartridgeDASH& cart); - virtual ~CartridgeDASHWidget() = default; - - private: - void updateUIState(); - - private: - CartridgeDASH& myCart; - - std::array myBankNumber{nullptr}; - std::array myBankType{nullptr}; - std::array myBankCommit{nullptr}; - std::array myBankState{nullptr}; - - struct CartState { - ByteArray internalram; - }; - CartState myOldState; - - enum BankID { - kBank0Changed = 'b0CH', - kBank1Changed = 'b1CH', - kBank2Changed = 'b2CH', - kBank3Changed = 'b3CH' - }; - static const std::array bankEnum; - - private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - // end of functions for Cartridge RAM tab - - // Following constructors and assignment operators not supported - CartridgeDASHWidget() = delete; - CartridgeDASHWidget(const CartridgeDASHWidget&) = delete; - CartridgeDASHWidget(CartridgeDASHWidget&&) = delete; - CartridgeDASHWidget& operator=(const CartridgeDASHWidget&) = delete; - CartridgeDASHWidget& operator=(CartridgeDASHWidget&&) = delete; -}; - -#endif diff --git a/src/debugger/gui/CartDFSCWidget.cxx b/src/debugger/gui/CartDFSCWidget.cxx index e03fbf1c6..ed792acb4 100644 --- a/src/debugger/gui/CartDFSCWidget.cxx +++ b/src/debugger/gui/CartDFSCWidget.cxx @@ -15,185 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartDFSC.hxx" -#include "PopUpWidget.hxx" #include "CartDFSCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDFSCWidget::CartridgeDFSCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeDFSC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 32 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeDFSCWidget::description() +{ ostringstream info; - info << "128K DFSC + RAM, 32 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFC0; i < 32; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << (start + 0x100) - << " - " << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "128K DFSC + RAM, 32 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "CPUWIZ", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FFC0)"); - VarList::push_back(items, " 1 ($FFC1)"); - VarList::push_back(items, " 2 ($FFC2)"); - VarList::push_back(items, " 3 ($FFC3)"); - VarList::push_back(items, " 4 ($FFC4)"); - VarList::push_back(items, " 5 ($FFC5)"); - VarList::push_back(items, " 6 ($FFC6)"); - VarList::push_back(items, " 7 ($FFC7)"); - VarList::push_back(items, " 8 ($FFC8)"); - VarList::push_back(items, " 9 ($FFC9)"); - VarList::push_back(items, "10 ($FFCA)"); - VarList::push_back(items, "11 ($FFCB)"); - VarList::push_back(items, "12 ($FFCC)"); - VarList::push_back(items, "13 ($FFCD)"); - VarList::push_back(items, "14 ($FFCE)"); - VarList::push_back(items, "15 ($FFCF)"); - VarList::push_back(items, "16 ($FFD0)"); - VarList::push_back(items, "17 ($FFD1)"); - VarList::push_back(items, "18 ($FFD2)"); - VarList::push_back(items, "19 ($FFD3)"); - VarList::push_back(items, "20 ($FFD4)"); - VarList::push_back(items, "21 ($FFD5)"); - VarList::push_back(items, "22 ($FFD6)"); - VarList::push_back(items, "23 ($FFD7)"); - VarList::push_back(items, "24 ($FFD8)"); - VarList::push_back(items, "25 ($FFD9)"); - VarList::push_back(items, "26 ($FFDA)"); - VarList::push_back(items, "27 ($FFDB)"); - VarList::push_back(items, "28 ($FFDC)"); - VarList::push_back(items, "29 ($FFDD)"); - VarList::push_back(items, "30 ($FFDE)"); - VarList::push_back(items, "31 ($FFDF)"); - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("31 ($FFE0)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDFSCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFC0", "$FFC1", "$FFC2", "$FFC3", "$FFC4", "$FFC5", "$FFC6", "$FFC7", - "$FFC8", "$FFC9", "$FFCA", "$FFCB", "$FFCC", "$FFCD", "$FFCE", "$FFCF", - "$FFD0", "$FFD1", "$FFD2", "$FFD3", "$FFD4", "$FFD5", "$FFD6", "$FFE7", - "$FFD8", "$FFD9", "$FFDA", "$FFDB", "$FFDC", "$FFDD", "$FFDE", "$FFDF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeDFSCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeDFSCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDFSCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeDFSCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeDFSCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeDFSCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDFSCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartDFSCWidget.hxx b/src/debugger/gui/CartDFSCWidget.hxx index 4d4a07feb..9e4481fa8 100644 --- a/src/debugger/gui/CartDFSCWidget.hxx +++ b/src/debugger/gui/CartDFSCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEDFSC_WIDGET_HXX class CartridgeDFSC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeDFSCWidget : public CartDebugWidget +class CartridgeDFSCWidget : public CartridgeEnhancedWidget { public: CartridgeDFSCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,35 +32,11 @@ class CartridgeDFSCWidget : public CartDebugWidget virtual ~CartridgeDFSCWidget() = default; private: - CartridgeDFSC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "CPUWIZ"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeDFSCWidget() = delete; CartridgeDFSCWidget(const CartridgeDFSCWidget&) = delete; diff --git a/src/debugger/gui/CartDFWidget.cxx b/src/debugger/gui/CartDFWidget.cxx index c8fde5fff..653588e56 100644 --- a/src/debugger/gui/CartDFWidget.cxx +++ b/src/debugger/gui/CartDFWidget.cxx @@ -16,115 +16,24 @@ //============================================================================ #include "CartDF.hxx" -#include "PopUpWidget.hxx" #include "CartDFWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDFWidget::CartridgeDFWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeDF& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 32 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeDFWidget::description() +{ ostringstream info; - info << "EF 2 cartridge, 32 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFD0; i < 32; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "128K DF, 32 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "CPUWIZ", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FFC0)"); - VarList::push_back(items, " 1 ($FFC1)"); - VarList::push_back(items, " 2 ($FFC2)"); - VarList::push_back(items, " 3 ($FFC3)"); - VarList::push_back(items, " 4 ($FFC4)"); - VarList::push_back(items, " 5 ($FFC5)"); - VarList::push_back(items, " 6 ($FFC6)"); - VarList::push_back(items, " 7 ($FFC7)"); - VarList::push_back(items, " 8 ($FFC8)"); - VarList::push_back(items, " 9 ($FFC9)"); - VarList::push_back(items, "10 ($FFCA)"); - VarList::push_back(items, "11 ($FFCB)"); - VarList::push_back(items, "12 ($FFCC)"); - VarList::push_back(items, "13 ($FFCD)"); - VarList::push_back(items, "14 ($FFCE)"); - VarList::push_back(items, "15 ($FFCF)"); - VarList::push_back(items, "16 ($FFD0)"); - VarList::push_back(items, "17 ($FFD1)"); - VarList::push_back(items, "18 ($FFD2)"); - VarList::push_back(items, "19 ($FFD3)"); - VarList::push_back(items, "20 ($FFD4)"); - VarList::push_back(items, "21 ($FFD5)"); - VarList::push_back(items, "22 ($FFD6)"); - VarList::push_back(items, "23 ($FFD7)"); - VarList::push_back(items, "24 ($FFD8)"); - VarList::push_back(items, "25 ($FFD9)"); - VarList::push_back(items, "26 ($FFDA)"); - VarList::push_back(items, "27 ($FFDB)"); - VarList::push_back(items, "28 ($FFDC)"); - VarList::push_back(items, "29 ($FFDD)"); - VarList::push_back(items, "30 ($FFDE)"); - VarList::push_back(items, "31 ($FFDF)"); - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("31 ($FFDF)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFWidget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeDFWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFC0", "$FFC1", "$FFC2", "$FFC3", "$FFC4", "$FFC5", "$FFC6", "$FFC7", - "$FFC8", "$FFC9", "$FFCA", "$FFCB", "$FFCC", "$FFCD", "$FFCE", "$FFCF", - "$FFD0", "$FFD1", "$FFD2", "$FFD3", "$FFD4", "$FFD5", "$FFD6", "$FFD7", - "$FFD8", "$FFD9", "$FFDA", "$FFDB", "$FFDC", "$FFDD", "$FFDE", "$FFDF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartDFWidget.hxx b/src/debugger/gui/CartDFWidget.hxx index 146763b75..9b45552b9 100644 --- a/src/debugger/gui/CartDFWidget.hxx +++ b/src/debugger/gui/CartDFWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEDF_WIDGET_HXX class CartridgeDF; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeDFWidget : public CartDebugWidget +class CartridgeDFWidget : public CartridgeEnhancedWidget { public: CartridgeDFWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeDFWidget : public CartDebugWidget virtual ~CartridgeDFWidget() = default; private: - CartridgeDF& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "CPUWIZ"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeDFWidget() = delete; CartridgeDFWidget(const CartridgeDFWidget&) = delete; diff --git a/src/debugger/gui/CartDPCPlusWidget.cxx b/src/debugger/gui/CartDPCPlusWidget.cxx index e55da1d1c..18166c6af 100644 --- a/src/debugger/gui/CartDPCPlusWidget.cxx +++ b/src/debugger/gui/CartDPCPlusWidget.cxx @@ -35,7 +35,8 @@ CartridgeDPCPlusWidget::CartridgeDPCPlusWidget( << "DPC registers accessible @ $F000 - $F07F\n" << " $F000 - $F03F (R), $F040 - $F07F (W)\n" << "Banks accessible at hotspots $FFF6 to $FFFB\n" - << "Startup bank = " << cart.startBank() << "\n"; + << "Startup bank = " << cart.startBank() << "\n" + << "Ver = " << cart.myDriverMD5; #if 0 // Eventually, we should query this from the debugger/disassembler diff --git a/src/debugger/gui/CartDPCWidget.cxx b/src/debugger/gui/CartDPCWidget.cxx index c07ae8739..681b3692d 100644 --- a/src/debugger/gui/CartDPCWidget.cxx +++ b/src/debugger/gui/CartDPCWidget.cxx @@ -27,12 +27,13 @@ CartridgeDPCWidget::CartridgeDPCWidget( : CartDebugWidget(boss, lfont, nfont, x, y, w, h), myCart(cart) { + const int V_GAP = 4; size_t size = cart.mySize; - ostringstream info; + info << "DPC cartridge, two 4K banks + 2K display bank\n" - << "DPC registers accessible @ $F000 - $F07F\n" - << " $F000 - $F03F (R), $F040 - $F07F (W)\n" + << "DPC registers accessible @ $" << Common::Base::HEX4 << 0xF000 << " - $" << 0xF07F << "\n" + << " $" << 0xF000 << " - " << 0xF03F << " (R), $" << 0xF040 << " - $" << 0xF07F << " (W)\n" << "Startup bank = " << cart.startBank() << " or undetermined\n"; @@ -42,7 +43,7 @@ CartridgeDPCWidget::CartridgeDPCWidget( uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; start -= start % 0x1000; info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x80) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; + << "$" << (start + 0xFFF) << " (hotspot = $" << (0xF000 + spot + i) << ")\n"; } int xpos = 2, @@ -50,26 +51,30 @@ CartridgeDPCWidget::CartridgeDPCWidget( myLineHeight; VariantList items; - VarList::push_back(items, "0 ($FFF8)"); - VarList::push_back(items, "1 ($FFF9)"); + for(int bank = 0; bank < 2; ++bank) + { + ostringstream buf; + + buf << "#" << std::dec << bank << " ($" << Common::Base::HEX4 << (0xFFF8 + bank) << ")"; + VarList::push_back(items, buf.str()); + } + myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), + new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("#0 ($FFFx)"), myLineHeight, items, "Set bank ", 0, kBankChanged); myBank->setTarget(this); addFocusWidget(myBank); - ypos += myLineHeight + 8; + ypos += myLineHeight + V_GAP * 3; // Data fetchers - int lwidth = _font.getStringWidth("Data Fetchers "); - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Data Fetchers ", TextAlign::Left); + int lwidth = _font.getStringWidth("Data fetchers "); + new StaticTextWidget(boss, _font, xpos, ypos, "Data fetchers "); // Top registers - lwidth = _font.getStringWidth("Counter Registers "); - xpos = 18; ypos += myLineHeight + 4; - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Top Registers ", TextAlign::Left); + lwidth = _font.getStringWidth("Counter registers "); + xpos = 2 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4; + new StaticTextWidget(boss, _font, xpos, ypos, "Top registers "); xpos += lwidth; myTops = new DataGridWidget(boss, _nfont, xpos, ypos-2, 8, 1, 2, 8, Common::Base::Fmt::_16); @@ -77,9 +82,8 @@ CartridgeDPCWidget::CartridgeDPCWidget( myTops->setEditable(false); // Bottom registers - xpos = 10; ypos += myLineHeight + 4; - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Bottom Registers ", TextAlign::Left); + xpos = 2 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4; + new StaticTextWidget(boss, _font, xpos, ypos, "Bottom registers "); xpos += lwidth; myBottoms = new DataGridWidget(boss, _nfont, xpos, ypos-2, 8, 1, 2, 8, Common::Base::Fmt::_16); @@ -87,9 +91,8 @@ CartridgeDPCWidget::CartridgeDPCWidget( myBottoms->setEditable(false); // Counter registers - xpos = 10; ypos += myLineHeight + 4; - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Counter Registers ", TextAlign::Left); + xpos = 2 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4; + new StaticTextWidget(boss, _font, xpos, ypos, "Counter registers "); xpos += lwidth; myCounters = new DataGridWidget(boss, _nfont, xpos, ypos-2, 8, 1, 4, 16, Common::Base::Fmt::_16_4); @@ -97,9 +100,8 @@ CartridgeDPCWidget::CartridgeDPCWidget( myCounters->setEditable(false); // Flag registers - xpos = 10; ypos += myLineHeight + 4; - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Flag Registers ", TextAlign::Left); + xpos = 2 + _font.getMaxCharWidth() * 2; ypos += myLineHeight + 4; + new StaticTextWidget(boss, _font, xpos, ypos, "Flag registers "); xpos += lwidth; myFlags = new DataGridWidget(boss, _nfont, xpos, ypos-2, 8, 1, 2, 8, Common::Base::Fmt::_16); @@ -107,10 +109,9 @@ CartridgeDPCWidget::CartridgeDPCWidget( myFlags->setEditable(false); // Music mode - xpos = 2; ypos += myLineHeight + 12; + xpos = 2; ypos += myLineHeight + V_GAP * 3; lwidth = _font.getStringWidth("Music mode (DF5/DF6/DF7) "); - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Music mode (DF5/DF6/DF7) ", TextAlign::Left); + new StaticTextWidget(boss, _font, xpos, ypos, "Music mode (DF5/DF6/DF7) "); xpos += lwidth; myMusicMode = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 2, 8, Common::Base::Fmt::_16); @@ -118,9 +119,8 @@ CartridgeDPCWidget::CartridgeDPCWidget( myMusicMode->setEditable(false); // Current random number - xpos = 10; ypos += myLineHeight + 4; - new StaticTextWidget(boss, _font, xpos, ypos, lwidth, - myFontHeight, "Current random number ", TextAlign::Left); + xpos = 2; ypos += myLineHeight + V_GAP * 3; + new StaticTextWidget(boss, _font, xpos, ypos, "Current random number "); xpos += lwidth; myRandom = new DataGridWidget(boss, _nfont, xpos, ypos-2, 1, 1, 2, 8, Common::Base::Fmt::_16); @@ -229,9 +229,8 @@ string CartridgeDPCWidget::bankState() { ostringstream& buf = buffer(); - static constexpr std::array spot = { "$FFF8", "$FFF9" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; + buf << "Bank #" << std::dec << myCart.getBank() + << " (hotspot $" << Common::Base::HEX4 << (0xFFF8 + myCart.getBank()) << ")"; return buf.str(); } @@ -252,10 +251,9 @@ uInt32 CartridgeDPCWidget::internalRamRPort(int start) string CartridgeDPCWidget::internalRamDescription() { ostringstream desc; - desc << "$0000 - $07FF - 2K display data\n" - << " indirectly accessible to 6507\n" - << " via DPC+'s Data Fetcher\n" - << " registers\n"; + desc << "2K display data @ $0000 - $" << Common::Base::HEX4 << 0x07FF << "\n" + << " indirectly accessible to 6507 via DPC's\n" + << " data fetcher registers\n"; return desc.str(); } diff --git a/src/debugger/gui/CartDPCWidget.hxx b/src/debugger/gui/CartDPCWidget.hxx index ff57ddc1d..0a675a2c8 100644 --- a/src/debugger/gui/CartDPCWidget.hxx +++ b/src/debugger/gui/CartDPCWidget.hxx @@ -75,6 +75,7 @@ class CartridgeDPCWidget : public CartDebugWidget const ByteArray& internalRamCurrent(int start, int count) override; void internalRamSetValue(int addr, uInt8 value) override; uInt8 internalRamGetValue(int addr) override; + string tabLabel() override { return " DPC Display Data "; } // end of functions for Cartridge RAM tab // Following constructors and assignment operators not supported diff --git a/src/debugger/gui/CartDebugWidget.cxx b/src/debugger/gui/CartDebugWidget.cxx index 9e164f4a6..b04000328 100644 --- a/src/debugger/gui/CartDebugWidget.cxx +++ b/src/debugger/gui/CartDebugWidget.cxx @@ -42,14 +42,14 @@ int CartDebugWidget::addBaseInformation(size_t bytes, const string& manufacturer const string& desc, const uInt16 maxlines) { const int lwidth = _font.getStringWidth("Manufacturer "), - fwidth = _w - lwidth - 20; + fwidth = _w - lwidth - 12; EditTextWidget* w = nullptr; ostringstream buf; int x = 2, y = 8; // Add ROM size, manufacturer and bankswitch info - new StaticTextWidget(_boss, _font, x, y + 1, "ROM Size "); + new StaticTextWidget(_boss, _font, x, y + 1, "ROM size "); buf << bytes << " bytes"; if(bytes >= 1024) buf << " / " << (bytes/1024) << "KB"; @@ -65,7 +65,7 @@ int CartDebugWidget::addBaseInformation(size_t bytes, const string& manufacturer w->setEditable(false); y += myLineHeight + 4; - StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth - 4); + StringParser bs(desc, (fwidth - ScrollBarWidget::scrollBarWidth(_font)) / myFontWidth - 4); const StringList& sl = bs.stringList(); uInt32 lines = uInt32(sl.size()); if(lines < 3) lines = 3; diff --git a/src/debugger/gui/CartDebugWidget.hxx b/src/debugger/gui/CartDebugWidget.hxx index 7789cbb16..27c3befa5 100644 --- a/src/debugger/gui/CartDebugWidget.hxx +++ b/src/debugger/gui/CartDebugWidget.hxx @@ -19,7 +19,6 @@ #define CART_DEBUG_WIDGET_HXX class GuiObject; -class ButtonWidget; class StringListWidget; namespace GUI { @@ -29,8 +28,6 @@ namespace GUI { #include "Base.hxx" // not needed here, but all child classes need it #include "Command.hxx" #include "Widget.hxx" -#include "Debugger.hxx" -#include "CartDebug.hxx" class CartDebugWidget : public Widget, public CommandSender { @@ -58,7 +55,7 @@ class CartDebugWidget : public Widget, public CommandSender virtual string bankState() { return "0 (non-bankswitched)"; } // To make the Cartridge RAM show up in the debugger, implement - // the following 8 functions for cartridges with internal RAM + // the following 9 functions for cartridges with internal RAM virtual uInt32 internalRamSize() { return 0; } virtual uInt32 internalRamRPort(int start) { return 0; } virtual string internalRamDescription() { return EmptyString; } @@ -67,6 +64,7 @@ class CartDebugWidget : public Widget, public CommandSender virtual void internalRamSetValue(int addr, uInt8 value) { } virtual uInt8 internalRamGetValue(int addr) { return 0; } virtual string internalRamLabel(int addr) { return "Not available/applicable"; } + virtual string tabLabel() { return " Cartridge RAM "; } protected: // Arrays used to hold current and previous internal RAM values diff --git a/src/debugger/gui/CartE0Widget.cxx b/src/debugger/gui/CartE0Widget.cxx index 9413ce5c0..08ccc802a 100644 --- a/src/debugger/gui/CartE0Widget.cxx +++ b/src/debugger/gui/CartE0Widget.cxx @@ -16,129 +16,59 @@ //============================================================================ #include "CartE0.hxx" -#include "PopUpWidget.hxx" #include "CartE0Widget.hxx" -static constexpr std::array seg0 = { - "0 ($FFE0)", "1 ($FFE1)", "2 ($FFE2)", "3 ($FFE3)", - "4 ($FFE4)", "5 ($FFE5)", "6 ($FFE6)", "7 ($FFE7)" -}; -static constexpr std::array seg1 = { - "0 ($FFE8)", "1 ($FFE9)", "2 ($FFEA)", "3 ($FFEB)", - "4 ($FFEC)", "5 ($FFED)", "6 ($FFEE)", "7 ($FFEF)" -}; -static constexpr std::array seg2 = { - "0 ($FFF0)", "1 ($FFF1)", "2 ($FFF2)", "3 ($FFF3)", - "4 ($FFF4)", "5 ($FFF5)", "6 ($FFF6)", "7 ($FFF7)" -}; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeE0Widget::CartridgeE0Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeE0& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 8 * 1024; + initialize(); +} - string info = - "E0 cartridge, eight 1K slices\n" - "Segment 0 accessible @ $F000 - $F3FF\n" - " Hotspots $FE0 to $FE7\n" - "Segment 1 accessible @ $F400 - $F7FF\n" - " Hotspots $FE8 to $FEF\n" - "Segment 2 accessible @ $F800 - $FBFF\n" - " Hotspots $FF0 to $FF7\n" - "Segment 3 accessible @ $FC00 - $FFFF\n" - " Always points to last 1K of ROM\n" - "Startup slices = 4 / 5 / 6 or undetermined\n"; +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeE0Widget::description() +{ + ostringstream info; -#if 0 - // Eventually, we should query this from the debugger/disassembler - uInt16 start = (cart.myImage[size-3] << 8) | cart.myImage[size-4]; - start -= start % 0x1000; - info << "Bank RORG" << " = $" << HEX4 << start << "\n"; -#endif - int xpos = 2, - ypos = addBaseInformation(size, "Parker Brothers", info) + myLineHeight; + info << "E0 cartridge,\n eight 1K banks mapped into four segments\n"; + info << CartridgeEnhancedWidget::description(); - VariantList items0, items1, items2; - for(int i = 0; i < 8; ++i) + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeE0Widget::romDescription() +{ + ostringstream info; + + for(int seg = 0; seg < 4; ++seg) { - VarList::push_back(items0, seg0[i]); - VarList::push_back(items1, seg1[i]); - VarList::push_back(items2, seg2[i]); + uInt16 segmentOffset = seg << 10; // myCart.myBankShift; + + info << "Segment #" << seg << " accessible @ $" + << Common::Base::HEX4 << (ADDR_BASE | segmentOffset) + << " - $" << (ADDR_BASE | (segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF)) << ",\n"; + if (seg < 3) + info << " Hotspots " << hotspotStr(0, seg, true) << " - " << hotspotStr(7, seg, true) << "\n"; + else + info << " Always points to last 1K bank of ROM\n"; } + info << "Startup banks = 4 / 5 / 6 or undetermined"; - const int lwidth = _font.getStringWidth("Set slice for segment X "); - mySlice0 = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("7 ($FFF7)"), - myLineHeight, items0, "Set slice for segment 0 ", - lwidth, kSlice0Changed); - mySlice0->setTarget(this); - addFocusWidget(mySlice0); - ypos += mySlice0->getHeight() + 4; - - mySlice1 = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("7 ($FFF7)"), - myLineHeight, items1, "Set slice for segment 1 ", - lwidth, kSlice1Changed); - mySlice1->setTarget(this); - addFocusWidget(mySlice1); - ypos += mySlice1->getHeight() + 4; - - mySlice2 = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("7 ($FFF7)"), - myLineHeight, items2, "Set slice for segment 2 ", - lwidth, kSlice2Changed); - mySlice2->setTarget(this); - addFocusWidget(mySlice2); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0Widget::loadConfig() +string CartridgeE0Widget::hotspotStr(int bank, int segment, bool noBrackets) { - mySlice0->setSelectedIndex(myCart.myCurrentSlice[0]); - mySlice1->setSelectedIndex(myCart.myCurrentSlice[1]); - mySlice2->setSelectedIndex(myCart.myCurrentSlice[2]); + ostringstream info; + uInt16 hotspot = myCart.hotspot(); - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - myCart.unlockBank(); - - switch(cmd) - { - case kSlice0Changed: - myCart.segmentZero(mySlice0->getSelected()); - break; - case kSlice1Changed: - myCart.segmentOne(mySlice1->getSelected()); - break; - case kSlice2Changed: - myCart.segmentTwo(mySlice2->getSelected()); - break; - default: - break; - } - - myCart.lockBank(); - invalidate(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeE0Widget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Slices: " << std::dec - << seg0[myCart.myCurrentSlice[0]] << " / " - << seg1[myCart.myCurrentSlice[1]] << " / " - << seg2[myCart.myCurrentSlice[2]]; - - return buf.str(); + info << (noBrackets ? "" : "("); + info << "$" << Common::Base::HEX1 << (hotspot + bank + segment * 8); + info << (noBrackets ? "" : ")"); + + return info.str(); } diff --git a/src/debugger/gui/CartE0Widget.hxx b/src/debugger/gui/CartE0Widget.hxx index bdbe73182..a50893e84 100644 --- a/src/debugger/gui/CartE0Widget.hxx +++ b/src/debugger/gui/CartE0Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEE0_WIDGET_HXX class CartridgeE0; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeE0Widget : public CartDebugWidget +class CartridgeE0Widget : public CartridgeEnhancedWidget { public: CartridgeE0Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,21 +32,17 @@ class CartridgeE0Widget : public CartDebugWidget virtual ~CartridgeE0Widget() = default; private: - CartridgeE0& myCart; - PopUpWidget *mySlice0{nullptr}, *mySlice1{nullptr}, *mySlice2{nullptr}; + string manufacturer() override { return "Parker Brothers"; } - enum { - kSlice0Changed = 's0CH', - kSlice1Changed = 's1CH', - kSlice2Changed = 's2CH' - }; + string description() override; + + string romDescription() override; + + string hotspotStr(int bank, int segment, bool noBrackets = false) override; + + uInt16 bankSegs() override { return 3; } private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeE0Widget() = delete; CartridgeE0Widget(const CartridgeE0Widget&) = delete; diff --git a/src/debugger/gui/CartE78KWidget.cxx b/src/debugger/gui/CartE78KWidget.cxx index b14d24809..2ad1c012e 100644 --- a/src/debugger/gui/CartE78KWidget.cxx +++ b/src/debugger/gui/CartE78KWidget.cxx @@ -27,17 +27,18 @@ CartridgeE78KWidget::CartridgeE78KWidget( : CartridgeMNetworkWidget(boss, lfont, nfont, x, y, w, h, cart) { ostringstream info; - info << "E78K cartridge, 4 2K slices ROM + 2 1K RAM\n" - << "Lower 2K accessible @ $F000 - $F7FF\n" - << " Slice 0 - 2 of ROM (hotspots $FE4 to $FE6)\n" - << " Slice 7 (1K) of RAM (hotspot $FE7)\n" - << " $F400 - $F7FF (R), $F000 - $F3FF (W)\n" - << "256B RAM accessible @ $F800 - $F9FF\n" - << " Hotspots $FE8 - $FEB (256B of RAM slice 1)\n" - << " $F900 - $F9FF (R), $F800 - $F8FF (W)\n" - << "Upper 1.5K ROM accessible @ $FA00 - $FFFF\n" - << " Always points to last 1.5K of ROM\n" - << "Startup slices = 0 / 0 or undetermined\n"; + info << "E78K cartridge, four 2K banks ROM + 2K RAM,\n" + << " mapped into three segments\n" + << "Lower 2K accessible @ $F000 - $F7FF\n" + << " ROM banks 0 - 2 (hotspots $FFE4 to $FFE6)\n" + << " 1K RAM bank 3 (hotspot $FFE7)\n" + << " $F400 - $F7FF (R), $F000 - $F3FF (W)\n" + << "256B RAM accessible @ $F800 - $F9FF\n" + << " RAM banks 0 - 3 (hotspots $FFE8 - $FFEB)\n" + << " $F900 - $F9FF (R), $F800 - $F8FF (W)\n" + << "Upper 1.5K ROM accessible @ $FA00 - $FFFF\n" + << " Always points to last 1.5K of ROM\n" + << "Startup segments = 0 / 0 or undetermined\n"; #if 0 // Eventually, we should query this from the debugger/disassembler @@ -53,7 +54,7 @@ CartridgeE78KWidget::CartridgeE78KWidget( const char* CartridgeE78KWidget::getSpotLower(int idx) { static constexpr std::array spot_lower = { - "0 - ROM ($FFE4)", "1 - ROM ($FFE5)", "2 - ROM ($FFE6)", "3 - RAM ($FFE7)" + "#0 - ROM ($FFE4)", "#1 - ROM ($FFE5)", "#2 - ROM ($FFE6)", "#3 - RAM ($FFE7)" }; return spot_lower[idx]; @@ -63,7 +64,7 @@ const char* CartridgeE78KWidget::getSpotLower(int idx) const char* CartridgeE78KWidget::getSpotUpper(int idx) { static constexpr std::array spot_upper = { - "0 - RAM ($FFE8)", "1 - RAM ($FFE9)", "2 - RAM ($FFEA)", "3 - RAM ($FFEB)" + "#0 - RAM ($FFE8)", "#1 - RAM ($FFE9)", "#2 - RAM ($FFEA)", "#3 - RAM ($FFEB)" }; return spot_upper[idx]; diff --git a/src/debugger/gui/CartE7Widget.cxx b/src/debugger/gui/CartE7Widget.cxx index f4a5ea3dd..8546e84eb 100644 --- a/src/debugger/gui/CartE7Widget.cxx +++ b/src/debugger/gui/CartE7Widget.cxx @@ -26,17 +26,18 @@ CartridgeE7Widget::CartridgeE7Widget( : CartridgeMNetworkWidget(boss, lfont, nfont, x, y, w, h, cart) { ostringstream info; - info << "E7 cartridge, 8 2K slices ROM + 2 1K RAM\n" + info << "E7 cartridge, eight 2K banks ROM + 2K RAM,\n" + << " mapped into three segments\n" << "Lower 2K accessible @ $F000 - $F7FF\n" - << " Slice 0 - 6 of ROM (hotspots $FE0 to $FE6)\n" - << " Slice 7 (1K) of RAM (hotspot $FE7)\n" + << " ROM Banks 0 - 6 (hotspots $FFE0 to $FFE6)\n" + << " 1K RAM Bank 7 (hotspot $FFE7)\n" << " $F400 - $F7FF (R), $F000 - $F3FF (W)\n" << "256B RAM accessible @ $F800 - $F9FF\n" - << " Hotspots $FE8 - $FEB (256B of RAM slice 1)\n" + << " RAM banks 0 - 3 (hotspots $FFE8 - $FFEB)\n" << " $F900 - $F9FF (R), $F800 - $F8FF (W)\n" << "Upper 1.5K ROM accessible @ $FA00 - $FFFF\n" << " Always points to last 1.5K of ROM\n" - << "Startup slices = 0 / 0 or undetermined\n"; + << "Startup segments = 0 / 0 or undetermined\n"; #if 0 // Eventually, we should query this from the debugger/disassembler @@ -52,8 +53,8 @@ CartridgeE7Widget::CartridgeE7Widget( const char* CartridgeE7Widget::getSpotLower(int idx) { static constexpr std::array spot_lower = { - "0 - ROM ($FFE0)", "1 - ROM ($FFE1)", "2 - ROM ($FFE2)", "3 - ROM ($FFE3)", - "4 - ROM ($FFE4)", "5 - ROM ($FFE5)", "6 - ROM ($FFE6)", "7 - RAM ($FFE7)" + "#0 - ROM ($FFE0)", "#1 - ROM ($FFE1)", "#2 - ROM ($FFE2)", "#3 - ROM ($FFE3)", + "#4 - ROM ($FFE4)", "#5 - ROM ($FFE5)", "#6 - ROM ($FFE6)", "#7 - RAM ($FFE7)" }; return spot_lower[idx]; @@ -63,7 +64,7 @@ const char* CartridgeE7Widget::getSpotLower(int idx) const char* CartridgeE7Widget::getSpotUpper(int idx) { static constexpr std::array spot_upper = { - "0 - RAM ($FFE8)", "1 - RAM ($FFE9)", "2 - RAM ($FFEA)", "3 - RAM ($FFEB)" + "#0 - RAM ($FFE8)", "#1 - RAM ($FFE9)", "#2 - RAM ($FFEA)", "#3 - RAM ($FFEB)" }; return spot_upper[idx]; diff --git a/src/debugger/gui/CartEFSCWidget.cxx b/src/debugger/gui/CartEFSCWidget.cxx index a7bae36c7..d6f60ddba 100644 --- a/src/debugger/gui/CartEFSCWidget.cxx +++ b/src/debugger/gui/CartEFSCWidget.cxx @@ -15,167 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartEFSC.hxx" -#include "PopUpWidget.hxx" #include "CartEFSCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeEFSCWidget::CartridgeEFSCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeEFSC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 16 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEFSCWidget::description() +{ ostringstream info; - info << "64K H. Runner EFSC + RAM, 16 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFE0; i < 16; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << (start + 0x100) - << " - " << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "64K H. Runner EFSC + RAM, 16 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Paul Slocum / Homestar Runner", - info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FFE0)"); - VarList::push_back(items, " 1 ($FFE1)"); - VarList::push_back(items, " 2 ($FFE2)"); - VarList::push_back(items, " 3 ($FFE3)"); - VarList::push_back(items, " 4 ($FFE4)"); - VarList::push_back(items, " 5 ($FFE5)"); - VarList::push_back(items, " 6 ($FFE6)"); - VarList::push_back(items, " 7 ($FFE7)"); - VarList::push_back(items, " 8 ($FFE8)"); - VarList::push_back(items, " 9 ($FFE9)"); - VarList::push_back(items, "10 ($FFEA)"); - VarList::push_back(items, "11 ($FFEB)"); - VarList::push_back(items, "12 ($FFEC)"); - VarList::push_back(items, "13 ($FFED)"); - VarList::push_back(items, "14 ($FFEE)"); - VarList::push_back(items, "15 ($FFEF)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("15 ($FFE0)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeEFSCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFE0", "$FFE1", "$FFE2", "$FFE3", "$FFE4", "$FFE5", "$FFE6", "$FFE7", - "$FFE8", "$FFE9", "$FFEA", "$FFEB", "$FFEC", "$FFED", "$FFEE", "$FFEF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeEFSCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeEFSCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeEFSCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeEFSCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeEFSCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeEFSCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeEFSCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartEFSCWidget.hxx b/src/debugger/gui/CartEFSCWidget.hxx index b9e902f69..975f17f8a 100644 --- a/src/debugger/gui/CartEFSCWidget.hxx +++ b/src/debugger/gui/CartEFSCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEEFSC_WIDGET_HXX class CartridgeEFSC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeEFSCWidget : public CartDebugWidget +class CartridgeEFSCWidget : public CartridgeEnhancedWidget { public: CartridgeEFSCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,35 +32,11 @@ class CartridgeEFSCWidget : public CartDebugWidget virtual ~CartridgeEFSCWidget() = default; private: - CartridgeEFSC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Paul Slocum / Homestar Runner"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeEFSCWidget() = delete; CartridgeEFSCWidget(const CartridgeEFSCWidget&) = delete; diff --git a/src/debugger/gui/CartEFWidget.cxx b/src/debugger/gui/CartEFWidget.cxx index 165c205bf..c00d2c3f6 100644 --- a/src/debugger/gui/CartEFWidget.cxx +++ b/src/debugger/gui/CartEFWidget.cxx @@ -16,97 +16,24 @@ //============================================================================ #include "CartEF.hxx" -#include "PopUpWidget.hxx" #include "CartEFWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeEFWidget::CartridgeEFWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeEF& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 16 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEFWidget::description() +{ ostringstream info; - info << "64K H. Runner EF cartridge, 16 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFE0; i < 16; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "64K H. Runner EF cartridge, 16 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Paul Slocum / Homestar Runner", - info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0 ($FFE0)"); - VarList::push_back(items, " 1 ($FFE1)"); - VarList::push_back(items, " 2 ($FFE2)"); - VarList::push_back(items, " 3 ($FFE3)"); - VarList::push_back(items, " 4 ($FFE4)"); - VarList::push_back(items, " 5 ($FFE5)"); - VarList::push_back(items, " 6 ($FFE6)"); - VarList::push_back(items, " 7 ($FFE7)"); - VarList::push_back(items, " 8 ($FFE8)"); - VarList::push_back(items, " 9 ($FFE9)"); - VarList::push_back(items, "10 ($FFEA)"); - VarList::push_back(items, "11 ($FFEB)"); - VarList::push_back(items, "12 ($FFEC)"); - VarList::push_back(items, "13 ($FFED)"); - VarList::push_back(items, "14 ($FFEE)"); - VarList::push_back(items, "15 ($FFEF)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("15 ($FFE0)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFWidget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeEFWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFE0", "$FFE1", "$FFE2", "$FFE3", "$FFE4", "$FFE5", "$FFE6", "$FFE7", - "$FFE8", "$FFE9", "$FFEA", "$FFEB", "$FFEC", "$FFED", "$FFEE", "$FFEF" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartEFWidget.hxx b/src/debugger/gui/CartEFWidget.hxx index 3f34fa6cb..7d173836a 100644 --- a/src/debugger/gui/CartEFWidget.hxx +++ b/src/debugger/gui/CartEFWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEEF_WIDGET_HXX class CartridgeEF; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeEFWidget : public CartDebugWidget +class CartridgeEFWidget : public CartridgeEnhancedWidget { public: CartridgeEFWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeEFWidget : public CartDebugWidget virtual ~CartridgeEFWidget() = default; private: - CartridgeEF& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Paul Slocum / Homestar Runner"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeEFWidget() = delete; CartridgeEFWidget(const CartridgeEFWidget&) = delete; diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx new file mode 100644 index 000000000..97beb1f6b --- /dev/null +++ b/src/debugger/gui/CartEnhancedWidget.cxx @@ -0,0 +1,396 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "PopUpWidget.hxx" +#include "OSystem.hxx" +#include "Debugger.hxx" +#include "CartDebug.hxx" +#include "CartEnhanced.hxx" +#include "CartEnhancedWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeEnhancedWidget::CartridgeEnhancedWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartridgeEnhanced& cart) + : CartDebugWidget(boss, lfont, nfont, x, y, w, h), + myCart(cart) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeEnhancedWidget::initialize() +{ + int ypos = addBaseInformation(size(), manufacturer(), description(), descriptionLines()) + + myLineHeight; + + bankSelect(ypos); + + return ypos; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t CartridgeEnhancedWidget::size() +{ + size_t size; + + myCart.getImage(size); + + return size; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::description() +{ + ostringstream info; + + if (myCart.myRamSize > 0) + info << ramDescription(); + info << romDescription(); + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int CartridgeEnhancedWidget::descriptionLines() +{ + return 18; // should be enough for almost all types +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::ramDescription() +{ + ostringstream info; + + if(myCart.ramBankCount() == 0) + info << myCart.myRamSize << " bytes RAM @ " + << "$" << Common::Base::HEX4 << ADDR_BASE << " - " + << "$" << (ADDR_BASE | (myCart.myRamSize * 2 - 1)) << "\n"; + + info << " $" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset) + << " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask)) << " (R)" + << ", $" << (ADDR_BASE | myCart.myWriteOffset) + << " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamMask)) << " (W)\n"; + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::romDescription() +{ + ostringstream info; + size_t size; + const ByteBuffer& image = myCart.getImage(size); + + if(myCart.romBankCount() > 1) + { + for(int bank = 0, offset = 0xFFC; bank < myCart.romBankCount(); ++bank, offset += 0x1000) + { + uInt16 start = (image[offset + 1] << 8) | image[offset]; + start -= start % 0x1000; + string hash = myCart.romBankCount() > 10 && bank < 10 ? " #" : "#"; + + info << "Bank " << hash << std::dec << bank << " @ $" + << Common::Base::HEX4 << (start + myCart.myRomOffset) << " - $" << (start + 0xFFF); + if(myCart.hotspot() != 0) + { + string hs = hotspotStr(bank, 0, true); + if(hs.length() > 22) + info << "\n "; + info << " " << hs; + } + info << "\n"; + } + info << "Startup bank = #" << std::dec << myCart.startBank() << " or undetermined\n"; + } + else + { + uInt16 start = (image[myCart.mySize - 3] << 8) | image[myCart.mySize - 4]; + uInt16 end; + + start -= start % std::min(int(size), 0x1000); + end = start + uInt16(myCart.mySize) - 1; + // special check for ROMs where the extra RAM is not included in the image (e.g. CV). + if((start & 0xFFFU) < size) + { + start += myCart.myRomOffset; + } + info << "ROM accessible @ $" + << Common::Base::HEX4 << start << " - $" + << Common::Base::HEX4 << end; + } + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::bankList(uInt16 bankCount, int seg, VariantList& items, int& width) +{ + width = 0; + + for(int bank = 0; bank < bankCount; ++bank) + { + ostringstream buf; + + buf << std::setw(bank < 10 ? 2 : 1) << "#" << std::dec << bank; + if(myCart.hotspot() != 0 && myHotspotDelta > 0) + buf << " " << hotspotStr(bank, seg); + VarList::push_back(items, buf.str()); + width = std::max(width, _font.getStringWidth(buf.str())); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::bankSelect(int& ypos) +{ + if(myCart.romBankCount() > 1) + { + int xpos = 2; + + myBankWidgets = make_unique(bankSegs()); + + for(int seg = 0; seg < bankSegs(); ++seg) + { + // fill bank and hotspot list + VariantList items; + int pw = 0; + + bankList(myCart.romBankCount(), seg, items, pw); + + // create widgets + ostringstream buf; + + buf << "Set bank"; + if(bankSegs() > 1) + buf << " for segment #" << seg << " "; + else + buf << " "; // align with info + + myBankWidgets[seg] = new PopUpWidget(_boss, _font, xpos, ypos - 2, + pw, myLineHeight, items, buf.str(), + 0, kBankChanged); + myBankWidgets[seg]->setTarget(this); + myBankWidgets[seg]->setID(seg); + addFocusWidget(myBankWidgets[seg]); + + ypos += myBankWidgets[seg]->getHeight() + 4; + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::bankState() +{ + if(myCart.romBankCount() > 1) + { + ostringstream& buf = buffer(); + uInt16 hotspot = myCart.hotspot(); + bool hasRamBanks = myCart.myRamBankCount > 0; + + if(bankSegs() > 1) + { + buf << "Segments: "; + + for(int seg = 0; seg < bankSegs(); ++seg) + { + int bank = myCart.getSegmentBank(seg); + bool isRamBank = (bank >= myCart.romBankCount()); + + + if(seg > 0) + buf << " / "; + + buf << "#" << std::dec << (bank - (isRamBank ? myCart.romBankCount() : 0)); + + if(isRamBank) // was RAM mapped here? + buf << " RAM"; + else if (hasRamBanks) + buf << " ROM"; + + //if(hotspot >= 0x100) + if(hotspot != 0 && myHotspotDelta > 0) + buf << " " << hotspotStr(bank, 0, bankSegs() < 3); + } + } + else + { + buf << "Bank #" << std::dec << myCart.getBank(); + + if(hotspot != 0 && myHotspotDelta > 0) + buf << " " << hotspotStr(myCart.getBank(), 0, true); + } + return buf.str(); + } + return "non-bankswitched"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::hotspotStr(int bank, int segment, bool prefix) +{ + ostringstream info; + uInt16 hotspot = myCart.hotspot(); + + if(hotspot & 0x1000) + hotspot |= ADDR_BASE; + + info << "(" << (prefix ? "hotspot " : ""); + info << "$" << Common::Base::HEX1 << (hotspot + bank * myHotspotDelta); + info << ")"; + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeEnhancedWidget::bankSegs() +{ + return myCart.myBankSegs; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::saveOldState() +{ + myOldState.internalRam.clear(); + for(uInt32 i = 0; i < myCart.myRamSize; ++i) + myOldState.internalRam.push_back(myCart.myRAM[i]); + + myOldState.banks.clear(); + if (bankSegs() > 1) + for(int seg = 0; seg < bankSegs(); ++seg) + myOldState.banks.push_back(myCart.getSegmentBank(seg)); + else + myOldState.banks.push_back(myCart.getBank()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::loadConfig() +{ + if(myBankWidgets != nullptr) + { + if (bankSegs() > 1) + for(int seg = 0; seg < bankSegs(); ++seg) + myBankWidgets[seg]->setSelectedIndex(myCart.getSegmentBank(seg), + myCart.getSegmentBank(seg) != myOldState.banks[seg]); + else + myBankWidgets[0]->setSelectedIndex(myCart.getBank(), + myCart.getBank() != myOldState.banks[0]); + } + CartDebugWidget::loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::handleCommand(CommandSender* sender, + int cmd, int data, int id) +{ + if(cmd == kBankChanged) + { + myCart.unlockBank(); + myCart.bank(myBankWidgets[id]->getSelected(), id); + myCart.lockBank(); + invalidate(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 CartridgeEnhancedWidget::internalRamSize() +{ + return uInt32(myCart.myRamSize); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 CartridgeEnhancedWidget::internalRamRPort(int start) +{ + if(myCart.ramBankCount() == 0) + return ADDR_BASE + myCart.myReadOffset + start; + else + return start; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::internalRamDescription() +{ + ostringstream desc; + string indent = ""; + + if(myCart.ramBankCount()) + { + desc << "Accessible "; + if (myCart.bankSize() >> 1 >= 1024) + desc << ((myCart.bankSize() >> 1) / 1024) << "K"; + else + desc << (myCart.bankSize() >> 1) << " bytes"; + desc << " at a time via:\n"; + indent = " "; + } + + // order RW by addresses + if(myCart.myReadOffset <= myCart.myWriteOffset) + { + desc << indent << "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset) + << " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask)) + << " used for read access\n"; + } + + desc << indent << "$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myWriteOffset) + << " - $" << (ADDR_BASE | (myCart.myWriteOffset + myCart.myRamMask)) + << " used for write access"; + + if(myCart.myReadOffset > myCart.myWriteOffset) + { + desc << indent << "\n$" << Common::Base::HEX4 << (ADDR_BASE | myCart.myReadOffset) + << " - $" << (ADDR_BASE | (myCart.myReadOffset + myCart.myRamMask)) + << " used for read access"; + } + + return desc.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const ByteArray& CartridgeEnhancedWidget::internalRamOld(int start, int count) +{ + myRamOld.clear(); + for(int i = 0; i < count; i++) + myRamOld.push_back(myOldState.internalRam[start + i]); + return myRamOld; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const ByteArray& CartridgeEnhancedWidget::internalRamCurrent(int start, int count) +{ + myRamCurrent.clear(); + for(int i = 0; i < count; i++) + myRamCurrent.push_back(myCart.myRAM[start + i]); + return myRamCurrent; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhancedWidget::internalRamSetValue(int addr, uInt8 value) +{ + myCart.myRAM[addr] = value; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeEnhancedWidget::internalRamGetValue(int addr) +{ + return myCart.myRAM[addr]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeEnhancedWidget::internalRamLabel(int addr) +{ + CartDebug& dbg = instance().debugger().cartDebug(); + return dbg.getLabel(addr + ADDR_BASE + myCart.myReadOffset, false); +} diff --git a/src/debugger/gui/CartCVPlusWidget.hxx b/src/debugger/gui/CartEnhancedWidget.hxx similarity index 50% rename from src/debugger/gui/CartCVPlusWidget.hxx rename to src/debugger/gui/CartEnhancedWidget.hxx index b1401b07c..a367e8def 100644 --- a/src/debugger/gui/CartCVPlusWidget.hxx +++ b/src/debugger/gui/CartEnhancedWidget.hxx @@ -15,42 +15,58 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#ifndef CARTRIDGECVPlus_WIDGET_HXX -#define CARTRIDGECVPlus_WIDGET_HXX +#ifndef CART_ENHANCED_WIDGET_HXX +#define CART_ENHANCED_WIDGET_HXX -class CartridgeCVPlus; +class CartridgeEnhanced; class PopUpWidget; +namespace GUI { + class Font; +} + +#include "Variant.hxx" #include "CartDebugWidget.hxx" -class CartridgeCVPlusWidget : public CartDebugWidget +class CartridgeEnhancedWidget : public CartDebugWidget { public: - CartridgeCVPlusWidget(GuiObject* boss, const GUI::Font& lfont, - const GUI::Font& nfont, - int x, int y, int w, int h, - CartridgeCVPlus& cart); - virtual ~CartridgeCVPlusWidget() = default; + CartridgeEnhancedWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartridgeEnhanced& cart); + virtual ~CartridgeEnhancedWidget() = default; - private: - CartridgeCVPlus& myCart; - PopUpWidget* myBank{nullptr}; - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; + protected: + int initialize(); - enum { kBankChanged = 'bkCH' }; + virtual size_t size(); - private: + virtual string manufacturer() = 0; + + virtual string description(); + + virtual int descriptionLines(); + + virtual string ramDescription(); + + virtual string romDescription(); + + virtual void bankList(uInt16 bankCount, int seg, VariantList& items, int& width); + + virtual void bankSelect(int& ypos); + + virtual string hotspotStr(int bank = 0, int segment = 0, bool prefix = false); + + virtual uInt16 bankSegs(); // { return myCart.myBankSegs; } + + void saveOldState() override; void loadConfig() override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; string bankState() override; - void saveOldState() override; - // start of functions for Cartridge RAM tab uInt32 internalRamSize() override; uInt32 internalRamRPort(int start) override; @@ -62,12 +78,34 @@ class CartridgeCVPlusWidget : public CartDebugWidget string internalRamLabel(int addr) override; // end of functions for Cartridge RAM tab + protected: + enum { kBankChanged = 'bkCH' }; + + struct CartState { + ByteArray internalRam; + ByteArray banks; + }; + CartState myOldState; + + CartridgeEnhanced& myCart; + + // Distance between two hotspots + int myHotspotDelta{1}; + + std::unique_ptr myBankWidgets{nullptr}; + + + // Display all addresses based on this + static constexpr uInt16 ADDR_BASE = 0xF000; + + private: // Following constructors and assignment operators not supported - CartridgeCVPlusWidget() = delete; - CartridgeCVPlusWidget(const CartridgeCVPlusWidget&) = delete; - CartridgeCVPlusWidget(CartridgeCVPlusWidget&&) = delete; - CartridgeCVPlusWidget& operator=(const CartridgeCVPlusWidget&) = delete; - CartridgeCVPlusWidget& operator=(CartridgeCVPlusWidget&&) = delete; + CartridgeEnhancedWidget() = delete; + CartridgeEnhancedWidget(const CartridgeEnhancedWidget&) = delete; + CartridgeEnhancedWidget(CartridgeEnhancedWidget&&) = delete; + CartridgeEnhancedWidget& operator=(const CartridgeEnhancedWidget&) = delete; + CartridgeEnhancedWidget& operator=(CartridgeEnhancedWidget&&) = delete; }; #endif + diff --git a/src/debugger/gui/CartF0Widget.cxx b/src/debugger/gui/CartF0Widget.cxx index c7564cefa..78b13f2d9 100644 --- a/src/debugger/gui/CartF0Widget.cxx +++ b/src/debugger/gui/CartF0Widget.cxx @@ -16,85 +16,28 @@ //============================================================================ #include "CartF0.hxx" -#include "PopUpWidget.hxx" #include "CartF0Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF0Widget::CartridgeF0Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF0& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 16 * 4096; + myHotspotDelta = 0; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF0Widget::description() +{ ostringstream info; - info << "64K Megaboy F0 cartridge, 16 4K banks\n" - << "Startup bank = #" << cart.startBank() << " or undetermined\n" - << "Bankswitch triggered by accessing $1FF0\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC; i < 16; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start - << " - " << "$" << (start + 0xFFF) << "\n"; - } + info << "Megaboy F0 cartridge, 16 4K banks\n" + << "Startup bank = #" << myCart.startBank() << " or undetermined\n" + << "Bankswitch triggered by accessing $" << Common::Base::HEX4 << 0xFFF0 << "\n"; - int xpos = 2, - ypos = addBaseInformation(size, "Dynacom Megaboy", - info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0"); - VarList::push_back(items, " 1"); - VarList::push_back(items, " 2"); - VarList::push_back(items, " 3"); - VarList::push_back(items, " 4"); - VarList::push_back(items, " 5"); - VarList::push_back(items, " 6"); - VarList::push_back(items, " 7"); - VarList::push_back(items, " 8"); - VarList::push_back(items, " 9"); - VarList::push_back(items, " 10"); - VarList::push_back(items, " 11"); - VarList::push_back(items, " 12"); - VarList::push_back(items, " 13"); - VarList::push_back(items, " 14"); - VarList::push_back(items, " 15"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth(" 15"), - myLineHeight, items, "Set bank #", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF0Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF0Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -102,7 +45,8 @@ string CartridgeF0Widget::bankState() { ostringstream& buf = buffer(); - buf << "Bank = #" << std::dec << myCart.getBank() << ", hotspot = $FFF0"; + buf << "Bank #" << std::dec << myCart.getBank() + << " (hotspot $" << Common::Base::HEX4 << 0xFFF0 << ")"; return buf.str(); } diff --git a/src/debugger/gui/CartF0Widget.hxx b/src/debugger/gui/CartF0Widget.hxx index 6225fff71..017d88e78 100644 --- a/src/debugger/gui/CartF0Widget.hxx +++ b/src/debugger/gui/CartF0Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF0_WIDGET_HXX class CartridgeF0; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF0Widget : public CartDebugWidget +class CartridgeF0Widget : public CartridgeEnhancedWidget { public: CartridgeF0Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,13 @@ class CartridgeF0Widget : public CartDebugWidget virtual ~CartridgeF0Widget() = default; private: - CartridgeF0& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Dynacom Megaboy"; } - enum { kBankChanged = 'bkCH' }; - - private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + string description() override; string bankState() override; + private: // Following constructors and assignment operators not supported CartridgeF0Widget() = delete; CartridgeF0Widget(const CartridgeF0Widget&) = delete; diff --git a/src/debugger/gui/CartF4SCWidget.cxx b/src/debugger/gui/CartF4SCWidget.cxx index 512edba55..8f75b6fce 100644 --- a/src/debugger/gui/CartF4SCWidget.cxx +++ b/src/debugger/gui/CartF4SCWidget.cxx @@ -15,157 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartF4SC.hxx" -#include "PopUpWidget.hxx" #include "CartF4SCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF4SCWidget::CartridgeF4SCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF4SC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 8 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF4SCWidget::description() +{ ostringstream info; - info << "Standard F4SC cartridge, eight 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF4; i < 8; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x100) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F4SC cartridge, eight 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str(), 15) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF4)"); - VarList::push_back(items, "1 ($FFF5)"); - VarList::push_back(items, "2 ($FFF6)"); - VarList::push_back(items, "3 ($FFF7)"); - VarList::push_back(items, "4 ($FFF8)"); - VarList::push_back(items, "5 ($FFF9)"); - VarList::push_back(items, "6 ($FFFA)"); - VarList::push_back(items, "7 ($FFFB)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF4SCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFF4", "$FFF5", "$FFF6", "$FFF7", "$FFF8", "$FFF9", "$FFFA", "$FFFB" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF4SCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF4SCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF4SCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF4SCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF4SCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF4SCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF4SCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartF4SCWidget.hxx b/src/debugger/gui/CartF4SCWidget.hxx index e2ec21f06..c6570a9fa 100644 --- a/src/debugger/gui/CartF4SCWidget.hxx +++ b/src/debugger/gui/CartF4SCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF4SC_WIDGET_HXX class CartridgeF4SC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF4SCWidget : public CartDebugWidget +class CartridgeF4SCWidget : public CartridgeEnhancedWidget { public: CartridgeF4SCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,36 +32,11 @@ class CartridgeF4SCWidget : public CartDebugWidget virtual ~CartridgeF4SCWidget() = default; private: - CartridgeF4SC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Atari"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeF4SCWidget() = delete; CartridgeF4SCWidget(const CartridgeF4SCWidget&) = delete; diff --git a/src/debugger/gui/CartF4Widget.cxx b/src/debugger/gui/CartF4Widget.cxx index 3d5848cd0..5069f029d 100644 --- a/src/debugger/gui/CartF4Widget.cxx +++ b/src/debugger/gui/CartF4Widget.cxx @@ -16,87 +16,24 @@ //============================================================================ #include "CartF4.hxx" -#include "PopUpWidget.hxx" #include "CartF4Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF4Widget::CartridgeF4Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF4& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 8 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF4Widget::description() +{ ostringstream info; - info << "Standard F4 cartridge, eight 4K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF4; i < 8; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F4 cartridge, eight 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str(), 15) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF4)"); - VarList::push_back(items, "1 ($FFF5)"); - VarList::push_back(items, "2 ($FFF6)"); - VarList::push_back(items, "3 ($FFF7)"); - VarList::push_back(items, "4 ($FFF8)"); - VarList::push_back(items, "5 ($FFF9)"); - VarList::push_back(items, "6 ($FFFA)"); - VarList::push_back(items, "7 ($FFFB)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF4Widget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFF4", "$FFF5", "$FFF6", "$FFF7", "$FFF8", "$FFF9", "$FFFA", "$FFFB" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartF4Widget.hxx b/src/debugger/gui/CartF4Widget.hxx index 7487a1b4b..d444a5956 100644 --- a/src/debugger/gui/CartF4Widget.hxx +++ b/src/debugger/gui/CartF4Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF4_WIDGET_HXX class CartridgeF4; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF4Widget : public CartDebugWidget +class CartridgeF4Widget : public CartridgeEnhancedWidget { public: CartridgeF4Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeF4Widget : public CartDebugWidget virtual ~CartridgeF4Widget() = default; private: - CartridgeF4& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Atari"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeF4Widget() = delete; CartridgeF4Widget(const CartridgeF4Widget&) = delete; diff --git a/src/debugger/gui/CartF6SCWidget.cxx b/src/debugger/gui/CartF6SCWidget.cxx index 863ff2948..d2556799c 100644 --- a/src/debugger/gui/CartF6SCWidget.cxx +++ b/src/debugger/gui/CartF6SCWidget.cxx @@ -15,151 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartF6SC.hxx" -#include "PopUpWidget.hxx" #include "CartF6SCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF6SCWidget::CartridgeF6SCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF6SC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 4 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF6SCWidget::description() +{ ostringstream info; - info << "Standard F6SC cartridge, four 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF6; i < 4; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x100) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F6SC cartridge, four 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF6)"); - VarList::push_back(items, "1 ($FFF7)"); - VarList::push_back(items, "2 ($FFF8)"); - VarList::push_back(items, "3 ($FFF9)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF6SCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$FFF6", "$FFF7", "$FFF8", "$FFF9" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF6SCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF6SCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF6SCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF6SCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF6SCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF6SCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF6SCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartF6SCWidget.hxx b/src/debugger/gui/CartF6SCWidget.hxx index deee0e836..1ed6378a7 100644 --- a/src/debugger/gui/CartF6SCWidget.hxx +++ b/src/debugger/gui/CartF6SCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF6SC_WIDGET_HXX class CartridgeF6SC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF6SCWidget : public CartDebugWidget +class CartridgeF6SCWidget : public CartridgeEnhancedWidget { public: CartridgeF6SCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,34 +32,11 @@ class CartridgeF6SCWidget : public CartDebugWidget virtual ~CartridgeF6SCWidget() = default; private: - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartridgeF6SC& myCart; - PopUpWidget* myBank{nullptr}; - CartState myOldState; + string manufacturer() override { return "Atari"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeF6SCWidget() = delete; CartridgeF6SCWidget(const CartridgeF6SCWidget&) = delete; diff --git a/src/debugger/gui/CartF6Widget.cxx b/src/debugger/gui/CartF6Widget.cxx index 114d20e18..66bcbc6a7 100644 --- a/src/debugger/gui/CartF6Widget.cxx +++ b/src/debugger/gui/CartF6Widget.cxx @@ -16,81 +16,24 @@ //============================================================================ #include "CartF6.hxx" -#include "PopUpWidget.hxx" #include "CartF6Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF6Widget::CartridgeF6Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF6& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 4 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF6Widget::description() +{ ostringstream info; - info << "Standard F6 cartridge, four 4K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF6; i < 4; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F6 cartridge, four 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF6)"); - VarList::push_back(items, "1 ($FFF7)"); - VarList::push_back(items, "2 ($FFF8)"); - VarList::push_back(items, "3 ($FFF9)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx) "), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF6Widget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$FFF6", "$FFF7", "$FFF8", "$FFF9" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartF6Widget.hxx b/src/debugger/gui/CartF6Widget.hxx index 392eb6a0c..2d0eb3734 100644 --- a/src/debugger/gui/CartF6Widget.hxx +++ b/src/debugger/gui/CartF6Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF6_WIDGET_HXX class CartridgeF6; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF6Widget : public CartDebugWidget +class CartridgeF6Widget : public CartridgeEnhancedWidget { public: CartridgeF6Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeF6Widget : public CartDebugWidget virtual ~CartridgeF6Widget() = default; private: - CartridgeF6& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Atari"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeF6Widget() = delete; CartridgeF6Widget(const CartridgeF6Widget&) = delete; diff --git a/src/debugger/gui/CartF8SCWidget.cxx b/src/debugger/gui/CartF8SCWidget.cxx index 1f432e224..baae2360a 100644 --- a/src/debugger/gui/CartF8SCWidget.cxx +++ b/src/debugger/gui/CartF8SCWidget.cxx @@ -15,149 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartF8SC.hxx" -#include "PopUpWidget.hxx" #include "CartF8SCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF8SCWidget::CartridgeF8SCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF8SC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 8192; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF8SCWidget::description() +{ ostringstream info; - info << "Standard F8SC cartridge, two 4K banks\n" - << "128 bytes RAM @ $F000 - $F0FF\n" - << " $F080 - $F0FF (R), $F000 - $F07F (W)\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF8; i < 2; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x100) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F8SC cartridge, two 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF8)"); - VarList::push_back(items, "1 ($FFF9)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SCWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SCWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF8SCWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$FFF8", "$FFF9" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF8SCWidget::internalRamSize() -{ - return 128; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeF8SCWidget::internalRamRPort(int start) -{ - return 0xF080 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF8SCWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F07F used for Write Access\n" - << "$F080 - $F0FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF8SCWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeF8SCWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SCWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF8SCWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF8SCWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF080, false); + return info.str(); } diff --git a/src/debugger/gui/CartF8SCWidget.hxx b/src/debugger/gui/CartF8SCWidget.hxx index 7bebef602..3f6199783 100644 --- a/src/debugger/gui/CartF8SCWidget.hxx +++ b/src/debugger/gui/CartF8SCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEF8SC_WIDGET_HXX class CartridgeF8SC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF8SCWidget : public CartDebugWidget +class CartridgeF8SCWidget : public CartridgeEnhancedWidget { public: CartridgeF8SCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,35 +32,11 @@ class CartridgeF8SCWidget : public CartDebugWidget virtual ~CartridgeF8SCWidget() = default; private: - CartridgeF8SC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Atari"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeF8SCWidget() = delete; CartridgeF8SCWidget(const CartridgeF8SCWidget&) = delete; diff --git a/src/debugger/gui/CartF8Widget.cxx b/src/debugger/gui/CartF8Widget.cxx index ca648b5f1..d3dd88c23 100644 --- a/src/debugger/gui/CartF8Widget.cxx +++ b/src/debugger/gui/CartF8Widget.cxx @@ -16,79 +16,24 @@ //============================================================================ #include "CartF8.hxx" -#include "PopUpWidget.hxx" #include "CartF8Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF8Widget::CartridgeF8Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeF8& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 2 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeF8Widget::description() +{ ostringstream info; - info << "Standard F8 cartridge, two 4K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF8; i < 2; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "Standard F8 cartridge, two 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "Atari", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF8)"); - VarList::push_back(items, "1 ($FFF9)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeF8Widget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$FFF8", "$FFF9" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartF8Widget.hxx b/src/debugger/gui/CartF8Widget.hxx index 507ad464b..a0577f250 100644 --- a/src/debugger/gui/CartF8Widget.hxx +++ b/src/debugger/gui/CartF8Widget.hxx @@ -21,9 +21,9 @@ class CartridgeF8; class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeF8Widget : public CartDebugWidget +class CartridgeF8Widget : public CartridgeEnhancedWidget { public: CartridgeF8Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +33,11 @@ class CartridgeF8Widget : public CartDebugWidget virtual ~CartridgeF8Widget() = default; private: - CartridgeF8& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Atari"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeF8Widget() = delete; CartridgeF8Widget(const CartridgeF8Widget&) = delete; diff --git a/src/debugger/gui/CartFA2Widget.cxx b/src/debugger/gui/CartFA2Widget.cxx index eb2bf4d07..e7dcba933 100644 --- a/src/debugger/gui/CartFA2Widget.cxx +++ b/src/debugger/gui/CartFA2Widget.cxx @@ -15,65 +15,26 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartFA2.hxx" -#include "PopUpWidget.hxx" #include "CartFA2Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFA2Widget::CartridgeFA2Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeFA2& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), + myCartFA2(cart) { - size_t size = cart.mySize; - - ostringstream info; - info << "Modified FA RAM+, six or seven 4K banks\n" - << "256 bytes RAM @ $F000 - $F1FF\n" - << " $F100 - $F1FF (R), $F000 - $F0FF (W)\n" - << "RAM can be loaded/saved to Harmony flash by accessing $FFF4\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < cart.bankCount(); - ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x200) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } - int xpos = 2, - ypos = addBaseInformation(size, "Chris D. Walton (Star Castle 2600)", - info.str(), 15) + myLineHeight; + ypos = initialize(); - VariantList items; - VarList::push_back(items, "0 ($FFF5)"); - VarList::push_back(items, "1 ($FFF6)"); - VarList::push_back(items, "2 ($FFF7)"); - VarList::push_back(items, "3 ($FFF8)"); - VarList::push_back(items, "4 ($FFF9)"); - VarList::push_back(items, "5 ($FFFA)"); - if(cart.bankCount() == 7) - VarList::push_back(items, "6 ($FFFB)"); - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); - ypos += myLineHeight + 20; + ypos += 12; const int bwidth = _font.getStringWidth("Erase") + 20; StaticTextWidget* t = new StaticTextWidget(boss, _font, xpos, ypos, - _font.getStringWidth("Harmony Flash "), - myFontHeight, "Harmony Flash ", TextAlign::Left); + _font.getStringWidth("Harmony flash memory "), + myFontHeight, "Harmony flash memory ", TextAlign::Left); xpos += t->getWidth() + 4; myFlashErase = @@ -98,22 +59,16 @@ CartridgeFA2Widget::CartridgeFA2Widget( } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA2Widget::saveOldState() +string CartridgeFA2Widget::description() { - myOldState.internalram.clear(); + ostringstream info; - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); + info << "Modified FA RAM+, six or seven 4K banks\n"; + info << "RAM+ can be loaded/saved to Harmony flash memory by accessing $" + << Common::Base::HEX4 << 0xFFF4 << "\n"; + info << CartridgeEnhancedWidget::description(); - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA2Widget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -122,99 +77,19 @@ void CartridgeFA2Widget::handleCommand(CommandSender* sender, { switch(cmd) { - case kBankChanged: - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - break; - case kFlashErase: - myCart.flash(0); + myCartFA2.flash(0); break; case kFlashLoad: - myCart.flash(1); + myCartFA2.flash(1); break; case kFlashSave: - myCart.flash(2); + myCartFA2.flash(2); break; default: - break; + CartridgeEnhancedWidget::handleCommand(sender, cmd, data, id); } } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFA2Widget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { - "$FFF5", "$FFF6", "$FFF7", "$FFF8", "$FFF9", "$FFFA", "$FFFB" - }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeFA2Widget::internalRamSize() -{ - return 256; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeFA2Widget::internalRamRPort(int start) -{ - return 0xF100 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFA2Widget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F0FF used for Write Access\n" - << "$F100 - $F1FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeFA2Widget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeFA2Widget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA2Widget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeFA2Widget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFA2Widget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF100, false); -} diff --git a/src/debugger/gui/CartFA2Widget.hxx b/src/debugger/gui/CartFA2Widget.hxx index 0b5fe3fb4..06865c495 100644 --- a/src/debugger/gui/CartFA2Widget.hxx +++ b/src/debugger/gui/CartFA2Widget.hxx @@ -20,11 +20,10 @@ class CartridgeFA2; class ButtonWidget; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeFA2Widget : public CartDebugWidget +class CartridgeFA2Widget : public CartridgeEnhancedWidget { public: CartridgeFA2Widget(GuiObject* boss, const GUI::Font& lfont, @@ -34,41 +33,25 @@ class CartridgeFA2Widget : public CartDebugWidget virtual ~CartridgeFA2Widget() = default; private: - CartridgeFA2& myCart; - PopUpWidget* myBank{nullptr}; + CartridgeFA2& myCartFA2; + ButtonWidget *myFlashErase{nullptr}, *myFlashLoad{nullptr}, *myFlashSave{nullptr}; - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - enum { - kBankChanged = 'bkCH', kFlashErase = 'flER', kFlashLoad = 'flLD', kFlashSave = 'flSV' }; private: - void saveOldState() override; - void loadConfig() override; + string manufacturer() override { return "Chris D. Walton (Star Castle 2600 Arcade)"; } + + string description() override; + + private: void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - + private: // Following constructors and assignment operators not supported CartridgeFA2Widget() = delete; CartridgeFA2Widget(const CartridgeFA2Widget&) = delete; diff --git a/src/debugger/gui/CartFAWidget.cxx b/src/debugger/gui/CartFAWidget.cxx index e32a3eec0..aea8a2061 100644 --- a/src/debugger/gui/CartFAWidget.cxx +++ b/src/debugger/gui/CartFAWidget.cxx @@ -15,150 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartFA.hxx" -#include "PopUpWidget.hxx" #include "CartFAWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFAWidget::CartridgeFAWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeFA& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = 3 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeFAWidget::description() +{ ostringstream info; - info << "CBS RAM+ FA cartridge, three 4K banks\n" - << "256 bytes RAM @ $F000 - $F1FF\n" - << " $F100 - $F1FF (R), $F000 - $F0FF (W)\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF8; i < 3; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << (start + 0x200) << " - " - << "$" << (start + 0xFFF) << " (hotspot = $F" << (spot+i) << ")\n"; - } + info << "CBS RAM+ FA cartridge, three 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "CBS", info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($FFF8)"); - VarList::push_back(items, "1 ($FFF9)"); - VarList::push_back(items, "2 ($FFFA)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFAWidget::saveOldState() -{ - myOldState.internalram.clear(); - - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); - - myOldState.bank = myCart.getBank(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFAWidget::loadConfig() -{ - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFAWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFAWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$FFF8", "$FFF9", "$FFFA" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << spot[myCart.getBank()]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeFAWidget::internalRamSize() -{ - return 256; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeFAWidget::internalRamRPort(int start) -{ - return 0xF100 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFAWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F0FF used for Write Access\n" - << "$F100 - $F1FF used for Read Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeFAWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; i++) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeFAWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; i++) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFAWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeFAWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFAWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF100, false); + return info.str(); } diff --git a/src/debugger/gui/CartFAWidget.hxx b/src/debugger/gui/CartFAWidget.hxx index e4e1da416..2d7311a71 100644 --- a/src/debugger/gui/CartFAWidget.hxx +++ b/src/debugger/gui/CartFAWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEFA_WIDGET_HXX class CartridgeFA; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeFAWidget : public CartDebugWidget +class CartridgeFAWidget : public CartridgeEnhancedWidget { public: CartridgeFAWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,35 +32,11 @@ class CartridgeFAWidget : public CartDebugWidget virtual ~CartridgeFAWidget() = default; private: - CartridgeFA& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "CBS"; } - struct CartState { - ByteArray internalram; - uInt16 bank{0}; - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab - // Following constructors and assignment operators not supported CartridgeFAWidget() = delete; CartridgeFAWidget(const CartridgeFAWidget&) = delete; diff --git a/src/debugger/gui/CartFCWidget.cxx b/src/debugger/gui/CartFCWidget.cxx index ce1bf9403..d206ec694 100644 --- a/src/debugger/gui/CartFCWidget.cxx +++ b/src/debugger/gui/CartFCWidget.cxx @@ -16,80 +16,44 @@ //============================================================================ #include "CartFC.hxx" -#include "PopUpWidget.hxx" #include "CartFCWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFCWidget::CartridgeFCWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeFC& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt16 size = cart.bankCount() * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeFCWidget::description() +{ ostringstream info; - info << "FC cartridge, up to eight 4K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; + uInt16 hotspot = myCart.hotspot() | ADDR_BASE; - // Eventually, we should query this from the debugger/disassembler + info << "FC cartridge, up to eight 4K banks\n"; info << "Bank selected by hotspots\n" - << " $FFF8 (defines low 2 bits)\n" - << " $FFF9 (defines high bits)\n" - << " $FFFC (triggers bank switch)"; + << " $" << Common::Base::HEX4 << hotspot << " (defines low 2 bits)\n" + << " $" << Common::Base::HEX4 << (hotspot + 1) << " (defines high bits)\n" + << " $" << Common::Base::HEX4 << (hotspot + 4) << " (triggers bank switch)\n"; - int xpos = 2, - ypos = addBaseInformation(size, "Amiga Corp.", info.str()) + myLineHeight; + info << CartridgeEnhancedWidget::description(); - VariantList items; - for (uInt16 i = 0; i < cart.bankCount(); ++i) - VarList::push_back(items, Variant(i).toString() + - " ($FFF8 = " + Variant(i & 0b11).toString() + - "/$FFF9 = " + Variant(i >> 2).toString() +")"); - - myBank = new PopUpWidget(boss, _font, xpos, ypos - 2, - _font.getStringWidth("7 ($FFF8 = 3/$FFF9 = 1)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFCWidget::loadConfig() +string CartridgeFCWidget::hotspotStr(int bank, int, bool prefix) { - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); + ostringstream info; + uInt16 hotspot = myCart.hotspot() | ADDR_BASE; - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); + info << "(" << (prefix ? "hotspots " : ""); + info << "$" << Common::Base::HEX4 << hotspot << " = " << (bank & 0b11); + info << ", $" << Common::Base::HEX4 << (hotspot + 1) << " = " << (bank >> 2); + info << ")"; - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFCWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if (cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFCWidget::bankState() -{ - ostringstream& buf = buffer(); - uInt16 bank = myCart.getBank(); - - buf << "Bank = #" << std::dec << bank - << ", hotspots $FFF8 = " << (bank & 0b11) - << "/$FF99 = " << (bank >> 2); - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartFCWidget.hxx b/src/debugger/gui/CartFCWidget.hxx index 0e74246ed..f6d56af71 100644 --- a/src/debugger/gui/CartFCWidget.hxx +++ b/src/debugger/gui/CartFCWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEFC_WIDGET_HXX class CartridgeFC; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeFCWidget : public CartDebugWidget +class CartridgeFCWidget : public CartridgeEnhancedWidget { public: CartridgeFCWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,13 @@ class CartridgeFCWidget : public CartDebugWidget virtual ~CartridgeFCWidget() = default; private: - CartridgeFC& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Amiga Corp."; } - enum { kBankChanged = 'bkCH' }; + string description() override; + + string hotspotStr(int bank, int seg = 0, bool prefix = false) override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeFCWidget() = delete; CartridgeFCWidget(const CartridgeFCWidget&) = delete; diff --git a/src/debugger/gui/CartFEWidget.cxx b/src/debugger/gui/CartFEWidget.cxx index afccb359f..ce7267e6e 100644 --- a/src/debugger/gui/CartFEWidget.cxx +++ b/src/debugger/gui/CartFEWidget.cxx @@ -16,72 +16,36 @@ //============================================================================ #include "CartFE.hxx" -#include "PopUpWidget.hxx" #include "CartFEWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFEWidget::CartridgeFEWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeFE& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - string info = - "FE cartridge, two 4K banks\n" - "Monitors access to hotspot $01FE, and uses " - "upper 3 bits of databus for bank number:\n" - "Bank 0 @ $F000 - $FFFF (DATA = 111, D5 = 1)\n" - "Bank 1 @ $D000 - $DFFF (DATA = 110, D5 = 0)\n"; - - int xpos = 2, - ypos = addBaseInformation(2 * 4096, "Activision", info) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($01FE, D5=1)"); - VarList::push_back(items, "1 ($01FE, D5=0)"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, - _font.getStringWidth("0 ($01FE, D5=1)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); + initialize(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFEWidget::loadConfig() +string CartridgeFEWidget::description() { - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); + ostringstream info; - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); + info << "FE cartridge, two 4K banks\n" + << "Monitors access to hotspot $01FE, and uses " + << "upper 3 bits of databus for bank number:\n"; + info << CartridgeEnhancedWidget::description(); - CartDebugWidget::loadConfig(); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFEWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) +string CartridgeFEWidget::hotspotStr(int bank, int, bool) { - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeFEWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array range = { "$F000", "$D000" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", address range = " << range[myCart.getBank()]; - - return buf.str(); + ostringstream info; + + info << "(DATA = 11" << !bank << ", D5 = " << !bank << ")"; + + return info.str(); } diff --git a/src/debugger/gui/CartFEWidget.hxx b/src/debugger/gui/CartFEWidget.hxx index a9f37190c..468fcc144 100644 --- a/src/debugger/gui/CartFEWidget.hxx +++ b/src/debugger/gui/CartFEWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEFE_WIDGET_HXX class CartridgeFE; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeFEWidget : public CartDebugWidget +class CartridgeFEWidget : public CartridgeEnhancedWidget { public: CartridgeFEWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,18 +32,13 @@ class CartridgeFEWidget : public CartDebugWidget virtual ~CartridgeFEWidget() = default; private: - CartridgeFE& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Activision"; } - enum { kBankChanged = 'bkCH' }; + string description() override; + + string hotspotStr(int bank, int, bool) override; private: - // No implementation for non-bankswitched ROMs - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeFEWidget() = delete; CartridgeFEWidget(const CartridgeFEWidget&) = delete; diff --git a/src/debugger/gui/CartMDMWidget.cxx b/src/debugger/gui/CartMDMWidget.cxx index 7b0f799e4..a3509cb34 100644 --- a/src/debugger/gui/CartMDMWidget.cxx +++ b/src/debugger/gui/CartMDMWidget.cxx @@ -17,44 +17,39 @@ #include "CartMDM.hxx" #include "PopUpWidget.hxx" -#include "Widget.hxx" #include "CartMDMWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeMDMWidget::CartridgeMDMWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeMDM& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), + myCartMDM(cart) { - size_t size = myCart.mySize; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeMDMWidget::description() +{ ostringstream info; - info << "Menu Driven Megacart, containing up to 128 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n" - << "\nBanks are selected by reading from $800 - $BFF, where the lower " - "byte determines the 4K bank to use."; - int xpos = 2, - ypos = addBaseInformation(size, "Edwin Blink", info.str(), 15) + myLineHeight; + info << "Menu Driven Megacart, " << myCart.romBankCount() << " 4K banks\n" + << "Banks are selected by reading from $800 - $" << Common::Base::HEX1 << 0xBFF + << ", where the lower byte determines the 4K bank to use.\n"; + info << CartridgeEnhancedWidget::description(); - VariantList items; - for(uInt32 i = 0x800; i < (0x800U + myCart.bankCount()); ++i) - { - info.str(""); - info << std::dec << (i & 0xFF) << " ($" << Common::Base::HEX4 << i << ")"; - VarList::push_back(items, info.str()); - } + return info.str(); +} - myBank = - new PopUpWidget(boss, _font, xpos, ypos, _font.getStringWidth("xxx ($0FFF)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeMDMWidget::bankSelect(int& ypos) +{ + CartridgeEnhancedWidget::bankSelect(ypos); + int xpos = myBankWidgets[0]->getRight() + 20; + ypos = myBankWidgets[0]->getTop(); - xpos += myBank->getWidth() + 30; - myBankDisabled = new CheckboxWidget(boss, _font, xpos, ypos + 1, + myBankDisabled = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Bankswitching is locked/disabled", kBankDisabled); myBankDisabled->setTarget(this); @@ -64,39 +59,21 @@ CartridgeMDMWidget::CartridgeMDMWidget( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMDMWidget::loadConfig() { - myBank->setSelectedIndex(myCart.getBank()); - myBank->setEnabled(!myCart.myBankingDisabled); - myBankDisabled->setState(myCart.myBankingDisabled); + myBankWidgets[0]->setEnabled(!myCartMDM.myBankingDisabled); + myBankDisabled->setState(myCartMDM.myBankingDisabled); - CartDebugWidget::loadConfig(); + CartridgeEnhancedWidget::loadConfig(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMDMWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) { - if(cmd == kBankChanged) + if(cmd == kBankDisabled) { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } - else if(cmd == kBankDisabled) - { - myCart.myBankingDisabled = myBankDisabled->getState(); - myBank->setEnabled(!myCart.myBankingDisabled); + myCartMDM.myBankingDisabled = myBankDisabled->getState(); + myBankWidgets[0]->setEnabled(!myCartMDM.myBankingDisabled); } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeMDMWidget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = " << "$" << Common::Base::HEX4 - << (myCart.getBank()+0x800); - - return buf.str(); + else + CartridgeEnhancedWidget::handleCommand(sender, cmd, data, id); } diff --git a/src/debugger/gui/CartMDMWidget.hxx b/src/debugger/gui/CartMDMWidget.hxx index adf242b68..c7add24d7 100644 --- a/src/debugger/gui/CartMDMWidget.hxx +++ b/src/debugger/gui/CartMDMWidget.hxx @@ -20,11 +20,10 @@ class CartridgeMDM; class CheckboxWidget; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeMDMWidget : public CartDebugWidget +class CartridgeMDMWidget : public CartridgeEnhancedWidget { public: CartridgeMDMWidget(GuiObject* boss, const GUI::Font& lfont, @@ -34,18 +33,24 @@ class CartridgeMDMWidget : public CartDebugWidget virtual ~CartridgeMDMWidget() = default; private: - CartridgeMDM& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Edwin Blink"; } + + string description() override; + + void bankSelect(int& ypos) override; + + CartridgeMDM& myCartMDM; CheckboxWidget* myBankDisabled{nullptr}; - enum { kBankChanged = 'bkCH', kBankDisabled = 'bkDI' }; + enum { + kBankDisabled = 'bkDI' + }; private: void loadConfig() override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - string bankState() override; - + private: // Following constructors and assignment operators not supported CartridgeMDMWidget() = delete; CartridgeMDMWidget(const CartridgeMDMWidget&) = delete; diff --git a/src/debugger/gui/CartMNetworkWidget.cxx b/src/debugger/gui/CartMNetworkWidget.cxx index cdc1f9bce..e9cc68869 100644 --- a/src/debugger/gui/CartMNetworkWidget.cxx +++ b/src/debugger/gui/CartMNetworkWidget.cxx @@ -35,30 +35,30 @@ CartridgeMNetworkWidget::CartridgeMNetworkWidget( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMNetworkWidget::initialize(GuiObject* boss, CartridgeMNetwork& cart, ostringstream& info) { - uInt32 size = cart.bankCount() * cart.BANK_SIZE; + uInt32 size = cart.romBankCount() * cart.BANK_SIZE; int xpos = 2, ypos = addBaseInformation(size, "M-Network", info.str(), 15) + myLineHeight; VariantList items0, items1; - for(int i = 0; i < cart.bankCount(); ++i) + for(int i = 0; i < cart.romBankCount(); ++i) VarList::push_back(items0, getSpotLower(i)); for(int i = 0; i < 4; ++i) VarList::push_back(items1, getSpotUpper(i)); - const int lwidth = _font.getStringWidth("Set slice for upper 256B "), - fwidth = _font.getStringWidth("3 - RAM ($FFEB)"); + const int lwidth = _font.getStringWidth("Set bank for upper 256B segment "), + fwidth = _font.getStringWidth("#3 - RAM ($FFEB)"); myLower2K = new PopUpWidget(boss, _font, xpos, ypos - 2, fwidth, myLineHeight, items0, - "Set slice for lower 2K ", lwidth, kLowerChanged); + "Set bank for lower 2K segment", lwidth, kLowerChanged); myLower2K->setTarget(this); addFocusWidget(myLower2K); ypos += myLower2K->getHeight() + 4; myUpper256B = new PopUpWidget(boss, _font, xpos, ypos - 2, fwidth, myLineHeight, items1, - "Set slice for upper 256B ", lwidth, kUpperChanged); + "Set bank for upper 256B segment ", lwidth, kUpperChanged); myUpper256B->setTarget(this); addFocusWidget(myUpper256B); } @@ -71,14 +71,14 @@ void CartridgeMNetworkWidget::saveOldState() for(uInt32 i = 0; i < internalRamSize(); ++i) myOldState.internalram.push_back(myCart.myRAM[i]); - myOldState.lowerBank = myCart.myCurrentSlice[0]; + myOldState.lowerBank = myCart.myCurrentBank[0]; myOldState.upperBank = myCart.myCurrentRAM; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMNetworkWidget::loadConfig() { - myLower2K->setSelectedIndex(myCart.myCurrentSlice[0], myCart.myCurrentSlice[0] != myOldState.lowerBank); + myLower2K->setSelectedIndex(myCart.myCurrentBank[0], myCart.myCurrentBank[0] != myOldState.lowerBank); myUpper256B->setSelectedIndex(myCart.myCurrentRAM, myCart.myCurrentRAM != myOldState.upperBank); CartDebugWidget::loadConfig(); @@ -111,8 +111,8 @@ string CartridgeMNetworkWidget::bankState() { ostringstream& buf = buffer(); - buf << "Slices: " << std::dec - << getSpotLower(myCart.myCurrentSlice[0]) << " / " + buf << "Segments: " << std::dec + << getSpotLower(myCart.myCurrentBank[0]) << " / " << getSpotUpper(myCart.myCurrentRAM); return buf.str(); @@ -135,11 +135,11 @@ string CartridgeMNetworkWidget::internalRamDescription() { ostringstream desc; desc << "First 1K accessible via:\n" - << " $F000 - $F3FF used for Write Access\n" - << " $F400 - $F7FF used for Read Access\n" - << "256K of second 1K accessible via:\n" - << " $F800 - $F8FF used for Write Access\n" - << " $F900 - $F9FF used for Read Access"; + << " $F000 - $F3FF used for write access\n" + << " $F400 - $F7FF used for read access\n" + << "256 bytes of second 1K accessible via:\n" + << " $F800 - $F8FF used for write access\n" + << " $F900 - $F9FF used for read access"; return desc.str(); } diff --git a/src/debugger/gui/CartRamWidget.cxx b/src/debugger/gui/CartRamWidget.cxx index 1dfcfdaac..76c8e972a 100644 --- a/src/debugger/gui/CartRamWidget.cxx +++ b/src/debugger/gui/CartRamWidget.cxx @@ -47,7 +47,7 @@ CartRamWidget::CartRamWidget( int xpos = 2, ypos = 8; // Add RAM size - new StaticTextWidget(_boss, _font, xpos, ypos + 1, "RAM Size "); + new StaticTextWidget(_boss, _font, xpos, ypos + 1, "RAM size "); uInt32 ramsize = cartDebug.internalRamSize(); buf << ramsize << " bytes"; @@ -62,18 +62,18 @@ CartRamWidget::CartRamWidget( // Add Description const string& desc = cartDebug.internalRamDescription(); const uInt16 maxlines = 6; - StringParser bs(desc, (fwidth - kScrollBarWidth) / myFontWidth); + StringParser bs(desc, (fwidth - ScrollBarWidget::scrollBarWidth(_font)) / myFontWidth); const StringList& sl = bs.stringList(); uInt32 lines = uInt32(sl.size()); - if(lines < 3) lines = 3; + if(lines < 2) lines = 2; if(lines > maxlines) lines = maxlines; new StaticTextWidget(_boss, _font, xpos, ypos + 1, "Description "); myDesc = new StringListWidget(boss, nfont, xpos+lwidth, ypos - 1, fwidth, lines * myLineHeight, false); myDesc->setEditable(false); + myDesc->setEnabled(false); myDesc->setList(sl); - addFocusWidget(myDesc); ypos += myDesc->getHeight() + myFontHeight / 2; diff --git a/src/debugger/gui/CartSBWidget.cxx b/src/debugger/gui/CartSBWidget.cxx index a7bf7e5b2..b564781bc 100644 --- a/src/debugger/gui/CartSBWidget.cxx +++ b/src/debugger/gui/CartSBWidget.cxx @@ -16,85 +16,27 @@ //============================================================================ #include "CartSB.hxx" -#include "PopUpWidget.hxx" #include "CartSBWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeSBWidget::CartridgeSBWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeSB& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - size_t size = myCart.mySize; - - VariantList items; - ostringstream info, bank; - info << "SB SUPERbanking, 32 or 64 4K banks\n" - << "Hotspots are from $800 to $" - << Common::Base::HEX2 << (0x800 + myCart.bankCount() - 1) << ", including\n" - << "mirrors ($900, $A00, $B00, ...)\n" - << "Startup bank = " << std::dec << cart.startBank() << "\n"; - - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = 0x800; i < myCart.bankCount(); - ++i, offset += 0x1000, ++spot) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspot = $" << spot << ")\n"; - - bank << std::dec << std::setw(2) << std::setfill(' ') << i << " ($" - << Common::Base::HEX2 << spot << ")"; - VarList::push_back(items, bank.str()); - bank.str(""); - } - - int xpos = 2, - ypos = addBaseInformation(size, "Fred X. Quimby", info.str()) + myLineHeight; - - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("XX ($800)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); + initialize(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeSBWidget::loadConfig() +string CartridgeSBWidget::description() { - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); + ostringstream info; - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); + info << "SB SUPERbanking, " << myCart.romBankCount() << " 4K banks\n" + << "Hotspots are from $800 to $" + << Common::Base::HEX2 << (0x800 + myCart.romBankCount() - 1) << ", including\n" + << "mirrors ($900, $" << 0xA00 << ", $" << 0xB00 << ", ...)\n"; + info << CartridgeEnhancedWidget::description(); - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeSBWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeSBWidget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspot = $" << Common::Base::HEX2 << (myCart.getBank() + 0x800); - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartSBWidget.hxx b/src/debugger/gui/CartSBWidget.hxx index 5819dec02..91cc90ec1 100644 --- a/src/debugger/gui/CartSBWidget.hxx +++ b/src/debugger/gui/CartSBWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGESB_WIDGET_HXX class CartridgeSB; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeSBWidget : public CartDebugWidget +class CartridgeSBWidget : public CartridgeEnhancedWidget { public: CartridgeSBWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeSBWidget : public CartDebugWidget virtual ~CartridgeSBWidget() = default; private: - CartridgeSB& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "Fred X. Quimby"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeSBWidget() = delete; CartridgeSBWidget(const CartridgeSBWidget&) = delete; diff --git a/src/debugger/gui/CartTVBoyWidget.cxx b/src/debugger/gui/CartTVBoyWidget.cxx new file mode 100644 index 000000000..5012642ba --- /dev/null +++ b/src/debugger/gui/CartTVBoyWidget.cxx @@ -0,0 +1,79 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "CartTVBoy.hxx" +#include "PopUpWidget.hxx" +#include "CartTVBoyWidget.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeTVBoyWidget::CartridgeTVBoyWidget( + GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, + int x, int y, int w, int h, CartridgeTVBoy& cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), + myCartTVBoy(cart) +{ + initialize(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeTVBoyWidget::description() +{ + ostringstream info; + + info << "TV Boy, " << myCart.romBankCount() << " 4K banks\n" + << "Hotspots are from $" << Common::Base::HEX2 << 0xf800 << " to $" + << Common::Base::HEX2 << (0xf800 + myCart.romBankCount() - 1) << "\n"; + info << CartridgeEnhancedWidget::description(); + + return info.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeTVBoyWidget::bankSelect(int& ypos) +{ + CartridgeEnhancedWidget::bankSelect(ypos); + int xpos = myBankWidgets[0]->getRight() + _font.getMaxCharWidth() * 4; + ypos = myBankWidgets[0]->getTop(); + + myBankLocked = new CheckboxWidget(_boss, _font, xpos, ypos + 1, + "Bankswitching is locked", + kBankLocked); + myBankLocked->setTarget(this); + addFocusWidget(myBankLocked); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeTVBoyWidget::loadConfig() +{ + myBankWidgets[0]->setEnabled(!myCartTVBoy.myBankingDisabled); + myBankLocked->setState(myCartTVBoy.myBankingDisabled); + + CartridgeEnhancedWidget::loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeTVBoyWidget::handleCommand(CommandSender* sender, + int cmd, int data, int id) +{ + if(cmd == kBankLocked) + { + myCartTVBoy.myBankingDisabled = myBankLocked->getState(); + myBankWidgets[0]->setEnabled(!myCartTVBoy.myBankingDisabled); + } + else + CartridgeEnhancedWidget::handleCommand(sender, cmd, data, id); +} diff --git a/src/debugger/gui/CartTVBoyWidget.hxx b/src/debugger/gui/CartTVBoyWidget.hxx new file mode 100644 index 000000000..e1c2780e6 --- /dev/null +++ b/src/debugger/gui/CartTVBoyWidget.hxx @@ -0,0 +1,62 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGETVBOY_WIDGET_HXX +#define CARTRIDGETVBOY_WIDGET_HXX + +class CartridgeTVBoy; +class CheckboxWidget; + +#include "CartEnhancedWidget.hxx" + +class CartridgeTVBoyWidget : public CartridgeEnhancedWidget +{ + public: + CartridgeTVBoyWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, + int x, int y, int w, int h, + CartridgeTVBoy& cart); + virtual ~CartridgeTVBoyWidget() = default; + + private: + string manufacturer() override { return "Akor"; } + + string description() override; + + void bankSelect(int& ypos) override; + + CartridgeTVBoy& myCartTVBoy; + CheckboxWidget* myBankLocked{nullptr}; + + enum { + kBankLocked = 'bkLO' + }; + + private: + void loadConfig() override; + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + + private: + // Following constructors and assignment operators not supported + CartridgeTVBoyWidget() = delete; + CartridgeTVBoyWidget(const CartridgeTVBoyWidget&) = delete; + CartridgeTVBoyWidget(CartridgeTVBoyWidget&&) = delete; + CartridgeTVBoyWidget& operator=(const CartridgeTVBoyWidget&) = delete; + CartridgeTVBoyWidget& operator=(CartridgeTVBoyWidget&&) = delete; +}; + +#endif diff --git a/src/debugger/gui/CartUAWidget.cxx b/src/debugger/gui/CartUAWidget.cxx index 7417d8b44..f6ae16bc7 100644 --- a/src/debugger/gui/CartUAWidget.cxx +++ b/src/debugger/gui/CartUAWidget.cxx @@ -16,89 +16,39 @@ //============================================================================ #include "CartUA.hxx" -#include "PopUpWidget.hxx" #include "CartUAWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeUAWidget::CartridgeUAWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeUA& cart, bool swapHotspots) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart), + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), mySwappedHotspots(swapHotspots) { - uInt16 size = 2 * 4096; + myHotspotDelta = 0x20; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeUAWidget::description() +{ ostringstream info; - info << "8K UA cartridge" << (mySwappedHotspots ? " (swapped banks)" : "") << ", two 4K banks\n" - << "Startup bank = " << cart.startBank() << " or undetermined\n"; - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC, spot = mySwappedHotspots ? 0x240 : 0x220; i < 2; - ++i, offset += 0x1000, spot += mySwappedHotspots ? -0x20 : 0x20) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << i << " @ $" << Common::Base::HEX4 << start << " - " - << "$" << (start + 0xFFF) << " (hotspots = $" << spot << ", $" << (spot | 0x80) << ")\n"; - } + info << "8K UA cartridge" << (mySwappedHotspots ? " (swapped banks)" : "") << ", two 4K banks\n"; + info << CartridgeEnhancedWidget::description(); - int xpos = 2, - ypos = addBaseInformation(size, "UA Limited", info.str()) + myLineHeight; - - VariantList items; - if (swapHotspots) - { - VarList::push_back(items, "0 ($240, $2C0)"); - VarList::push_back(items, "1 ($220, $2A0)"); - } - else - { - VarList::push_back(items, "0 ($220, $2A0)"); - VarList::push_back(items, "1 ($240, $2C0)"); - } - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth("0 ($FFx, $FFx)"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeUAWidget::loadConfig() +string CartridgeUAWidget::hotspotStr(int bank, int, bool prefix) { - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); + ostringstream info; + uInt16 hotspot = myCart.hotspot() + (bank ^ (mySwappedHotspots ? 1 : 0)) * myHotspotDelta; - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); + info << "(" << (prefix ? "hotspot " : ""); + info << "$" << Common::Base::HEX1 << hotspot << ", $" << (hotspot | 0x80); + info << ")"; - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeUAWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeUAWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array spot = { "$220, $2A0", "$240, $2C0" }; - buf << "Bank = " << std::dec << myCart.getBank() - << ", hotspots = " << spot[myCart.getBank() ^ (mySwappedHotspots ? 1U : 0U)]; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartUAWidget.hxx b/src/debugger/gui/CartUAWidget.hxx index 346b1c1d2..a610a1316 100644 --- a/src/debugger/gui/CartUAWidget.hxx +++ b/src/debugger/gui/CartUAWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEUA_WIDGET_HXX class CartridgeUA; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeUAWidget : public CartDebugWidget +class CartridgeUAWidget : public CartridgeEnhancedWidget { public: CartridgeUAWidget(GuiObject* boss, const GUI::Font& lfont, @@ -33,19 +32,16 @@ class CartridgeUAWidget : public CartDebugWidget virtual ~CartridgeUAWidget() = default; private: - CartridgeUA& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "UA Limited"; } - bool mySwappedHotspots; + string description() override; - enum { kBankChanged = 'bkCH' }; + string hotspotStr(int bank, int seg, bool prefix = false) override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; + const bool mySwappedHotspots; + private: // Following constructors and assignment operators not supported CartridgeUAWidget() = delete; CartridgeUAWidget(const CartridgeUAWidget&) = delete; diff --git a/src/debugger/gui/CartWDWidget.cxx b/src/debugger/gui/CartWDWidget.cxx index c89c3c8c8..268e81bf1 100644 --- a/src/debugger/gui/CartWDWidget.cxx +++ b/src/debugger/gui/CartWDWidget.cxx @@ -15,157 +15,45 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Debugger.hxx" -#include "CartDebug.hxx" #include "CartWD.hxx" -#include "PopUpWidget.hxx" #include "CartWDWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeWDWidget::CartridgeWDWidget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeWD& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart), + myCartWD(cart) { - string info = - "This scheme has eight 1K slices, which can be mapped into four 1K " - "segments in various combinations. Each 'bank' selects a predefined " - "segment arrangement (indicated in square brackets)\n" - "In the third (uppermost) segment the byte at $3FC is overwritten with 0.\n\n" - "64 bytes RAM @ $F000 - $F080\n" - " $F000 - $F03F (R), $F040 - $F07F (W)\n"; - - int xpos = 2, - ypos = addBaseInformation(myCart.mySize, "Wickstead Design", info, 12) + myLineHeight; - - VariantList items; - VarList::push_back(items, "0 ($30) [0,0,1,3]", 0); - VarList::push_back(items, "1 ($31) [0,1,2,3]", 1); - VarList::push_back(items, "2 ($32) [4,5,6,7]", 2); - VarList::push_back(items, "3 ($33) [7,4,2,3]", 3); - VarList::push_back(items, "4 ($34) [0,0,6,7]", 4); - VarList::push_back(items, "5 ($35) [0,1,7,6]", 5); - VarList::push_back(items, "6 ($36) [2,3,4,5]", 6); - VarList::push_back(items, "7 ($37) [6,0,5,1]", 7); - VarList::push_back(items, "8 ($38) [0,0,1,3]", 8); - VarList::push_back(items, "9 ($39) [0,1,2,3]", 9); - VarList::push_back(items, "10 ($3A) [4,5,6,7]", 10); - VarList::push_back(items, "11 ($3B) [7,4,2,3]", 11); - VarList::push_back(items, "12 ($3C) [0,0,6,7]", 12); - VarList::push_back(items, "13 ($3D) [0,1,7,6]", 13); - VarList::push_back(items, "14 ($3E) [2,3,4,5]", 14); - VarList::push_back(items, "15 ($3F) [6,0,5,1]", 15); - myBank = new PopUpWidget(boss, _font, xpos, ypos-2, - _font.getStringWidth("15 ($3F) [6,0,5,1]"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); + initialize(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWDWidget::saveOldState() +string CartridgeWDWidget::description() { - myOldState.internalram.clear(); + ostringstream info; - for(uInt32 i = 0; i < internalRamSize(); ++i) - myOldState.internalram.push_back(myCart.myRAM[i]); + info << "8K + RAM Wickstead Design cartridge, \n" + << " eight 1K banks, mapped into four segments\n" + << "Hotspots $" << Common::Base::HEX1 << myCart.hotspot() << " - $" << (myCart.hotspot() + 7) << ", " + << "each hotspot selects a [predefined bank mapping]\n"; + info << ramDescription(); - myOldState.bank = myCart.getBank(); + return info.str(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWDWidget::loadConfig() +string CartridgeWDWidget::hotspotStr(int bank, int segment, bool prefix) { - myBank->setSelectedIndex(myCart.getBank(), myCart.getBank() != myOldState.bank); + ostringstream info; + CartridgeWD::BankOrg banks = myCartWD.ourBankOrg[bank]; - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWDWidget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeWDWidget::bankState() -{ - ostringstream& buf = buffer(); - - static constexpr std::array segments = { - "[0,0,1,3]", "[0,1,2,3]", "[4,5,6,7]", "[7,4,2,3]", - "[0,0,6,7]", "[0,1,7,6]", "[2,3,4,5]", "[6,0,5,1]" - }; - uInt16 bank = myCart.getBank(); - buf << "Bank = " << std::dec << bank << ", segments = " << segments[bank & 0x7]; - - return buf.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeWDWidget::internalRamSize() -{ - return 64; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 CartridgeWDWidget::internalRamRPort(int start) -{ - return 0xF000 + start; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeWDWidget::internalRamDescription() -{ - ostringstream desc; - desc << "$F000 - $F03F used for Read Access\n" - << "$F040 - $F07F used for Write Access"; - - return desc.str(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeWDWidget::internalRamOld(int start, int count) -{ - myRamOld.clear(); - for(int i = 0; i < count; ++i) - myRamOld.push_back(myOldState.internalram[start + i]); - return myRamOld; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const ByteArray& CartridgeWDWidget::internalRamCurrent(int start, int count) -{ - myRamCurrent.clear(); - for(int i = 0; i < count; ++i) - myRamCurrent.push_back(myCart.myRAM[start + i]); - return myRamCurrent; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWDWidget::internalRamSetValue(int addr, uInt8 value) -{ - myCart.myRAM[addr] = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeWDWidget::internalRamGetValue(int addr) -{ - return myCart.myRAM[addr]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeWDWidget::internalRamLabel(int addr) -{ - CartDebug& dbg = instance().debugger().cartDebug(); - return dbg.getLabel(addr + 0xF000, false); + info << "(" << (prefix ? "hotspot " : "") + << "$" << Common::Base::HEX1 << (myCart.hotspot() + bank) << ") [" + << uInt16(banks.zero) << ", " + << uInt16(banks.one) << ", " + << uInt16(banks.two) << ", " + << uInt16(banks.three) << "]"; + + return info.str(); } diff --git a/src/debugger/gui/CartWDWidget.hxx b/src/debugger/gui/CartWDWidget.hxx index f52f4a2a9..2ccdd7437 100644 --- a/src/debugger/gui/CartWDWidget.hxx +++ b/src/debugger/gui/CartWDWidget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEWD_WIDGET_HXX class CartridgeWD; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeWDWidget : public CartDebugWidget +class CartridgeWDWidget : public CartridgeEnhancedWidget { public: CartridgeWDWidget(GuiObject* boss, const GUI::Font& lfont, @@ -32,36 +31,19 @@ class CartridgeWDWidget : public CartDebugWidget CartridgeWD& cart); virtual ~CartridgeWDWidget() = default; - private: - CartridgeWD& myCart; - PopUpWidget* myBank{nullptr}; - - struct CartState { - ByteArray internalram; - uInt16 bank{0}; // Current banking layout - }; - CartState myOldState; - - enum { kBankChanged = 'bkCH' }; +private: + CartridgeWD& myCartWD; private: - void saveOldState() override; - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + string manufacturer() override { return "Wickstead Design"; } - string bankState() override; + string description() override; - // start of functions for Cartridge RAM tab - uInt32 internalRamSize() override; - uInt32 internalRamRPort(int start) override; - string internalRamDescription() override; - const ByteArray& internalRamOld(int start, int count) override; - const ByteArray& internalRamCurrent(int start, int count) override; - void internalRamSetValue(int addr, uInt8 value) override; - uInt8 internalRamGetValue(int addr) override; - string internalRamLabel(int addr) override; - // end of functions for Cartridge RAM tab + string hotspotStr(int bank, int seg = 0, bool prefix = false) override; + uInt16 bankSegs() override { return 1; } + + private: // Following constructors and assignment operators not supported CartridgeWDWidget() = delete; CartridgeWDWidget(const CartridgeWDWidget&) = delete; diff --git a/src/debugger/gui/CartX07Widget.cxx b/src/debugger/gui/CartX07Widget.cxx index 78fd70d3b..2c4a167d4 100644 --- a/src/debugger/gui/CartX07Widget.cxx +++ b/src/debugger/gui/CartX07Widget.cxx @@ -16,94 +16,26 @@ //============================================================================ #include "CartX07.hxx" -#include "PopUpWidget.hxx" #include "CartX07Widget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeX07Widget::CartridgeX07Widget( GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, int x, int y, int w, int h, CartridgeX07& cart) - : CartDebugWidget(boss, lfont, nfont, x, y, w, h), - myCart(cart) + : CartridgeEnhancedWidget(boss, lfont, nfont, x, y, w, h, cart) { - uInt32 size = 16 * 4096; + initialize(); +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string CartridgeX07Widget::description() +{ ostringstream info; + info << "64K X07 cartridge, 16 4K banks\n" - << "Startup bank = " << cart.startBank() << "\n" << "Multiple hotspots, all below $1000\n" << "See documentation for further details\n"; + info << CartridgeEnhancedWidget::description(); - // Eventually, we should query this from the debugger/disassembler - for(uInt32 i = 0, offset = 0xFFC; i < 16; ++i, offset += 0x1000) - { - uInt16 start = (cart.myImage[offset+1] << 8) | cart.myImage[offset]; - start -= start % 0x1000; - info << "Bank " << std::dec << i << " @ $" << Common::Base::HEX4 << start - << " - " << "$" << (start + 0xFFF) << "\n"; - } - - int xpos = 2, - ypos = addBaseInformation(size, "AtariAge / John Payson / Fred Quimby", - info.str()) + myLineHeight; - - VariantList items; - VarList::push_back(items, " 0"); - VarList::push_back(items, " 1"); - VarList::push_back(items, " 2"); - VarList::push_back(items, " 3"); - VarList::push_back(items, " 4"); - VarList::push_back(items, " 5"); - VarList::push_back(items, " 6"); - VarList::push_back(items, " 7"); - VarList::push_back(items, " 8"); - VarList::push_back(items, " 9"); - VarList::push_back(items, " 10"); - VarList::push_back(items, " 11"); - VarList::push_back(items, " 12"); - VarList::push_back(items, " 13"); - VarList::push_back(items, " 14"); - VarList::push_back(items, " 15"); - myBank = - new PopUpWidget(boss, _font, xpos, ypos-2, _font.getStringWidth(" 15"), - myLineHeight, items, "Set bank ", - 0, kBankChanged); - myBank->setTarget(this); - addFocusWidget(myBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeX07Widget::loadConfig() -{ - Debugger& dbg = instance().debugger(); - CartDebug& cart = dbg.cartDebug(); - const CartState& state = static_cast(cart.getState()); - const CartState& oldstate = static_cast(cart.getOldState()); - - myBank->setSelectedIndex(myCart.getBank(), state.bank != oldstate.bank); - - CartDebugWidget::loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeX07Widget::handleCommand(CommandSender* sender, - int cmd, int data, int id) -{ - if(cmd == kBankChanged) - { - myCart.unlockBank(); - myCart.bank(myBank->getSelected()); - myCart.lockBank(); - invalidate(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartridgeX07Widget::bankState() -{ - ostringstream& buf = buffer(); - - buf << "Bank = " << std::dec << myCart.myCurrentBank; - - return buf.str(); + return info.str(); } diff --git a/src/debugger/gui/CartX07Widget.hxx b/src/debugger/gui/CartX07Widget.hxx index 00782dca8..58492e7e6 100644 --- a/src/debugger/gui/CartX07Widget.hxx +++ b/src/debugger/gui/CartX07Widget.hxx @@ -19,11 +19,10 @@ #define CARTRIDGEX07_WIDGET_HXX class CartridgeX07; -class PopUpWidget; -#include "CartDebugWidget.hxx" +#include "CartEnhancedWidget.hxx" -class CartridgeX07Widget : public CartDebugWidget +class CartridgeX07Widget : public CartridgeEnhancedWidget { public: CartridgeX07Widget(GuiObject* boss, const GUI::Font& lfont, @@ -33,17 +32,11 @@ class CartridgeX07Widget : public CartDebugWidget virtual ~CartridgeX07Widget() = default; private: - CartridgeX07& myCart; - PopUpWidget* myBank{nullptr}; + string manufacturer() override { return "AtariAge / John Payson / Fred Quimby"; } - enum { kBankChanged = 'bkCH' }; + string description() override; private: - void loadConfig() override; - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - string bankState() override; - // Following constructors and assignment operators not supported CartridgeX07Widget() = delete; CartridgeX07Widget(const CartridgeX07Widget&) = delete; diff --git a/src/debugger/gui/ControllerWidget.hxx b/src/debugger/gui/ControllerWidget.hxx index e552be284..d14c1ba69 100644 --- a/src/debugger/gui/ControllerWidget.hxx +++ b/src/debugger/gui/ControllerWidget.hxx @@ -23,6 +23,7 @@ class ButtonWidget; #include "Font.hxx" #include "Widget.hxx" +#include "OSystem.hxx" #include "Console.hxx" #include "Command.hxx" #include "ControlLowLevel.hxx" diff --git a/src/debugger/gui/CpuWidget.cxx b/src/debugger/gui/CpuWidget.cxx index cd6b87640..babdb8e08 100644 --- a/src/debugger/gui/CpuWidget.cxx +++ b/src/debugger/gui/CpuWidget.cxx @@ -93,10 +93,11 @@ CpuWidget::CpuWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n myCpuDataSrc[i]->setEditable(false, true); src_y += fontHeight+2; } - int swidth = lfont.getStringWidth("Source Address"); - new StaticTextWidget(boss, lfont, xpos, src_y + 4, src_w, - fontHeight, swidth <= src_w ? "Source Address" : "Source Addr", - TextAlign::Center); + + // Last write destination address + new StaticTextWidget(boss, lfont, xpos - fontWidth * 4.5, src_y + 4, "Dest"); + myCpuDataDest = new EditTextWidget(boss, nfont, xpos, src_y + 2, src_w, fontHeight+1); + myCpuDataDest->setEditable(false, true); // Add labels for other CPU registers xpos = x; @@ -325,6 +326,10 @@ void CpuWidget::loadConfig() myCpuDataSrc[3]->setText((srcY != EmptyString ? srcY : Common::Base::toString(state.srcY)), state.srcY != oldstate.srcY); + const string& dest = state.dest < 0 ? "" : cart.getLabel(state.dest, false); + myCpuDataDest->setText((dest != EmptyString ? dest : Common::Base::toString(state.dest)), + state.dest != oldstate.dest); + // Update the PS register booleans changed.clear(); for(uInt32 i = 0; i < state.PSbits.size(); ++i) diff --git a/src/debugger/gui/CpuWidget.hxx b/src/debugger/gui/CpuWidget.hxx index 5008002f5..5992970f3 100644 --- a/src/debugger/gui/CpuWidget.hxx +++ b/src/debugger/gui/CpuWidget.hxx @@ -76,6 +76,7 @@ class CpuWidget : public Widget, public CommandSender ToggleBitWidget* myPSRegister{nullptr}; EditTextWidget* myPCLabel{nullptr}; std::array myCpuDataSrc{nullptr}; + EditTextWidget* myCpuDataDest{nullptr}; private: // Following constructors and assignment operators not supported diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx index 9d9d25886..719eebef2 100644 --- a/src/debugger/gui/DataGridWidget.cxx +++ b/src/debugger/gui/DataGridWidget.cxx @@ -18,6 +18,7 @@ #include "Widget.hxx" #include "Dialog.hxx" #include "Font.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "FrameBuffer.hxx" #include "FBSurface.hxx" @@ -67,7 +68,8 @@ DataGridWidget::DataGridWidget(GuiObject* boss, const GUI::Font& font, // Add a scrollbar if necessary if(useScrollbar) { - _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h); + _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, + ScrollBarWidget::scrollBarWidth(_font), _h); _scrollBar->setTarget(this); _scrollBar->_numEntries = 1; _scrollBar->_currentPos = 0; @@ -675,7 +677,7 @@ Common::Rect DataGridWidget::getEditRect() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int DataGridWidget::getWidth() const { - return _w + (_scrollBar ? kScrollBarWidth : 0); + return _w + (_scrollBar ? ScrollBarWidget::scrollBarWidth(_font) : 0); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx index 47e05da04..be9ad7515 100644 --- a/src/debugger/gui/DebuggerDialog.cxx +++ b/src/debugger/gui/DebuggerDialog.cxx @@ -47,6 +47,8 @@ #include "OptionsDialog.hxx" #include "StateManager.hxx" #include "FrameManager.hxx" +#include "OSystem.hxx" +#include "Console.hxx" #include "DebuggerDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -68,15 +70,19 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent, Menu::AppMode::debugger); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +DebuggerDialog::~DebuggerDialog() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::loadConfig() { - // set initial focus to myPrompt - if (myFirstLoad) - { - setFocus(myPrompt); - myFirstLoad = false; - } + if(myFocusedWidget == nullptr) + // Set initial focus to prompt tab + myFocusedWidget = myPrompt; + // Restore focus + setFocus(myFocusedWidget); myTab->loadConfig(); myTiaInfo->loadConfig(); @@ -89,6 +95,11 @@ void DebuggerDialog::loadConfig() myMessageBox->setText(""); } +void DebuggerDialog::saveConfig() +{ + myFocusedWidget = _focusedWidget; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DebuggerDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated) { @@ -231,7 +242,7 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd, doUnwind(); break; - case kDDExitCmd: + case kDDRunCmd: doExitDebugger(); break; @@ -240,6 +251,7 @@ void DebuggerDialog::handleCommand(CommandSender* sender, int cmd, break; case kDDOptionsCmd: + saveConfig(); myOptions->open(); loadConfig(); break; @@ -541,7 +553,7 @@ void DebuggerDialog::addRomArea() wid2.push_back(b); buttonY += bheight + 4; b = new ButtonWidget(this, *myLFont, buttonX, buttonY, - bwidth, bheight, "Exit", kDDExitCmd); + bwidth, bheight, "Run", kDDRunCmd); wid2.push_back(b); addCancelWidget(b); @@ -617,7 +629,7 @@ void DebuggerDialog::addRomArea() // The 'cart-specific' information tab (optional) - tabID = myRomTab->addTab(" " + instance().console().cartridge().name() + " ", TabWidget::AUTO_WIDTH); + tabID = myRomTab->addTab(" " + instance().console().cartridge().name() + " ", TabWidget::AUTO_WIDTH); myCartInfo = instance().console().cartridge().infoWidget( myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1, tabHeight - myRomTab->getTabHeight() - 2); @@ -640,7 +652,7 @@ void DebuggerDialog::addRomArea() // The cartridge RAM tab if (myCartDebug->internalRamSize() > 0) { - tabID = myRomTab->addTab(" Cartridge RAM ", TabWidget::AUTO_WIDTH); + tabID = myRomTab->addTab(myCartDebug->tabLabel(), TabWidget::AUTO_WIDTH); myCartRam = new CartRamWidget(myRomTab, *myLFont, *myNFont, 2, 2, tabWidth - 1, tabHeight - myRomTab->getTabHeight() - 2, *myCartDebug); diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx index f9f11e459..f38e8b2dc 100644 --- a/src/debugger/gui/DebuggerDialog.hxx +++ b/src/debugger/gui/DebuggerDialog.hxx @@ -33,14 +33,16 @@ class TiaOutputWidget; class TiaZoomWidget; class CartDebugWidget; class CartRamWidget; +class OptionsDialog; +namespace GUI { + class MessageBox; +} namespace Common { struct Rect; } #include "Dialog.hxx" -#include "MessageBox.hxx" -#include "OptionsDialog.hxx" class DebuggerDialog : public Dialog { @@ -55,7 +57,7 @@ class DebuggerDialog : public Dialog DebuggerDialog(OSystem& osystem, DialogContainer& parent, int x, int y, int w, int h); - virtual ~DebuggerDialog() = default; + virtual ~DebuggerDialog(); const GUI::Font& lfont() const { return *myLFont; } const GUI::Font& nfont() const { return *myNFont; } @@ -71,6 +73,7 @@ class DebuggerDialog : public Dialog ButtonWidget& unwindButton() const { return *myUnwindButton; } void showFatalMessage(const string& msg); + void saveConfig() override; private: void center() override { positionAt(0); } @@ -110,7 +113,7 @@ class DebuggerDialog : public Dialog kDDSAdvCmd = 'DDsv', kDDRewindCmd = 'DDrw', kDDUnwindCmd = 'DDuw', - kDDExitCmd = 'DDex', + kDDRunCmd = 'DDex', kDDExitFatalCmd = 'DDer', kDDOptionsCmd = 'DDop' }; @@ -136,7 +139,8 @@ class DebuggerDialog : public Dialog unique_ptr myLFont; // used for labels unique_ptr myNFont; // used for normal text - bool myFirstLoad{true}; + Widget* myFocusedWidget{nullptr}; + private: // Following constructors and assignment operators not supported diff --git a/src/debugger/gui/FlashWidget.cxx b/src/debugger/gui/FlashWidget.cxx index ace5e30cb..3c2614659 100644 --- a/src/debugger/gui/FlashWidget.cxx +++ b/src/debugger/gui/FlashWidget.cxx @@ -30,7 +30,6 @@ FlashWidget::FlashWidget(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FlashWidget::init(GuiObject* boss, const GUI::Font& font, int x, int y) { - const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = font.getLineHeight(); int xpos = x, ypos = y; @@ -38,14 +37,14 @@ void FlashWidget::init(GuiObject* boss, const GUI::Font& font, int x, int y) ypos += lineHeight + 6; - new StaticTextWidget(boss, ifont, xpos, ypos, "Pages/Ranges used:"); + new StaticTextWidget(boss, font, xpos, ypos, "Pages/Ranges used:"); ypos += lineHeight + 2; xpos += 8; for(uInt32 page = 0; page < MAX_PAGES; ++page) { - myPage[page] = new StaticTextWidget(boss, ifont, xpos, ypos, + myPage[page] = new StaticTextWidget(boss, font, xpos, ypos, page ? " " : "none "); ypos += lineHeight; } diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index a7910f8e8..7a1cd56f2 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -20,6 +20,7 @@ #include "Font.hxx" #include "StellaKeys.hxx" #include "Version.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "DebuggerDialog.hxx" #include "DebuggerParser.hxx" @@ -33,7 +34,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) - : Widget(boss, font, x, y, w - kScrollBarWidth, h), + : Widget(boss, font, x, y, w - ScrollBarWidget::scrollBarWidth(font), h), CommandSender(boss), _historySize(0), _historyIndex(0), @@ -53,12 +54,13 @@ PromptWidget::PromptWidget(GuiObject* boss, const GUI::Font& font, _kConsoleLineHeight = _kConsoleCharHeight + 2; // Calculate depending values - _lineWidth = (_w - kScrollBarWidth - 2) / _kConsoleCharWidth; + _lineWidth = (_w - ScrollBarWidget::scrollBarWidth(_font) - 2) / _kConsoleCharWidth; _linesPerPage = (_h - 2) / _kConsoleLineHeight; _linesInBuffer = kBufferSize / _lineWidth; // Add scrollbar - _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h); + _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, + ScrollBarWidget::scrollBarWidth(_font), _h); _scrollBar->setTarget(this); // Init colors @@ -546,7 +548,7 @@ void PromptWidget::loadConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int PromptWidget::getWidth() const { - return _w + kScrollBarWidth; + return _w + ScrollBarWidget::scrollBarWidth(_font); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -907,10 +909,7 @@ void PromptWidget::scrollToCurrent() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool PromptWidget::saveBuffer(const FilesystemNode& file) { - ofstream out(file.getPath()); - if(!out.is_open()) - return false; - + stringstream out; for(int start = 0; start < _promptStartPos; start += _lineWidth) { int end = start + _lineWidth - 1; @@ -928,7 +927,8 @@ bool PromptWidget::saveBuffer(const FilesystemNode& file) out << endl; } - return true; + try { return file.write(out) > 0; } + catch(...) { return false; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/gui/RiotRamWidget.cxx b/src/debugger/gui/RiotRamWidget.cxx index 2666182ec..5f3d5c0ab 100644 --- a/src/debugger/gui/RiotRamWidget.cxx +++ b/src/debugger/gui/RiotRamWidget.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" diff --git a/src/debugger/gui/RiotWidget.cxx b/src/debugger/gui/RiotWidget.cxx index eef3cce66..43514e072 100644 --- a/src/debugger/gui/RiotWidget.cxx +++ b/src/debugger/gui/RiotWidget.cxx @@ -214,7 +214,7 @@ RiotWidget::RiotWidget(GuiObject* boss, const GUI::Font& lfont, // 2600/7800 mode lwidth = lfont.getStringWidth("Console") + 29; - pwidth = lfont.getStringWidth("Atari 2600") + 4; + pwidth = lfont.getStringWidth("Atari 2600") + 6; new StaticTextWidget(boss, lfont, 10, ypos+1, "Console"); myConsole = new EditTextWidget(boss, lfont, 10 + lwidth, ypos - 1, pwidth, lineHeight); myConsole->setEditable(false, true); diff --git a/src/debugger/gui/RomListSettings.cxx b/src/debugger/gui/RomListSettings.cxx index edc65dfd5..9c3baf3d2 100644 --- a/src/debugger/gui/RomListSettings.cxx +++ b/src/debugger/gui/RomListSettings.cxx @@ -30,7 +30,7 @@ RomListSettings::RomListSettings(GuiObject* boss, const GUI::Font& font) : Dialog(boss->instance(), boss->parent()), CommandSender(boss) { - const int buttonWidth = font.getStringWidth("RunTo PC @ current line") + 20, + const int buttonWidth = font.getStringWidth("Disassemble @ current line") + 20, buttonHeight = font.getLineHeight() + 4; int xpos = 8, ypos = 8; WidgetArray wid; @@ -52,7 +52,7 @@ RomListSettings::RomListSettings(GuiObject* boss, const GUI::Font& font) ypos += buttonHeight + 4; ButtonWidget* disasm = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, - "Re-disassemble", RomListWidget::kDisassembleCmd); + "Disassemble @ current line", RomListWidget::kDisassembleCmd); wid.push_back(disasm); // Settings for Distella @@ -151,7 +151,7 @@ void RomListSettings::handleCommand(CommandSender* sender, int cmd, int data, in } case RomListWidget::kDisassembleCmd: { - sendCommand(cmd, -1, -1); + sendCommand(cmd, _item, -1); break; } case RomListWidget::kTentativeCodeCmd: diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 8a705f3b1..6e450e334 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "bspf.hxx" +#include "OSystem.hxx" #include "Debugger.hxx" #include "DiStella.hxx" #include "Widget.hxx" @@ -42,11 +43,12 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont, _rows = h / _fontHeight; // Set real dimensions - _w = w - kScrollBarWidth; + _w = w - ScrollBarWidget::scrollBarWidth(_font); _h = h + 2; // Create scrollbar and attach to the list - myScrollBar = new ScrollBarWidget(boss, lfont, _x + _w, _y, kScrollBarWidth, _h); + myScrollBar = new ScrollBarWidget(boss, lfont, _x + _w, _y, + ScrollBarWidget::scrollBarWidth(_font), _h); myScrollBar->setTarget(this); // Add settings menu @@ -65,7 +67,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont, // rowheight is determined by largest item on a line, // possibly meaning that number of rows will change - _fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize()); + _fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize(_font)); _rows = h / _fontHeight; // Create a CheckboxWidget for each row in the list @@ -465,7 +467,7 @@ void RomListWidget::drawWidget(bool hilite) // Draw a thin frame around the list and to separate columns s.frameRect(_x, _y, _w + 1, _h, hilite ? kWidColorHi : kColor); - s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor); + s.vLine(_x + CheckboxWidget::boxSize(_font) + 5, _y, _y + _h - 1, kColor); // Draw the list items int cycleCountW = _fontWidth * 8, @@ -476,7 +478,7 @@ void RomListWidget::drawWidget(bool hilite) if(actualWidth < codeDisasmW) codeDisasmW = actualWidth; - xpos = _x + CheckboxWidget::boxSize() + 10; ypos = _y + 2; + xpos = _x + CheckboxWidget::boxSize(_font) + 10; ypos = _y + 2; for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++, ypos += _fontHeight) { ColorId bytesColor = textColor; @@ -511,9 +513,10 @@ void RomListWidget::drawWidget(bool hilite) // Bytes are only editable if they represent code, graphics, or accessible data // Otherwise, the disassembly should get all remaining space - if(dlist[pos].type & (CartDebug::CODE|CartDebug::GFX|CartDebug::PGFX|CartDebug::DATA)) + if(dlist[pos].type & (Device::CODE|Device::GFX|Device::PGFX| + Device::COL|Device::PCOL|Device::BCOL|Device::DATA)) { - if(dlist[pos].type == CartDebug::CODE) + if(dlist[pos].type == Device::CODE) { // Draw mnemonic s.drawString(_font, dlist[pos].disasm.substr(0, 7), xpos + _labelWidth, ypos, @@ -565,7 +568,7 @@ void RomListWidget::drawWidget(bool hilite) Common::Rect RomListWidget::getLineRect() const { const int yoffset = std::max(0, (_selectedItem - _currentPos) * _fontHeight), - xoffset = CheckboxWidget::boxSize() + 10; + xoffset = CheckboxWidget::boxSize(_font) + 10; return Common::Rect(2 + xoffset, 1 + yoffset, _w - (xoffset - 15), _fontHeight + yoffset); @@ -592,8 +595,8 @@ void RomListWidget::startEditMode() _editMode = true; switch(myDisasm->list[_selectedItem].type) { - case CartDebug::GFX: - case CartDebug::PGFX: + case Device::GFX: + case Device::PGFX: _base = DiStella::settings.gfxFormat; break; default: diff --git a/src/debugger/gui/RomWidget.cxx b/src/debugger/gui/RomWidget.cxx index 18c8b0b78..9b387d69f 100644 --- a/src/debugger/gui/RomWidget.cxx +++ b/src/debugger/gui/RomWidget.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Settings.hxx" #include "Debugger.hxx" #include "CartDebug.hxx" @@ -41,12 +42,9 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& n // Show current bank state xpos = x; ypos = y + 7; - t = new StaticTextWidget(boss, lfont, xpos, ypos, - lfont.getStringWidth("Bank"), - lfont.getFontHeight(), - "Bank", TextAlign::Left); + t = new StaticTextWidget(boss, lfont, xpos, ypos, "Info "); - xpos += t->getWidth() + 5; + xpos += t->getRight(); myBank = new EditTextWidget(boss, nfont, xpos, ypos-2, _w - 2 - xpos, nfont.getLineHeight()); myBank->setEditable(false); @@ -68,7 +66,7 @@ void RomWidget::loadConfig() const CartState& oldstate = static_cast(cart.getOldState()); // Fill romlist the current bank of source or disassembly - myListIsDirty |= cart.disassemble(myListIsDirty); + myListIsDirty |= cart.disassemblePC(myListIsDirty); if(myListIsDirty) { myRomList->setList(cart.disassembly()); @@ -115,7 +113,8 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) break; case RomListWidget::kDisassembleCmd: - invalidate(); + // 'data' is the line in the disassemblylist to be accessed + disassemble(data); break; case RomListWidget::kTentativeCodeCmd: @@ -167,26 +166,25 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomWidget::toggleBreak(int disasm_line) { - const CartDebug::DisassemblyList& list = - instance().debugger().cartDebug().disassembly().list; - if(disasm_line >= int(list.size())) return; + const uInt16 address = getAddress(disasm_line); - if(list[disasm_line].address != 0 && list[disasm_line].bytes != "") - instance().debugger().toggleBreakPoint(list[disasm_line].address, - instance().debugger().cartDebug().getBank(list[disasm_line].address)); + if (address != 0) + { + Debugger& debugger = instance().debugger(); + + debugger.toggleBreakPoint(address, debugger.cartDebug().getBank(address)); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomWidget::setPC(int disasm_line) { - const CartDebug::DisassemblyList& list = - instance().debugger().cartDebug().disassembly().list; - if(disasm_line >= int(list.size())) return; + const uInt16 address = getAddress(disasm_line); - if(list[disasm_line].address != 0) + if(address != 0) { ostringstream command; - command << "pc #" << list[disasm_line].address; + command << "pc #" << address; instance().debugger().run(command.str()); } } @@ -194,15 +192,29 @@ void RomWidget::setPC(int disasm_line) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomWidget::runtoPC(int disasm_line) { - const CartDebug::DisassemblyList& list = - instance().debugger().cartDebug().disassembly().list; - if(disasm_line >= int(list.size())) return; + const uInt16 address = getAddress(disasm_line); - if(list[disasm_line].address != 0) + if(address != 0) { ostringstream command; - command << "runtopc #" << list[disasm_line].address; - instance().debugger().run(command.str()); + command << "runtopc #" << address; + string msg = instance().debugger().run(command.str()); + instance().frameBuffer().showMessage(msg); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RomWidget::disassemble(int disasm_line) +{ + const uInt16 address = getAddress(disasm_line); + + if(address != 0) + { + CartDebug& cart = instance().debugger().cartDebug(); + + cart.disassembleAddr(address, true); + invalidate(); + scrollTo(cart.addressToLine(address)); // the line might have been changed } } @@ -210,11 +222,9 @@ void RomWidget::runtoPC(int disasm_line) void RomWidget::patchROM(int disasm_line, const string& bytes, Common::Base::Fmt base) { - const CartDebug::DisassemblyList& list = - instance().debugger().cartDebug().disassembly().list; - if(disasm_line >= int(list.size())) return; + const uInt16 address = getAddress(disasm_line); - if(list[disasm_line].address != 0) + if(address != 0) { ostringstream command; @@ -223,7 +233,7 @@ void RomWidget::patchROM(int disasm_line, const string& bytes, Common::Base::Fmt oldbase = Common::Base::format(); Common::Base::setFormat(base); - command << "rom #" << list[disasm_line].address << " " << bytes; + command << "rom #" << address << " " << bytes; instance().debugger().run(command.str()); // Restore previous base @@ -231,6 +241,18 @@ void RomWidget::patchROM(int disasm_line, const string& bytes, } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 RomWidget::getAddress(int disasm_line) +{ + const CartDebug::DisassemblyList& list = + instance().debugger().cartDebug().disassembly().list; + + if (disasm_line < int(list.size()) && list[disasm_line].address != 0) + return list[disasm_line].address; + else + return 0; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomWidget::scrollTo(int line) { diff --git a/src/debugger/gui/RomWidget.hxx b/src/debugger/gui/RomWidget.hxx index 9c794a9f1..8dc4aabee 100644 --- a/src/debugger/gui/RomWidget.hxx +++ b/src/debugger/gui/RomWidget.hxx @@ -51,8 +51,10 @@ class RomWidget : public Widget, public CommandSender void toggleBreak(int disasm_line); void setPC(int disasm_line); void runtoPC(int disasm_line); + void disassemble(int disasm_line); void patchROM(int disasm_line, const string& bytes, Common::Base::Fmt base); + uInt16 getAddress(int disasm_line); private: RomListWidget* myRomList{nullptr}; diff --git a/src/debugger/gui/TiaInfoWidget.cxx b/src/debugger/gui/TiaInfoWidget.cxx index 788f28c27..21681d2c0 100644 --- a/src/debugger/gui/TiaInfoWidget.cxx +++ b/src/debugger/gui/TiaInfoWidget.cxx @@ -34,15 +34,16 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont, : Widget(boss, lfont, x, y, 16, 16), CommandSender(boss) { - bool longstr = 34 * lfont.getMaxCharWidth() <= max_w; + bool longstr = 11 + 32 * lfont.getMaxCharWidth() + 9 + + EditTextWidget::calcWidth(lfont) * 3 <= max_w; const int VGAP = 5; x += 11; const int lineHeight = lfont.getLineHeight(); int xpos = x, ypos = y + 10; int lwidth = lfont.getStringWidth(longstr ? "Frame Cycle " : "F. Cycle "); - int fwidth = 5 * lfont.getMaxCharWidth() + 4; - int twidth = 8 * lfont.getMaxCharWidth() + 4; + int fwidth = EditTextWidget::calcWidth(lfont, 5); + int twidth = EditTextWidget::calcWidth(lfont, 8); // Add frame info // 1st column @@ -78,11 +79,9 @@ TiaInfoWidget::TiaInfoWidget(GuiObject* boss, const GUI::Font& lfont, // 2nd column xpos = x + lwidth + myFrameCycles->getWidth() + 9; ypos = y + 10; lwidth = lfont.getStringWidth(longstr ? "Color Clock " : "Pixel Pos "); - fwidth = 3 * lfont.getMaxCharWidth() + 4; + fwidth = EditTextWidget::calcWidth(lfont, 3); - new StaticTextWidget(boss, lfont, xpos, ypos, - lfont.getStringWidth(longstr ? "Scanline" : "Scn Ln"), lineHeight, - longstr ? "Scanline" : "Scn Ln", TextAlign::Left); + new StaticTextWidget(boss, lfont, xpos, ypos, longstr ? "Scanline" : "Scn Ln"); myScanlineCountLast = new EditTextWidget(boss, nfont, xpos+lwidth, ypos-1, fwidth, lineHeight, ""); myScanlineCountLast->setEditable(false, true); @@ -143,10 +142,10 @@ void TiaInfoWidget::loadConfig() uInt64 total = tia.cyclesLo() + (uInt64(tia.cyclesHi()) << 32); uInt64 totalOld = oldTia.info[2] + (uInt64(oldTia.info[3]) << 32); - myTotalCycles->setText(Common::Base::toString(total / 1000000, Common::Base::Fmt::_10_6) + "e6", + myTotalCycles->setText(Common::Base::toString(uInt32(total) / 1000000, Common::Base::Fmt::_10_6) + "e6", total != totalOld); - uInt32 delta = total - totalOld; - myDeltaCycles->setText(Common::Base::toString(delta, Common::Base::Fmt::_10_8)); // no coloring + uInt64 delta = total - totalOld; + myDeltaCycles->setText(Common::Base::toString(uInt32(delta), Common::Base::Fmt::_10_8)); // no coloring int clk = tia.clocksThisLine(); myScanlineCount->setText(Common::Base::toString(tia.scanlines(), Common::Base::Fmt::_10_3), diff --git a/src/debugger/gui/TiaOutputWidget.cxx b/src/debugger/gui/TiaOutputWidget.cxx index 5277647dc..01d6d094b 100644 --- a/src/debugger/gui/TiaOutputWidget.cxx +++ b/src/debugger/gui/TiaOutputWidget.cxx @@ -179,7 +179,7 @@ void TiaOutputWidget::drawWidget(bool hilite) bool visible = instance().console().tia().electronBeamPos(scanx, scany); scanoffset = width * scany + scanx; uInt8* tiaOutputBuffer = instance().console().tia().outputBuffer(); - TIASurface& tiaSurface(instance().frameBuffer().tiaSurface()); + const TIASurface& tiaSurface = instance().frameBuffer().tiaSurface(); for(uInt32 y = 0, i = yStart * width; y < height; ++y) { diff --git a/src/debugger/gui/module.mk b/src/debugger/gui/module.mk index d80408a60..d992ae85a 100644 --- a/src/debugger/gui/module.mk +++ b/src/debugger/gui/module.mk @@ -22,14 +22,13 @@ MODULE_OBJS := \ src/debugger/gui/CartCDFInfoWidget.o \ src/debugger/gui/CartCMWidget.o \ src/debugger/gui/CartCTYWidget.o \ - src/debugger/gui/CartCVPlusWidget.o \ src/debugger/gui/CartCVWidget.o \ - src/debugger/gui/CartDASHWidget.o \ src/debugger/gui/CartDFSCWidget.o \ src/debugger/gui/CartDFWidget.o \ src/debugger/gui/CartDPCPlusWidget.o \ src/debugger/gui/CartDPCWidget.o \ src/debugger/gui/CartE0Widget.o \ + src/debugger/gui/CartEnhancedWidget.o \ src/debugger/gui/CartMNetworkWidget.o \ src/debugger/gui/CartE7Widget.o \ src/debugger/gui/CartE78KWidget.o \ @@ -49,6 +48,7 @@ MODULE_OBJS := \ src/debugger/gui/CartMDMWidget.o \ src/debugger/gui/CartRamWidget.o \ src/debugger/gui/CartSBWidget.o \ + src/debugger/gui/CartTVBoyWidget.o \ src/debugger/gui/CartUAWidget.o \ src/debugger/gui/CartWDWidget.o \ src/debugger/gui/CartX07Widget.o \ diff --git a/src/emucore/AtariVox.cxx b/src/emucore/AtariVox.cxx index 3314ac08c..fd75024e4 100644 --- a/src/emucore/AtariVox.cxx +++ b/src/emucore/AtariVox.cxx @@ -22,7 +22,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AtariVox::AtariVox(Jack jack, const Event& event, const System& system, - const string& portname, const string& eepromfile, + const string& portname, const FilesystemNode& eepromfile, const onMessageCallback& callback) : SaveKey(jack, event, system, eepromfile, callback, Controller::Type::AtariVox) { @@ -36,6 +36,11 @@ AtariVox::AtariVox(Jack jack, const Event& event, const System& system, setPin(DigitalPin::Four, true); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AtariVox::~AtariVox() +{ +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool AtariVox::read(DigitalPin pin) { @@ -45,9 +50,12 @@ bool AtariVox::read(DigitalPin pin) switch(pin) { // Pin 2: SpeakJet READY + // CTS (Clear To Send) is connected inverted + // So CTS = 0 means the buffer is full, which pulls pin 2 high case DigitalPin::Two: - // For now, we just assume the device is always ready - return setPin(pin, true); + { + return setPin(pin, !mySerialPort->isCTS()); + } default: return SaveKey::read(pin); diff --git a/src/emucore/AtariVox.hxx b/src/emucore/AtariVox.hxx index b21ec38b0..3251234ed 100644 --- a/src/emucore/AtariVox.hxx +++ b/src/emucore/AtariVox.hxx @@ -19,10 +19,11 @@ #define ATARIVOX_HXX class OSystem; +class SerialPort; +class FilesystemNode; #include "Control.hxx" #include "SaveKey.hxx" -#include "SerialPort.hxx" /** Richard Hutchinson's AtariVox "controller": A speech synthesizer and @@ -47,9 +48,9 @@ class AtariVox : public SaveKey @param callback Called to pass messages back to the parent controller */ AtariVox(Jack jack, const Event& event, const System& system, - const string& portname, const string& eepromfile, + const string& portname, const FilesystemNode& eepromfile, const onMessageCallback& callback); - virtual ~AtariVox() = default; + virtual ~AtariVox(); public: using Controller::read; @@ -78,6 +79,11 @@ class AtariVox : public SaveKey */ void update() override { } + /** + Returns the name of this controller. + */ + string name() const override { return "AtariVox"; } + /** Notification method invoked by the system after its reset method has been called. It may be necessary to override this method for diff --git a/src/emucore/Bankswitch.cxx b/src/emucore/Bankswitch.cxx index 231d6f73f..2ea053df1 100644 --- a/src/emucore/Bankswitch.cxx +++ b/src/emucore/Bankswitch.cxx @@ -104,8 +104,9 @@ Bankswitch::BSList = {{ { "64IN1" , "64IN1 Multicart (128/256K)" }, { "128IN1" , "128IN1 Multicart (256/512K)" }, { "2K" , "2K (32-2048 bytes Atari)" }, - { "3E" , "3E (32K Tigervision)" }, - { "3E+" , "3E+ (TJ modified DASH)" }, + { "3E" , "3E (Tigervision, 32K RAM)" }, + { "3EX" , "3EX (Tigervision, 256K RAM)" }, + { "3E+" , "3E+ (TJ modified 3E)" }, { "3F" , "3F (512K Tigervision)" }, { "4A50" , "4A50 (64K 4A50 + RAM)" }, { "4K" , "4K (4K Atari)" }, @@ -118,8 +119,6 @@ Bankswitch::BSList = {{ { "CM" , "CM (SpectraVideo CompuMate)" }, { "CTY" , "CTY (CDW - Chetiry)" }, { "CV" , "CV (Commavid extra RAM)" }, - { "CV+" , "CV+ (Extended Commavid)" }, - { "DASH" , "DASH (Experimental)" }, { "DF" , "DF (CPUWIZ 128K)" }, { "DFSC" , "DFSC (CPUWIZ 128K + RAM)" }, { "DPC" , "DPC (Pitfall II)" }, @@ -142,6 +141,7 @@ Bankswitch::BSList = {{ { "FE" , "FE (8K Decathlon)" }, { "MDM" , "MDM (Menu Driven Megacart)" }, { "SB" , "SB (128-256K SUPERbank)" }, + { "TVBOY" , "TV Boy (512K)" }, { "UA" , "UA (8K UA Ltd.)" }, { "UASW" , "UASW (8K UA swapped banks)" }, { "WD" , "WD (Pink Panther)" }, @@ -180,6 +180,7 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "128N1" , Bankswitch::Type::_128IN1 }, { "2K" , Bankswitch::Type::_2K }, { "3E" , Bankswitch::Type::_3E }, + { "3EX" , Bankswitch::Type::_3EX }, { "3EP" , Bankswitch::Type::_3EP }, { "3E+" , Bankswitch::Type::_3EP }, { "3F" , Bankswitch::Type::_3F }, @@ -197,9 +198,6 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "CM" , Bankswitch::Type::_CM }, { "CTY" , Bankswitch::Type::_CTY }, { "CV" , Bankswitch::Type::_CV }, - { "CVP" , Bankswitch::Type::_CVP }, - { "DAS" , Bankswitch::Type::_DASH }, - { "DASH" , Bankswitch::Type::_DASH }, { "DF" , Bankswitch::Type::_DF }, { "DFS" , Bankswitch::Type::_DFSC }, { "DFSC" , Bankswitch::Type::_DFSC }, @@ -229,6 +227,8 @@ Bankswitch::ExtensionMap Bankswitch::ourExtensions = { { "FE" , Bankswitch::Type::_FE }, { "MDM" , Bankswitch::Type::_MDM }, { "SB" , Bankswitch::Type::_SB }, + { "TVB" , Bankswitch::Type::_TVBOY }, + { "TVBOY" , Bankswitch::Type::_TVBOY }, { "UA" , Bankswitch::Type::_UA }, { "UASW" , Bankswitch::Type::_UASW }, { "WD" , Bankswitch::Type::_WD }, @@ -250,6 +250,7 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { { "2K" , Bankswitch::Type::_2K }, { "3E" , Bankswitch::Type::_3E }, { "3E+" , Bankswitch::Type::_3EP }, + { "3EX" , Bankswitch::Type::_3EX }, { "3F" , Bankswitch::Type::_3F }, { "4A50" , Bankswitch::Type::_4A50 }, { "4K" , Bankswitch::Type::_4K }, @@ -262,8 +263,6 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { { "CM" , Bankswitch::Type::_CM }, { "CTY" , Bankswitch::Type::_CTY }, { "CV" , Bankswitch::Type::_CV }, - { "CV+" , Bankswitch::Type::_CVP }, - { "DASH" , Bankswitch::Type::_DASH }, { "DF" , Bankswitch::Type::_DF }, { "DFSC" , Bankswitch::Type::_DFSC }, { "DPC" , Bankswitch::Type::_DPC }, @@ -286,6 +285,7 @@ Bankswitch::NameToTypeMap Bankswitch::ourNameToTypes = { { "FE" , Bankswitch::Type::_FE }, { "MDM" , Bankswitch::Type::_MDM }, { "SB" , Bankswitch::Type::_SB }, + { "TVBOY" , Bankswitch::Type::_TVBOY }, { "UA" , Bankswitch::Type::_UA }, { "UASW" , Bankswitch::Type::_UASW }, { "WD" , Bankswitch::Type::_WD }, diff --git a/src/emucore/Bankswitch.hxx b/src/emucore/Bankswitch.hxx index c57f81609..6ef5da867 100644 --- a/src/emucore/Bankswitch.hxx +++ b/src/emucore/Bankswitch.hxx @@ -38,14 +38,14 @@ class Bankswitch public: // Currently supported bankswitch schemes enum class Type { - _AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1, - _64IN1, _128IN1, _2K, _3E, _3EP, _3F, _4A50, - _4K, _4KSC, _AR, _BF, _BFSC, _BUS, _CDF, - _CM, _CTY, _CV, _CVP, _DASH, _DF, _DFSC, - _DPC, _DPCP, _E0, _E7, _E78K, _EF, _EFSC, - _F0, _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, - _FA, _FA2, _FC, _FE, _MDM, _SB, _UA, - _UASW, _WD, _WDSW, _X07, + _AUTO, _0840, _2IN1, _4IN1, _8IN1, _16IN1, _32IN1, + _64IN1, _128IN1, _2K, _3E, _3EX, _3EP, _3F, + _4A50, _4K, _4KSC, _AR, _BF, _BFSC, _BUS, + _CDF, _CM, _CTY, _CV, _DF, _DFSC, _DPC, + _DPCP, _E0, _E7, _E78K, _EF, _EFSC, _F0, + _F4, _F4SC, _F6, _F6SC, _F8, _F8SC, _FA, + _FA2, _FC, _FE, _MDM, _SB, _TVBOY, _UA, + _UASW, _WD, _WDSW, _X07, #ifdef CUSTOM_ARM _CUSTOM, #endif diff --git a/src/emucore/Booster.cxx b/src/emucore/Booster.cxx index fddd51c21..96d328b8a 100644 --- a/src/emucore/Booster.cxx +++ b/src/emucore/Booster.cxx @@ -59,7 +59,7 @@ void BoosterGrip::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; // The CBS Booster-grip has two more buttons on it. These buttons are // connected to the inputs usually used by paddles. @@ -120,11 +120,12 @@ void BoosterGrip::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); if(myEvent.get(Event::MouseButtonRightValue)) setPin(AnalogPin::Nine, MIN_RESISTANCE); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index 3f1f53690..d4b5c5c22 100644 --- a/src/emucore/Cart.cxx +++ b/src/emucore/Cart.cxx @@ -15,12 +15,13 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "FSNode.hxx" #include "Settings.hxx" #include "System.hxx" #include "MD5.hxx" #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" - #include "CartDebug.hxx" + #include "Base.hxx" #endif #include "Cart.hxx" @@ -39,7 +40,7 @@ Cartridge::Cartridge(const Settings& settings, const string& md5) for(uInt32 i = 0; i < 256; ++i) myRWPRandomValues[i] = rand.next(); - myRAMAccesses.reserve(5); + myRamReadAccesses.reserve(5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -52,19 +53,24 @@ void Cartridge::setAbout(const string& about, const string& type, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge::saveROM(ofstream& out) const +bool Cartridge::saveROM(const FilesystemNode& out) const { - size_t size = 0; - - const uInt8* image = getImage(size); - if(image == nullptr || size == 0) + try + { + size_t size = 0; + const ByteBuffer& image = getImage(size); + if(size == 0) + { + cerr << "save not supported" << endl; + return false; + } + out.write(image, size); + } + catch(...) { - cerr << "save not supported" << endl; return false; } - out.write(reinterpret_cast(image), size); - return true; } @@ -76,6 +82,16 @@ bool Cartridge::bankChanged() return changed; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 Cartridge::bankSize(uInt16 bank) const +{ + size_t size; + getImage(size); + + return static_cast( + std::min(size / romBankCount(), 4_KB)); // assuming that each bank has the same size +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address) { @@ -87,7 +103,7 @@ uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address) if(!bankLocked() && !mySystem->autodetectMode()) { // Record access here; final determination will happen in ::pokeRAM() - myRAMAccesses.push_back(address); + myRamReadAccesses.push_back(address); dest = value; } #else @@ -101,11 +117,11 @@ uInt8 Cartridge::peekRAM(uInt8& dest, uInt16 address) void Cartridge::pokeRAM(uInt8& dest, uInt16 address, uInt8 value) { #ifdef DEBUGGER_SUPPORT - for(auto i = myRAMAccesses.begin(); i != myRAMAccesses.end(); ++i) + for(auto i = myRamReadAccesses.begin(); i != myRamReadAccesses.end(); ++i) { if(*i == address) { - myRAMAccesses.erase(i); + myRamReadAccesses.erase(i); break; } } @@ -114,16 +130,96 @@ void Cartridge::pokeRAM(uInt8& dest, uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge::createCodeAccessBase(size_t size) +void Cartridge::createRomAccessArrays(size_t size) { + myAccessSize = uInt32(size); #ifdef DEBUGGER_SUPPORT - myCodeAccessBase = make_unique(size); - std::fill_n(myCodeAccessBase.get(), size, CartDebug::ROW); + myRomAccessBase = make_unique(size); + std::fill_n(myRomAccessBase.get(), size, Device::ROW); + myRomAccessCounter = make_unique(size * 2); + std::fill_n(myRomAccessCounter.get(), size * 2, 0); #else - myCodeAccessBase = nullptr; + myRomAccessBase = nullptr; + myRomAccessCounter = nullptr; #endif } +#ifdef DEBUGGER_SUPPORT +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string Cartridge::getAccessCounters() const +{ + ostringstream out; + uInt32 offset = 0; + + for(uInt16 bank = 0; bank < romBankCount(); ++bank) + { + uInt16 origin = bankOrigin(bank); + uInt16 bankSize = this->bankSize(bank); + + out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.." + << Common::Base::toString(romBankCount() - 1, Common::Base::Fmt::_10_8) << " reads:\n"; + for(uInt16 addr = 0; addr < bankSize; ++addr) + { + out << Common::Base::HEX4 << (addr | origin) << "," + << Common::Base::toString(myRomAccessCounter[offset + addr], Common::Base::Fmt::_10_8) << ", "; + } + out << "\n"; + out << "Bank " << Common::Base::toString(bank, Common::Base::Fmt::_10_8) << " / 0.." + << Common::Base::toString(romBankCount() - 1, Common::Base::Fmt::_10_8) << " writes:\n"; + for(uInt16 addr = 0; addr < bankSize; ++addr) + { + out << Common::Base::HEX4 << (addr | origin) << "," + << Common::Base::toString(myRomAccessCounter[offset + addr + myAccessSize], Common::Base::Fmt::_10_8) << ", "; + } + out << "\n"; + + offset += bankSize; + } + + return out.str(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 Cartridge::bankOrigin(uInt16 bank) const +{ + // isolate the high 3 address bits, count them and + // select the most frequent to define the bank origin + // TODO: origin for banks smaller than 4K + const int intervals = 0x8000 / 0x100; + uInt32 offset = bank * bankSize(); + //uInt16 addrMask = (4_KB - 1) & ~(bankSize(bank) - 1); + //int addrShift = 0; + std::array count; // up to 128 256 byte interval origins + + + //if(addrMask) + // addrShift = log(addrMask) / log(2); + //addrMask; + + count.fill(0); + for(uInt16 addr = 0x0000; addr < bankSize(bank); ++addr) + { + Device::AccessFlags flags = myRomAccessBase[offset + addr]; + // only count really accessed addresses + if(flags & ~Device::ROW) + { + //uInt16 addrBit = addr >> addrShift; + count[(flags & Device::HADDR) >> 13]++; + } + } + uInt16 max = 0, maxIdx = 0; + for(int idx = 0; idx < intervals; ++idx) + { + if(count[idx] > max) + { + max = count[idx]; + maxIdx = idx; + } + } + return maxIdx << 13 | 0x1000; //| (offset & 0xfff); +} +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge::initializeRAM(uInt8* arr, size_t size, uInt8 val) const { @@ -140,11 +236,11 @@ uInt16 Cartridge::initializeStartBank(uInt16 defaultBank) int propsBank = myStartBankFromPropsFunc(); if(randomStartBank()) - return myStartBank = mySystem->randGenerator().next() % bankCount(); + return myStartBank = mySystem->randGenerator().next() % romBankCount(); else if(propsBank >= 0) - return myStartBank = BSPF::clamp(propsBank, 0, bankCount() - 1); + return myStartBank = BSPF::clamp(propsBank, 0, romBankCount() - 1); else - return myStartBank = BSPF::clamp(int(defaultBank), 0, bankCount() - 1); + return myStartBank = BSPF::clamp(int(defaultBank), 0, romBankCount() - 1); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx index 9d79d390a..bc52104c0 100644 --- a/src/emucore/Cart.hxx +++ b/src/emucore/Cart.hxx @@ -20,15 +20,20 @@ class Cartridge; class Properties; +class FilesystemNode; class CartDebugWidget; class CartRamWidget; class GuiObject; +class Settings; + +#include #include "bspf.hxx" #include "Device.hxx" -#include "Settings.hxx" #ifdef DEBUGGER_SUPPORT - #include "Font.hxx" + namespace GUI { + class Font; + } #endif /** @@ -44,6 +49,9 @@ class Cartridge : public Device public: using StartBankFromPropsFunc = std::function; + // Maximum size of a ROM cart that Stella can support + static constexpr size_t maxSize() { return 512_KB; } + public: /** Create a new cartridge @@ -65,9 +73,9 @@ class Cartridge : public Device /** Save the internal (patched) ROM image. - @param out The output file stream to save the image + @param out The output file to save the image */ - bool saveROM(ofstream& out) const; + bool saveROM(const FilesystemNode& out) const; /** Lock/unlock bankswitching capability. The debugger will lock @@ -126,7 +134,7 @@ class Cartridge : public Device Clears information about all accesses to cart RAM. */ void clearAllRAMAccesses() { - myRAMAccesses.clear(); + myRamReadAccesses.clear(); myRamWriteAccess = 0; } @@ -138,7 +146,7 @@ class Cartridge : public Device @return Address of illegal access if one occurred, else 0 */ uInt16 getIllegalRAMReadAccess() const { - return myRAMAccesses.size() > 0 ? myRAMAccesses[0] : 0; + return myRamReadAccesses.size() > 0 ? myRamReadAccesses[0] : 0; } /** @@ -149,6 +157,21 @@ class Cartridge : public Device @return Address of illegal access if one occurred, else 0 */ uInt16 getIllegalRAMWriteAccess() const { return myRamWriteAccess; } + + /** + Query the access counters + + @return The access counters as comma separated string + */ + string getAccessCounters() const override; + + /** + Determine the bank's origin + + @param bank The bank to query + @return The origin of the bank + */ + uInt16 bankOrigin(uInt16 bank) const; #endif public: @@ -163,8 +186,13 @@ class Cartridge : public Device scheme defines banks in a standard format (ie, 0 for first bank, 1 for second, etc). Carts which will handle their own bankswitching completely or non-bankswitched carts can ignore this method. + + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - virtual bool bank(uInt16) { return false; } + virtual bool bank(uInt16 bank, uInt16 segment = 0) { return false; } /** Get the current bank for the provided address. Carts which have only @@ -177,7 +205,7 @@ class Cartridge : public Device virtual uInt16 getBank(uInt16 address = 0) const { return 0; } /** - Query the number of 'banks' supported by the cartridge. Note that + Query the number of ROM 'banks' supported by the cartridge. Note that this information is cart-specific, where each cart basically defines what a 'bank' is. @@ -186,10 +214,25 @@ class Cartridge : public Device cases where ROMs have 2K blocks in some preset area, the bankCount is the number of such blocks. Finally, in some esoteric schemes, the number of ways that the addressing can change (multiple ROM and - RAM slices at multiple access points) is so complicated that the + RAM segments at multiple access points) is so complicated that the cart will report having only one 'virtual' bank. */ - virtual uInt16 bankCount() const { return 1; } + virtual uInt16 romBankCount() const { return 1; } + + /** + Query the number of RAM 'banks' supported by the cartridge. Note that + this information is cart-specific, where each cart basically defines + what a 'bank' is. + */ + virtual uInt16 ramBankCount() const { return 0; } + + /** + Get the size of a bank. + + @param bank The bank to get the size for + @return The bank's size + */ + virtual uInt16 bankSize(uInt16 bank = 0) const; /** Patch the cartridge ROM. @@ -204,9 +247,9 @@ class Cartridge : public Device Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - virtual const uInt8* getImage(size_t& size) const = 0; + virtual const ByteBuffer& getImage(size_t& size) const = 0; /** Get a descriptor for the cart name. @@ -287,7 +330,7 @@ class Cartridge : public Device @param size The size of the code-access array to create */ - void createCodeAccessBase(size_t size); + void createRomAccessArrays(size_t size); /** Fill the given RAM array with (possibly random) data. @@ -335,12 +378,20 @@ class Cartridge : public Device bool myBankChanged{true}; // The array containing information about every byte of ROM indicating - // whether it is used as code. - ByteBuffer myCodeAccessBase; + // whether it is used as code, data, graphics etc. + std::unique_ptr myRomAccessBase; + + // The array containing information about every byte of ROM indicating + // how often it is accessed. + std::unique_ptr myRomAccessCounter; + // Contains address of illegal RAM write access or 0 uInt16 myRamWriteAccess{0}; + // Total size of ROM access area (might include RAM too) + uInt32 myAccessSize; + private: // The startup bank to use (where to look for the reset vector address) uInt16 myStartBank{0}; @@ -361,8 +412,10 @@ class Cartridge : public Device // Used when we want the 'Cartridge.StartBank' ROM property StartBankFromPropsFunc myStartBankFromPropsFunc; - // Contains - ShortArray myRAMAccesses; + // Used to answer whether an access in the last instruction cycle + // generated an illegal read RAM access. Contains address of illegal + // access. + ShortArray myRamReadAccesses; // Following constructors and assignment operators not supported Cartridge() = delete; diff --git a/src/emucore/Cart0840.cxx b/src/emucore/Cart0840.cxx index 22e6a1cff..c560b0a1b 100644 --- a/src/emucore/Cart0840.cxx +++ b/src/emucore/Cart0840.cxx @@ -20,26 +20,16 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge0840::Cartridge0840(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge0840::reset() -{ - // Upon reset we switch to the startup bank - initializeStartBank(0); - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge0840::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // Get the page accessing methods for the hot spots since they overlap // areas within the TIA we'll need to forward requests to the TIA @@ -56,32 +46,34 @@ void Cartridge0840::install(System& system) System::PageAccess access(this, System::PageAccessType::READ); for(uInt16 addr = 0x0800; addr < 0x0FFF; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Install pages for bank 0 - bank(startBank()); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Cartridge0840::checkSwitchBank(uInt16 address, uInt8) +{ + // Switch banks if necessary + switch(address & 0x1840) + { + case 0x0800: + // Set the current bank to the lower 4k bank + bank(0); + return true; + + case 0x0840: + // Set the current bank to the upper 4k bank + bank(1); + return true; + + default: + break; + } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 Cartridge0840::peek(uInt16 address) { - address &= 0x1840; - - // Switch banks if necessary - switch(address) - { - case 0x0800: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0840: - // Set the current bank to the upper 4k bank - bank(1); - break; - - default: - break; - } + checkSwitchBank(address); // Because of the way we've set up accessing above, we can only // get here when the addresses are from 0x800 - 0xFFF @@ -92,24 +84,7 @@ uInt8 Cartridge0840::peek(uInt16 address) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Cartridge0840::poke(uInt16 address, uInt8 value) { - address &= 0x1840; - - // Switch banks if necessary - switch(address) - { - case 0x0800: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0840: - // Set the current bank to the upper 4k bank - bank(1); - break; - - default: - break; - } + checkSwitchBank(address); // Because of the way accessing is set up, we will may get here by // doing a write to 0x800 - 0xFFF or cart; we ignore the cart write @@ -121,85 +96,3 @@ bool Cartridge0840::poke(uInt16 address, uInt8 value) return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge0840::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge0840::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge0840::bankCount() const -{ - return 2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge0840::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0fff)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge0840::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge0840::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: Cartridge0840::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge0840::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: Cartridge0840::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset); - - return true; -} diff --git a/src/emucore/Cart0840.hxx b/src/emucore/Cart0840.hxx index 87d372f59..0d120aad4 100644 --- a/src/emucore/Cart0840.hxx +++ b/src/emucore/Cart0840.hxx @@ -19,7 +19,7 @@ #define CARTRIDGE0840_HXX #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #include "System.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart0840Widget.hxx" @@ -30,9 +30,9 @@ are two 4K banks, which are switched by accessing $0800 (bank 0) and $0840 (bank 1). - @author Fred X. Quimby + @author Fred X. Quimby, Thomas Jentzsch */ -class Cartridge0840 : public Cartridge +class Cartridge0840 : public CartridgeEnhanced { friend class Cartridge0840Widget; @@ -44,17 +44,13 @@ class Cartridge0840 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ Cartridge0840(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~Cartridge0840() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -63,58 +59,6 @@ class Cartridge0840 : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -152,12 +96,11 @@ class Cartridge0840 : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // The 8K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 hotspot() const override { return 0x0840; } + private: // Previous Device's page access std::array myHotSpotPageAccess; diff --git a/src/emucore/Cart2K.cxx b/src/emucore/Cart2K.cxx index bbad871af..d204d93ed 100644 --- a/src/emucore/Cart2K.cxx +++ b/src/emucore/Cart2K.cxx @@ -20,89 +20,32 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { + // When creating a 2K cart, we always initially create a buffer of size 2_KB + // Sometimes we only use a portion of that buffer; we check for that now + // Size can be a maximum of 2K - if(size > 2_KB) size = 2_KB; + size = std::min(size, bsSize); // Set image size to closest power-of-two for the given size - mySize = 1; + mySize = 1; myBankShift = 0; while(mySize < size) + { mySize <<= 1; - - // Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam - size_t bufSize = std::max(mySize, System::PAGE_SIZE); - myImage = make_unique(bufSize); - std::fill_n(myImage.get(), bufSize, 0x02); + myBankShift++; + } // Handle cases where ROM is smaller than the page size // It's much easier to do it this way rather than changing the page size - if(mySize >= System::PAGE_SIZE) - { - // Directly copy the ROM image into the buffer - std::copy_n(image.get(), mySize, myImage.get()); - } - else + if(mySize < System::PAGE_SIZE) { // Manually 'mirror' the ROM image into the buffer for(size_t i = 0; i < System::PAGE_SIZE; i += mySize) std::copy_n(image.get(), mySize, myImage.get() + i); mySize = System::PAGE_SIZE; - } - - createCodeAccessBase(mySize); - - // Set mask for accessing the image buffer - // This is guaranteed to work, as mySize is a power of two - myMask = static_cast(mySize) - 1; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge2K::reset() -{ - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge2K::install(System& system) -{ - mySystem = &system; - - // Map ROM image into the system - // Note that we don't need our own peek/poke methods, since the mapping - // takes care of the entire address space - System::PageAccess access(this, System::PageAccessType::READ); - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[addr & myMask]; - access.codeAccessBase = &myCodeAccessBase[addr & myMask]; - mySystem->setPageAccess(addr, access); + myBankShift = System::PAGE_SHIFT; } } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge2K::patch(uInt16 address, uInt8 value) -{ - myImage[address & myMask] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge2K::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge2K::save(Serializer&) const -{ - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge2K::load(Serializer&) -{ - return true; -} diff --git a/src/emucore/Cart2K.hxx b/src/emucore/Cart2K.hxx index 22f08fbf5..878df4714 100644 --- a/src/emucore/Cart2K.hxx +++ b/src/emucore/Cart2K.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart2KWidget.hxx" #endif @@ -33,9 +33,9 @@ class System; data repeats in intervals based on the size of the ROM (which will always be a power of 2). - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class Cartridge2K : public Cartridge +class Cartridge2K : public CartridgeEnhanced { friend class Cartridge2KWidget; @@ -47,58 +47,13 @@ class Cartridge2K : public Cartridge @param size The size of the ROM image (<= 2048 bytes) @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ Cartridge2K(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 2_KB); virtual ~Cartridge2K() = default; public: - /** - Reset cartridge to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -118,22 +73,8 @@ class Cartridge2K : public Cartridge } #endif - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override { return myImage[address & myMask]; } - private: - // Pointer to a dynamically allocated ROM image of the cartridge - ByteBuffer myImage; - - // Size of the ROM image - size_t mySize{0}; - - // Mask to use for mirroring - uInt16 myMask{0}; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override { return false; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Cart3E.cxx b/src/emucore/Cart3E.cxx index 7844fc7e3..e3d049eea 100644 --- a/src/emucore/Cart3E.cxx +++ b/src/emucore/Cart3E.cxx @@ -21,259 +21,70 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge3E::Cartridge3E(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, + bsSize == 0 ? BSPF::nextMultipleOf(size, 2_KB) : bsSize) { - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize + myRAM.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3E::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); - - // We'll map the startup bank into the first segment upon reset - bank(startBank()); + myBankShift = BANK_SHIFT; + myRamSize = RAM_SIZE; + myRamBankCount = RAM_BANKS; + myRamWpHigh = RAM_HIGH_WP; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3E::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); - System::PageAccess access(this, System::PageAccessType::READWRITE); + System::PageAccess access(this, System::PageAccessType::WRITE); // The hotspots ($3E and $3F) are in TIA address space, so we claim it here for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Setup the second segment to always point to the last ROM slice - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)]; - access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (addr & 0x07FF)]; - mySystem->setPageAccess(addr, access); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool Cartridge3E::checkSwitchBank(uInt16 address, uInt8 value) +{ + // Switch banks if necessary + if(address == 0x003F) { + // Switch ROM bank into segment 0 + bank(value); + return true; } - - // Install pages for the startup bank into the first segment - bank(startBank()); + else if(address == 0x003E) + { + // Switch RAM bank into segment 0 + bank(value + romBankCount()); + return true; + } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 Cartridge3E::peek(uInt16 address) { uInt16 peekAddress = address; - address &= 0x0FFF; + address &= ROM_MASK; - if(address < 0x0800) - { - if(myCurrentBank < 256) - return myImage[(address & 0x07FF) + (myCurrentBank << 11)]; - else - { - if(address < 0x0400) - return myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)]; - else - { - // Reading from the write port triggers an unwanted write - return peekRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)], peekAddress); - } - } - } - else - { - return myImage[(address & 0x07FF) + mySize - 2048]; - } + if(address < 0x0040) // TIA access + return mySystem->tia().peek(address); + + return CartridgeEnhanced::peek(peekAddress); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Cartridge3E::poke(uInt16 address, uInt8 value) { uInt16 pokeAddress = address; - address &= 0x0FFF; + address &= ROM_MASK; - // Switch banks if necessary. Armin (Kroko) says there are no mirrored - // hotspots. - if(address < 0x0040) + if(address < 0x0040) // TIA access { - if(address == 0x003F) - bank(value); - else if(address == 0x003E) - bank(value + 256); - + checkSwitchBank(address, value); return mySystem->tia().poke(address, value); } - else - { - if(address & 0x0400) - { - pokeRAM(myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)], pokeAddress, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - pokeRAM(dummy, pokeAddress, value); - myRamWriteAccess = pokeAddress; - return false; - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3E::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - if(bank < 256) - { - // Make sure the bank they're asking for is reasonable - if((uInt32(bank) << 11) < mySize) - { - myCurrentBank = bank; - } - else - { - // Oops, the bank they're asking for isn't valid so let's wrap it - // around to a valid bank number - myCurrentBank = bank % (mySize >> 11); - } - - uInt32 offset = myCurrentBank << 11; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x07FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)]; - mySystem->setPageAccess(addr, access); - } - } - else - { - bank -= 256; - bank %= 32; - myCurrentBank = bank + 256; - - uInt32 offset = bank << 10; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map read-port RAM image into the system - for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[offset + (addr & 0x03FF)]; - access.codeAccessBase = &myCodeAccessBase[mySize + offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - - access.directPeekBase = nullptr; - access.type = System::PageAccessType::WRITE; - - // Map write-port RAM image into the system - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[mySize + offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3E::getBank(uInt16 address) const -{ - if (address & 0x800) - return 255; // 256 - 1 // 2K slices, fixed bank - else - return myCurrentBank; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3E::bankCount() const -{ - // Because the RAM banks always start at 256 and above, we require the - // number of ROM banks to be 256 - // If the RAM banks were simply appended to the number of actual - // ROM banks, bank numbers would be ambiguous (ie, would bank 128 be - // the last bank of ROM, or one of the banks of RAM?) - return 256 + 32; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3E::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0800) - { - if(myCurrentBank < 256) - myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value; - else - myRAM[(address & 0x03FF) + ((myCurrentBank - 256) << 10)] = value; - } - else - myImage[(address & 0x07FF) + mySize - 2048] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge3E::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3E::save(Serializer& out) const -{ - try - { - out.putShort(myCurrentBank); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: Cartridge3E::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3E::load(Serializer& in) -{ - try - { - myCurrentBank = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: Cartridge3E::load" << endl; - return false; - } - - // Now, go to the current bank - bank(myCurrentBank); - - return true; + return CartridgeEnhanced::poke(pokeAddress, value); } diff --git a/src/emucore/Cart3E.hxx b/src/emucore/Cart3E.hxx index 554560fd5..60e50613a 100644 --- a/src/emucore/Cart3E.hxx +++ b/src/emucore/Cart3E.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart3EWidget.hxx" #endif @@ -47,10 +47,8 @@ class System; by storing its value into $3F. To map RAM in the first 2K segment instead, store the RAM bank number into $3E. - This implementation of 3E bankswitching numbers the ROM banks 0 to - 255, and the RAM banks 256 to 287. This is done because the public - bankswitching interface requires us to use one bank number, not one - bank number plus the knowledge of whether it's RAM or ROM. + This implementation of 3E bankswitching numbers the RAM banks (up to 32) + after the ROM banks (up to 256). All 32K of potential RAM is available to a game using this class, even though real cartridges might not have the full 32K: We have no way to @@ -58,31 +56,29 @@ class System; may add a stella.pro property for this), but for now it shouldn't cause any problems. (Famous last words...) - @author B. Watson + @author B. Watson, Thomas Jentzsch */ -class Cartridge3E : public Cartridge +class Cartridge3E : public CartridgeEnhanced { friend class Cartridge3EWidget; public: /** - Create a new cartridge using the specified image and size + Create a new cartridge using the specified image and size. @param image Pointer to the ROM image @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ Cartridge3E(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~Cartridge3E() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; /** Install cartridge in the specified system. Invoked by the system @@ -92,58 +88,6 @@ class Cartridge3E : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -181,17 +125,20 @@ class Cartridge3E : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // Pointer to a dynamically allocated ROM image of the cartridge - ByteBuffer myImage; + bool checkSwitchBank(uInt16 address, uInt8 value) override; - // RAM contents. For now every ROM gets all 32K of potential RAM - std::array myRAM; + protected: + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 11; // = 2K = 0x0800 - // Size of the ROM image - size_t mySize{0}; + // The number of RAM banks + static constexpr uInt16 RAM_BANKS = 32; - // Indicates which bank is currently active for the first segment - uInt16 myCurrentBank{0}; + // RAM size + static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 32K = 0x8000; + + // Write port for extra RAM is at high address + static constexpr bool RAM_HIGH_WP = true; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Cart3EPlus.cxx b/src/emucore/Cart3EPlus.cxx index 23f833976..2233b0d71 100644 --- a/src/emucore/Cart3EPlus.cxx +++ b/src/emucore/Cart3EPlus.cxx @@ -21,328 +21,66 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge3EPlus::Cartridge3EPlus(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : Cartridge3E(image, size, md5, settings, + bsSize == 0 ? BSPF::nextMultipleOf(size, 1_KB) : bsSize) { - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize + myRAM.size()); + myBankShift = BANK_SHIFT; + myRamSize = RAM_SIZE; + myRamBankCount = RAM_BANKS; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3EPlus::reset() { - initializeRAM(myRAM.data(), myRAM.size()); + CartridgeEnhanced::reset(); - // Remember startup bank (0 per spec, rather than last per 3E scheme). - // Set this to go to 3rd 1K Bank. - initializeStartBank(0); - - // Initialise bank values for all ROM/RAM access - // This is used to reverse-lookup from address to bank location - for(auto& b: bankInUse) - b = BANK_UNDEFINED; // bank is undefined and inaccessible! - - initializeBankState(); - - // We'll map the startup banks 0 and 3 from the image into the third 1K bank upon reset - bankROM((0 << BANK_BITS) | 0); - bankROM((3 << BANK_BITS) | 0); + bank(mySystem->randGenerator().next() % romBankCount(), 0); + bank(mySystem->randGenerator().next() % romBankCount(), 1); + bank(mySystem->randGenerator().next() % romBankCount(), 2); + bank(startBank(), 3); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlus::install(System& system) +bool Cartridge3EPlus::checkSwitchBank(uInt16 address, uInt8 value) { - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READWRITE); - - // The hotspots are in TIA address space, so we claim it here - for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - - // Initialise bank values for all ROM/RAM access - // This is used to reverse-lookup from address to bank location - for(auto& b: bankInUse) - b = BANK_UNDEFINED; // bank is undefined and inaccessible! - - initializeBankState(); - - // Setup the last segment (of 4, each 1K) to point to the first ROM slice - // Actually we DO NOT want "always". It's just on bootup, and can be out switched later - bankROM((0 << BANK_BITS) | 0); - bankROM((3 << BANK_BITS) | 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3EPlus::getBank(uInt16 address) const -{ - return bankInUse[(address & 0xFFF) >> 10]; // 1K slices -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3EPlus::bankCount() const -{ - return uInt16(mySize >> 10); // 1K slices + // Switch banks if necessary + if(address == 0x003F) { + // Switch ROM bank into segment 0 + bank(value & 0b111111, value >> 6); + return true; + } + else if(address == 0x003E) + { + // Switch RAM bank into segment 0 + bank((value & 0b111111) + romBankCount(), value >> 6); + return true; + } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 Cartridge3EPlus::peek(uInt16 address) { uInt16 peekAddress = address; - address &= 0x0FFF; // restrict to 4K address range + address &= ROM_MASK; - uInt8 value = 0; - uInt32 bank = (address >> (ROM_BANK_TO_POWER - 1)) & 7; // convert to 512 byte bank index (0-7) - uInt16 imageBank = bankInUse[bank]; // the ROM/RAM bank that's here + if(address < 0x0040) // TIA peek + return mySystem->tia().peek(address); - if(imageBank == BANK_UNDEFINED) // an uninitialised bank? - { - // accessing invalid bank, so return should be... random? - value = mySystem->randGenerator().next(); - - } - else if(imageBank & BITMASK_ROMRAM) // a RAM bank - { - Int32 ramBank = imageBank & BIT_BANK_MASK; // discard irrelevant bits - Int32 offset = ramBank << RAM_BANK_TO_POWER; // base bank address in RAM - offset += (address & BITMASK_RAM_BANK); // + byte offset in RAM bank - - return peekRAM(myRAM[offset], peekAddress); - } - - return value; + return CartridgeEnhanced::peek(peekAddress); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Cartridge3EPlus::poke(uInt16 address, uInt8 value) { - bool changed = false; + if(CartridgeEnhanced::poke(address, value)) + return true; - // Check for write to the bank switch address. RAM/ROM and bank # are encoded in 'value' - // There are NO mirrored hotspots. - - if(address == BANK_SWITCH_HOTSPOT_RAM) - changed = bankRAM(value); - else if(address == BANK_SWITCH_HOTSPOT_ROM) - changed = bankROM(value); - - if(!(address & 0x1000)) - { + if(address < 0x0040) // TIA poke // Handle TIA space that we claimed above - changed = changed || mySystem->tia().poke(address, value); - } - else - { - uInt32 bankNumber = (address >> RAM_BANK_TO_POWER) & 7; // now 512 byte bank # (ie: 0-7) - Int16 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference + return mySystem->tia().poke(address, value); - if(whichBankIsThere & BITMASK_ROMRAM) - { - uInt32 byteOffset = address & BITMASK_RAM_BANK; - uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset; - pokeRAM(myRAM[baseAddress], address, value); - changed = true; - } - } - - return changed; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3EPlus::bankRAM(uInt8 bank) -{ - if(bankLocked()) // debugger can lock RAM - return false; - -//cerr << "bankRAM " << int(bank) << endl; - - // Each RAM bank uses two slots, separated by 0x200 in memory -- one read, one write. - bankRAMSlot(bank | BITMASK_ROMRAM | 0); - bankRAMSlot(bank | BITMASK_ROMRAM | BITMASK_LOWERUPPER); - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlus::bankRAMSlot(uInt16 bank) -{ - uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) to 512 byte block - uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range - bool upper = bank & BITMASK_LOWERUPPER; // is this the read or write port - - uInt32 startCurrentBank = currentBank << RAM_BANK_TO_POWER; // Effectively * 512 bytes -//cerr << "raw bank=" << std::dec << currentBank << endl -// << "startCurrentBank=$" << std::hex << startCurrentBank << endl; - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - if(upper) // We're mapping the write port - { - bankInUse[bankNumber * 2 + 1] = Int16(bank); - access.type = System::PageAccessType::WRITE; - } - else // We're mapping the read port - { - bankInUse[bankNumber * 2] = Int16(bank); - access.type = System::PageAccessType::READ; - } - - uInt16 start = 0x1000 + (bankNumber << (RAM_BANK_TO_POWER+1)) + (upper ? RAM_WRITE_OFFSET : 0); - uInt16 end = start + RAM_BANK_SIZE - 1; - -//cerr << "bank RAM: " << bankNumber << " -> " << (bankNumber * 2 + (upper ? 1 : 0)) << (upper ? " (W)" : " (R)") << endl -// << "start=" << std::hex << start << ", end=" << end << endl << endl; - for(uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - { - if(!upper) - access.directPeekBase = &myRAM[startCurrentBank + (addr & (RAM_BANK_SIZE - 1))]; - - access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3EPlus::bankROM(uInt8 bank) -{ - if(bankLocked()) // debugger can lock ROM - return false; - - // Map ROM bank image into the system into the correct slot - // Memory map is 1K slots at 0x1000, 0x1400, 0x1800, 0x1C00 - // Each ROM uses 2 consecutive 512 byte slots - bankROMSlot(bank | 0); - bankROMSlot(bank | BITMASK_LOWERUPPER); - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlus::bankROMSlot(uInt16 bank) -{ - uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) - uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range - bool upper = bank & BITMASK_LOWERUPPER; // is this the lower or upper 512b - - bankInUse[bankNumber * 2 + (upper ? 1 : 0)] = Int16(bank); // Record which bank switched in (as ROM) - - uInt32 startCurrentBank = currentBank << ROM_BANK_TO_POWER; // Effectively *1K - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - uInt16 start = 0x1000 + (bankNumber << ROM_BANK_TO_POWER) + (upper ? ROM_BANK_SIZE / 2 : 0); - uInt16 end = start + ROM_BANK_SIZE / 2 - 1; - - for(uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))]; - access.codeAccessBase = &myCodeAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3EPlus::initializeBankState() -{ - // Switch in each 512b slot - for(uInt32 b = 0; b < 8; ++b) - { - if(bankInUse[b] == BANK_UNDEFINED) - { - // All accesses point to peek/poke above - System::PageAccess access(this, System::PageAccessType::READ); - uInt16 start = 0x1000 + (b << RAM_BANK_TO_POWER); - uInt16 end = start + RAM_BANK_SIZE - 1; - for(uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - } - else if (bankInUse[b] & BITMASK_ROMRAM) - bankRAMSlot(bankInUse[b]); - else - bankROMSlot(bankInUse[b]); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3EPlus::patch(uInt16 address, uInt8 value) -{ -#if 0 - // Patch the cartridge ROM (for debugger) - - myBankChanged = true; - - uInt32 bankNumber = (address >> RAM_BANK_TO_POWER) & 7; // now 512 byte bank # (ie: 0-7) - uInt16 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference - - if (whichBankIsThere == BANK_UNDEFINED) { - - // We're trying to access undefined memory (no bank here yet). Fail! - myBankChanged = false; - - } else if (whichBankIsThere & BITMASK_ROMRAM) { // patching RAM (512 byte banks) - - uInt32 byteOffset = address & BITMASK_RAM_BANK; - uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset; - myRAM[baseAddress] = value; // write to RAM - - // TODO: Stephen -- should we set 'myBankChanged' true when there's a RAM write? - - } else { // patching ROM (1K banks) - - uInt32 byteOffset = address & BITMASK_ROM_BANK; - uInt32 baseAddress = (whichBankIsThere << ROM_BANK_TO_POWER) + byteOffset; - myImage[baseAddress] = value; // write to the image - } - - return myBankChanged; -#else return false; -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge3EPlus::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3EPlus::save(Serializer& out) const -{ - try - { - out.putShortArray(bankInUse.data(), bankInUse.size()); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch (...) - { - cerr << "ERROR: Cartridge3EPlus::save" << endl; - return false; - } - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3EPlus::load(Serializer& in) -{ - try - { - in.getShortArray(bankInUse.data(), bankInUse.size()); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch (...) - { - cerr << "ERROR: Cartridge3EPlus::load" << endl; - return false; - } - - initializeBankState(); - return true; } diff --git a/src/emucore/Cart3EPlus.hxx b/src/emucore/Cart3EPlus.hxx index 76919b9ae..2ba54d313 100644 --- a/src/emucore/Cart3EPlus.hxx +++ b/src/emucore/Cart3EPlus.hxx @@ -21,27 +21,68 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "Cart3E.hxx" #ifdef DEBUGGER_SUPPORT -class Cartridge3EPlusWidget; #include "Cart3EPlusWidget.hxx" #endif /** - Cartridge class from Thomas Jentzsch, mostly based on the 'DASH' scheme - with the following changes: + Cartridge class for new tiling engine "Boulder Dash" format games with RAM. + Kind of a combination of 3F and 3E, with better switchability. + B.Watson's Cart3E was used as a template for building this implementation. - RAM areas: - - read $x000, write $x200 - - read $x400, write $x600 - - read $x800, write $xa00 - - read $xc00, write $xe00 + The destination bank (0-3) is held in the top bits of the value written to + $3E (for RAM switching) or $3F (for ROM switching). The low 6 bits give + the actual bank number (0-63) corresponding to 512 byte blocks for RAM and + 1024 byte blocks for ROM. The maximum size is therefore 32K RAM and 64K ROM. - @author Thomas Jentzsch and Stephen Anthony + D7D6 indicate the bank number (0-3) + D5D4D3D2D1D0 indicate the actual # (0-63) from the image/ram + + ROM: + + Note: In descriptions $F000 is equivalent to $1000 -- that is, we only deal + with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000 + So, mask with top bits clear :) when reading this document. + + In this scheme, the 4K address space is broken into four 1K ROM/512b RAM segments + living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.), + + The last 1K ROM ($FC00-$FFFF) segment in the 6502 address space (ie: $1C00-$1FFF) + is initialised to point to the FIRST 1K of the ROM image, so the reset vectors + must be placed at the end of the first 1K in the ROM image. + + Note: This is DIFFERENT to 3E which switches in the UPPER bank and this bank is + fixed. This allows variable sized ROM without having to detect size. + + ROM switching (write of block+bank number to $3F) D7D6 upper 2 bits of bank # + indicates the destination segment (0-3, corresponding to $F000, $F400, $F800, + $FC00), and lower 6 bits indicate the 1K bank to switch in. Can handle 64 + x 1K ROM banks (64K total). + + D7 D6 D5D4D3D2D1D0 + 0 0 x x x x x x switch a 1K ROM bank xxxxxx to $F000 + 0 1 switch a 1K ROM bank xxxxxx to $F400 + 1 0 switch a 1K ROM bank xxxxxx to $F800 + 1 1 switch a 1K ROM bank xxxxxx to $FC00 + + RAM switching (write of segment+bank number to $3E) with D7D6 upper 2 bits of + bank # indicates the destination RAM segment (0-3, corresponding to $F000, + $F400, $F800, $FC00). + + Can handle 64 x 512 byte RAM banks (32K total) + + D7 D6 D5D4D3D2D1D0 + 0 0 x x x x x x switch a 512 byte RAM bank xxxxxx to $F000 with write @ $F200 + 0 1 switch a 512 byte RAM bank xxxxxx to $F400 with write @ $F600 + 1 0 switch a 512 byte RAM bank xxxxxx to $F800 with write @ $FA00 + 1 1 switch a 512 byte RAM bank xxxxxx to $FC00 with write @ $FE00 + + @author Thomas Jentzsch and Stephen Anthony */ -class Cartridge3EPlus: public Cartridge +class Cartridge3EPlus: public Cartridge3E { friend class Cartridge3EPlusWidget; @@ -53,68 +94,17 @@ class Cartridge3EPlus: public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ Cartridge3EPlus(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~Cartridge3EPlus() = default; public: /** Reset device to its power-on state */ void reset() override; - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -152,47 +142,17 @@ class Cartridge3EPlus: public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - bool bankRAM(uInt8 bank); // switch a RAM bank - bool bankROM(uInt8 bank); // switch a ROM bank + bool checkSwitchBank(uInt16 address, uInt8 value) override; - void bankRAMSlot(uInt16 bank); // switch in a 512b RAM slot (lower or upper 1/2 bank) - void bankROMSlot(uInt16 bank); // switch in a 512b RAM slot (read or write port) + private: + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400 - void initializeBankState(); // set all banks according to current bankInUse state + // The size of extra RAM in ROM address space + static constexpr uInt16 RAM_BANKS = 64; - // We have an array that indicates for each of the 8 512 byte areas of the address space, which ROM/RAM - // bank is used in that area. ROM switches 1K so occupies 2 successive entries for each switch. RAM occupies - // two as well, one 512 byte for read and one for write. The RAM locations are +0x800 apart, and the ROM - // are consecutive. This allows us to determine on a read/write exactly where the data is. - - static constexpr uInt16 BANK_UNDEFINED = 0x8000; // bank is undefined and inaccessible - std::array bankInUse; // bank being used for ROM/RAM (eight 512 byte areas) - - static constexpr uInt16 BANK_SWITCH_HOTSPOT_RAM = 0x3E; // writes to this address cause bankswitching - static constexpr uInt16 BANK_SWITCH_HOTSPOT_ROM = 0x3F; // writes to this address cause bankswitching - - static constexpr uInt8 BANK_BITS = 6; // # bits for bank - static constexpr uInt8 BIT_BANK_MASK = (1 << BANK_BITS) - 1; // mask for those bits - static constexpr uInt16 BITMASK_LOWERUPPER = 0x100; // flags lower or upper section of bank (1==upper) - static constexpr uInt16 BITMASK_ROMRAM = 0x200; // flags ROM or RAM bank switching (1==RAM) - - static constexpr uInt16 MAXIMUM_BANK_COUNT = (1 << BANK_BITS); - static constexpr uInt16 RAM_BANK_TO_POWER = 9; // 2^n = 512 - static constexpr uInt16 RAM_BANK_SIZE = (1 << RAM_BANK_TO_POWER); - static constexpr uInt16 BITMASK_RAM_BANK = (RAM_BANK_SIZE - 1); - static constexpr uInt32 RAM_TOTAL_SIZE = MAXIMUM_BANK_COUNT * RAM_BANK_SIZE; - - static constexpr uInt16 ROM_BANK_TO_POWER = 10; // 2^n = 1024 - static constexpr uInt16 ROM_BANK_SIZE = (1 << ROM_BANK_TO_POWER); - static constexpr uInt16 BITMASK_ROM_BANK = (ROM_BANK_SIZE - 1); - - static constexpr uInt16 ROM_BANK_COUNT = 64; - - static constexpr uInt16 RAM_WRITE_OFFSET = 0x200; - - ByteBuffer myImage; // Pointer to a dynamically allocated ROM image of the cartridge - size_t mySize{0}; // Size of the ROM image - std::array myRAM; + // RAM size + static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 32K = 0x4000; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Cart3EX.cxx b/src/emucore/Cart3EX.cxx new file mode 100644 index 000000000..c71fdd242 --- /dev/null +++ b/src/emucore/Cart3EX.cxx @@ -0,0 +1,28 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Cart3EX.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Cartridge3EX::Cartridge3EX(const ByteBuffer& image, size_t size, + const string& md5, const Settings& settings) + : Cartridge3E(image, size, md5, settings) +{ + // 0xFFFA contains RAM bank count - 1; + myRamBankCount = image[size - 6] + 1; + myRamSize = (myBankSize >> 1) * myRamBankCount; +} diff --git a/src/emucore/Cart3EX.hxx b/src/emucore/Cart3EX.hxx new file mode 100644 index 000000000..c949a0c9c --- /dev/null +++ b/src/emucore/Cart3EX.hxx @@ -0,0 +1,69 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGE3EX_HXX +#define CARTRIDGE3EX_HXX + +class System; +class Settings; + +#include "bspf.hxx" +#include "Cart3E.hxx" + +/** + This is an enhanced version of 3E which supports up to 256KB RAM. + + @author Thomas Jentzsch +*/ + +class Cartridge3EX : public Cartridge3E +{ + public: + /** + Create a new cartridge using the specified image and size + + @param image Pointer to the ROM image + @param size The size of the ROM image + @param md5 The md5sum of the ROM image + @param settings A reference to the various settings (read-only) + */ + Cartridge3EX(const ByteBuffer& image, size_t size, const string& md5, + const Settings& settings); + virtual ~Cartridge3EX() = default; + + public: + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + string name() const override { return "Cartridge3EX"; } + + private: + // RAM size + static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000; + + private: + // Following constructors and assignment operators not supported + Cartridge3EX() = delete; + Cartridge3EX(const Cartridge3EX&) = delete; + Cartridge3EX(Cartridge3EX&&) = delete; + Cartridge3EX& operator=(const Cartridge3EX&) = delete; + Cartridge3EX& operator=(Cartridge3EX&&) = delete; +}; + +#endif diff --git a/src/emucore/Cart3F.cxx b/src/emucore/Cart3F.cxx index 8b59d77ba..a44c28a5e 100644 --- a/src/emucore/Cart3F.cxx +++ b/src/emucore/Cart3F.cxx @@ -21,174 +21,35 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge3F::Cartridge3F(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, + bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize) { - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge3F::reset() -{ - initializeStartBank(bankCount() - 1); - - bank(startBank()); + myBankShift = BANK_SHIFT; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge3F::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); System::PageAccess access(this, System::PageAccessType::READWRITE); // The hotspot ($3F) is in TIA address space, so we claim it here for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); - - // Setup the second segment to always point to the last ROM slice - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[(mySize - 2048) + (addr & 0x07FF)]; - access.codeAccessBase = &myCodeAccessBase[(mySize - 2048) + (addr & 0x07FF)]; - mySystem->setPageAccess(addr, access); - } - - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge3F::peek(uInt16 address) +bool Cartridge3F::checkSwitchBank(uInt16 address, uInt8 value) { - address &= 0x0FFF; - - if(address < 0x0800) - return myImage[(address & 0x07FF) + (myCurrentBank << 11)]; - else - return myImage[(address & 0x07FF) + mySize - 2048]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3F::poke(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - // Switch banks if necessary if(address <= 0x003F) - bank(value); - - // Handle TIA space that we claimed above - mySystem->tia().poke(address, value); - + { + // Make sure the bank they're asking for is reasonable + bank(value % romBankCount(), 0); + return true; + } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3F::bank(uInt16 bank) -{ - if(bankLocked()) - return false; - - // Make sure the bank they're asking for is reasonable - if((uInt32(bank) << 11) < mySize) - { - myCurrentBank = bank; - } - else - { - // Oops, the bank they're asking for isn't valid so let's wrap it - // around to a valid bank number - myCurrentBank = bank % (mySize >> 11); - } - - uInt32 offset = myCurrentBank << 11; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x07FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3F::getBank(uInt16 address) const -{ - if (address & 0x800) - return uInt16((mySize >> 11) - 1); // 2K slices, fixed bank - else - return myCurrentBank; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 Cartridge3F::bankCount() const -{ - return uInt16(mySize >> 11); // 2K slices -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3F::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0800) - myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value; - else - myImage[(address & 0x07FF) + mySize - 2048] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge3F::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3F::save(Serializer& out) const -{ - try - { - out.putShort(myCurrentBank); - } - catch(...) - { - cerr << "ERROR: Cartridge3F::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge3F::load(Serializer& in) -{ - try - { - myCurrentBank = in.getShort(); - } - catch(...) - { - cerr << "ERROR: Cartridge3F::load" << endl; - return false; - } - - // Now, go to the current bank - bank(myCurrentBank); - - return true; -} diff --git a/src/emucore/Cart3F.hxx b/src/emucore/Cart3F.hxx index cb75bcd88..f5eeac809 100644 --- a/src/emucore/Cart3F.hxx +++ b/src/emucore/Cart3F.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart3FWidget.hxx" #endif @@ -36,9 +36,9 @@ class System; $00 to $3F will change banks. Although, the Tigervision games only used 8K this bankswitching scheme supports up to 512K. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class Cartridge3F : public Cartridge +class Cartridge3F : public CartridgeEnhanced { friend class Cartridge3FWidget; @@ -50,17 +50,14 @@ class Cartridge3F : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ Cartridge3F(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~Cartridge3F() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -69,57 +66,6 @@ class Cartridge3F : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; /** Get a descriptor for the device name (used in error checking). @@ -140,32 +86,14 @@ class Cartridge3F : public Cartridge } #endif - public: - /** - Get the byte at the specified address + private: + bool checkSwitchBank(uInt16 address, uInt8 value) override; - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + uInt16 hotspot() const override { return 0x003F; } private: - // Pointer to a dynamically allocated ROM image of the cartridge - ByteBuffer myImage; - - // Size of the ROM image - size_t mySize{0}; - - // Indicates which bank is currently active for the first segment - uInt16 myCurrentBank{0}; + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 11; // = 2K = 0x0800 private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Cart4A50.cxx b/src/emucore/Cart4A50.cxx index ead5d9285..6939bc0ef 100644 --- a/src/emucore/Cart4A50.cxx +++ b/src/emucore/Cart4A50.cxx @@ -24,6 +24,7 @@ Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) : Cartridge(settings, md5), + myImage(make_unique(128_KB)), mySize(size) { // Copy the ROM image into my buffer @@ -32,16 +33,16 @@ Cartridge4A50::Cartridge4A50(const ByteBuffer& image, size_t size, else if(size < 128_KB) size = 64_KB; else size = 128_KB; for(uInt32 slice = 0; slice < 128_KB / size; ++slice) - std::copy_n(image.get(), size, myImage.begin() + (slice*size)); + std::copy_n(image.get(), size, myImage.get() + (slice*size)); - // We use System::PageAccess.codeAccessBase, but don't allow its use + // We use System::PageAccess.romAccessBase, but don't allow its use // through a pointer, since the address space of 4A50 carts can change // at the instruction level, and PageAccess is normally defined at an // interval of 64 bytes // // Instead, access will be through the getAccessFlags and setAccessFlags // methods below - createCodeAccessBase(myImage.size() + myRAM.size()); + createRomAccessArrays(128_KB + myRAM.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -181,68 +182,70 @@ bool Cartridge4A50::poke(uInt16 address, uInt8 value) return myBankChanged; } +#ifdef DEBUGGER_SUPPORT // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge4A50::getAccessFlags(uInt16 address) const +Device::AccessFlags Cartridge4A50::getAccessFlags(uInt16 address) const { if((address & 0x1800) == 0x1000) // 2K region from 0x1000 - 0x17ff { if(myIsRomLow) - return myCodeAccessBase[(address & 0x7ff) + mySliceLow]; + return myRomAccessBase[(address & 0x7ff) + mySliceLow]; else - return myCodeAccessBase[131072 + (address & 0x7ff) + mySliceLow]; + return myRomAccessBase[131072 + (address & 0x7ff) + mySliceLow]; } else if(((address & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff ((address & 0x1fff) <= 0x1dff)) { if(myIsRomMiddle) - return myCodeAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000]; + return myRomAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000]; else - return myCodeAccessBase[131072 + (address & 0x7ff) + mySliceMiddle]; + return myRomAccessBase[131072 + (address & 0x7ff) + mySliceMiddle]; } else if((address & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff { if(myIsRomHigh) - return myCodeAccessBase[(address & 0xff) + mySliceHigh + 0x10000]; + return myRomAccessBase[(address & 0xff) + mySliceHigh + 0x10000]; else - return myCodeAccessBase[131072 + (address & 0xff) + mySliceHigh]; + return myRomAccessBase[131072 + (address & 0xff) + mySliceHigh]; } else if((address & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff { - return myCodeAccessBase[(address & 0xff) + 0x1ff00]; + return myRomAccessBase[(address & 0xff) + 0x1ff00]; } return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4A50::setAccessFlags(uInt16 address, uInt8 flags) +void Cartridge4A50::setAccessFlags(uInt16 address, Device::AccessFlags flags) { if((address & 0x1800) == 0x1000) // 2K region from 0x1000 - 0x17ff { if(myIsRomLow) - myCodeAccessBase[(address & 0x7ff) + mySliceLow] |= flags; + myRomAccessBase[(address & 0x7ff) + mySliceLow] |= flags; else - myCodeAccessBase[131072 + (address & 0x7ff) + mySliceLow] |= flags; + myRomAccessBase[131072 + (address & 0x7ff) + mySliceLow] |= flags; } else if(((address & 0x1fff) >= 0x1800) && // 1.5K region from 0x1800 - 0x1dff ((address & 0x1fff) <= 0x1dff)) { if(myIsRomMiddle) - myCodeAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000] |= flags; + myRomAccessBase[(address & 0x7ff) + mySliceMiddle + 0x10000] |= flags; else - myCodeAccessBase[131072 + (address & 0x7ff) + mySliceMiddle] |= flags; + myRomAccessBase[131072 + (address & 0x7ff) + mySliceMiddle] |= flags; } else if((address & 0x1f00) == 0x1e00) // 256B region from 0x1e00 - 0x1eff { if(myIsRomHigh) - myCodeAccessBase[(address & 0xff) + mySliceHigh + 0x10000] |= flags; + myRomAccessBase[(address & 0xff) + mySliceHigh + 0x10000] |= flags; else - myCodeAccessBase[131072 + (address & 0xff) + mySliceHigh] |= flags; + myRomAccessBase[131072 + (address & 0xff) + mySliceHigh] |= flags; } else if((address & 0x1f00) == 0x1f00) // 256B region from 0x1f00 - 0x1fff { - myCodeAccessBase[(address & 0xff) + 0x1ff00] |= flags; + myRomAccessBase[(address & 0xff) + 0x1ff00] |= flags; } } +#endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Cartridge4A50::checkBankSwitch(uInt16 address, uInt8 value) @@ -348,10 +351,10 @@ bool Cartridge4A50::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge4A50::getImage(size_t& size) const +const ByteBuffer& Cartridge4A50::getImage(size_t& size) const { size = mySize; - return myImage.data(); + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Cart4A50.hxx b/src/emucore/Cart4A50.hxx index 863b1a020..8a4fdaa2d 100644 --- a/src/emucore/Cart4A50.hxx +++ b/src/emucore/Cart4A50.hxx @@ -96,9 +96,9 @@ class Cartridge4A50 : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -153,20 +153,21 @@ class Cartridge4A50 : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: + #ifdef DEBUGGER_SUPPORT /** - Query the given address type for the associated disassembly flags. + Query the given address type for the associated access flags. @param address The address to query */ - uInt8 getAccessFlags(uInt16 address) const override; + Device::AccessFlags getAccessFlags(uInt16 address) const override; /** - Change the given address to use the given disassembly flags. + Change the given address to use the given access flags. @param address The address to modify - @param flags A bitfield of DisasmType directives for the given address + @param flags A bitfield of AccessType directives for the given address */ - void setAccessFlags(uInt16 address, uInt8 flags) override; - + void setAccessFlags(uInt16 address, Device::AccessFlags flags) override; + #endif /** Check all possible hotspots */ @@ -219,7 +220,7 @@ class Cartridge4A50 : public Cartridge private: // The 128K ROM image of the cartridge - std::array myImage; + ByteBuffer myImage; // The 32K of RAM on the cartridge std::array myRAM; diff --git a/src/emucore/Cart4K.cxx b/src/emucore/Cart4K.cxx index 8c924f720..830cffd49 100644 --- a/src/emucore/Cart4K.cxx +++ b/src/emucore/Cart4K.cxx @@ -20,47 +20,8 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge4K::Cartridge4K(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4K::reset() -{ - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4K::install(System& system) -{ - mySystem = &system; - - // Map ROM image into the system - // Note that we don't need our own peek/poke methods, since the mapping - // takes care of the entire address space - System::PageAccess access(this, System::PageAccessType::READ); - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[addr & 0x0FFF]; - access.codeAccessBase = &myCodeAccessBase[addr & 0x0FFF]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge4K::patch(uInt16 address, uInt8 value) -{ - myImage[address & 0x0FFF] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge4K::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); } diff --git a/src/emucore/Cart4K.hxx b/src/emucore/Cart4K.hxx index 2b42516f5..cc2bb5aef 100644 --- a/src/emucore/Cart4K.hxx +++ b/src/emucore/Cart4K.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart4KWidget.hxx" #endif @@ -30,9 +30,9 @@ class System; This is the standard Atari 4K cartridge. These cartridges are not bankswitched. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class Cartridge4K : public Cartridge +class Cartridge4K : public CartridgeEnhanced { friend class Cartridge4KWidget; @@ -44,58 +44,13 @@ class Cartridge4K : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ Cartridge4K(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 4_KB); virtual ~Cartridge4K() = default; public: - /** - Reset cartridge to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override { return true; } - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override { return true; } - /** Get a descriptor for the device name (used in error checking). @@ -115,16 +70,8 @@ class Cartridge4K : public Cartridge } #endif - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override { return myImage[address & 0x0FFF]; } - private: - // The 4K ROM image for the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override { return false; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Cart4KSC.cxx b/src/emucore/Cart4KSC.cxx index fa36e7b0f..50ad78e8b 100644 --- a/src/emucore/Cart4KSC.cxx +++ b/src/emucore/Cart4KSC.cxx @@ -20,138 +20,9 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : Cartridge4K(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4KSC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Cartridge4KSC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Map ROM image into the system - for(uInt16 addr = 0x1100; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[addr & 0x0FFF]; - access.codeAccessBase = &myCodeAccessBase[addr & 0x0FFF]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 Cartridge4KSC::peek(uInt16 address) -{ - // The only way we can get to this method is if we attempt to read from - // the write port (0xF000 - 0xF07F, 128 bytes), in which case an - // unwanted write is potentially triggered - return peekRAM(myRAM[address & 0x007F], address); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge4KSC::poke(uInt16 address, uInt8 value) -{ - if (!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], address, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge4KSC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[address & 0xFFF] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* Cartridge4KSC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge4KSC::save(Serializer& out) const -{ - try - { - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: Cartridge4KSC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Cartridge4KSC::load(Serializer& in) -{ - try - { - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: Cartridge4KSC::load" << endl; - return false; - } - - return true; + myRamSize = RAM_SIZE; } diff --git a/src/emucore/Cart4KSC.hxx b/src/emucore/Cart4KSC.hxx index 4d596f47a..a2197e018 100644 --- a/src/emucore/Cart4KSC.hxx +++ b/src/emucore/Cart4KSC.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "Cart4K.hxx" #ifdef DEBUGGER_SUPPORT #include "Cart4KSCWidget.hxx" #endif @@ -29,9 +29,11 @@ class System; /** Cartridge class used for 4K games with 128 bytes of RAM. RAM read port is $1080 - $10FF, write port is $1000 - $107F. + + @author Stephen Anthony, Thomas Jentzsch */ -class Cartridge4KSC : public Cartridge +class Cartridge4KSC : public Cartridge4K { friend class Cartridge4KSCWidget; @@ -43,58 +45,13 @@ class Cartridge4KSC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ Cartridge4KSC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 4_KB); virtual ~Cartridge4KSC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -114,29 +71,9 @@ class Cartridge4KSC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 4K ROM image of the cartridge - std::array myImage; - - // The 128 bytes of RAM - std::array myRAM; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartAR.cxx b/src/emucore/CartAR.cxx index b095d446a..cc58d60be 100644 --- a/src/emucore/CartAR.cxx +++ b/src/emucore/CartAR.cxx @@ -17,6 +17,7 @@ #include "M6502.hxx" #include "System.hxx" +#include "Settings.hxx" #include "CartAR.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -35,13 +36,13 @@ CartridgeAR::CartridgeAR(const ByteBuffer& image, size_t size, std::copy_n(ourDefaultHeader.data(), ourDefaultHeader.size(), myLoadImages.get()+myImage.size()); - // We use System::PageAccess.codeAccessBase, but don't allow its use + // We use System::PageAccess.romAccessBase, but don't allow its use // through a pointer, since the AR scheme doesn't support bankswitching // in the normal sense // // Instead, access will be through the getAccessFlags and setAccessFlags // methods below - createCodeAccessBase(mySize); + createRomAccessArrays(mySize); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -190,19 +191,21 @@ bool CartridgeAR::poke(uInt16 addr, uInt8) return modified; } +#ifdef DEBUGGER_SUPPORT // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeAR::getAccessFlags(uInt16 address) const +Device::AccessFlags CartridgeAR::getAccessFlags(uInt16 address) const { - return myCodeAccessBase[(address & 0x07FF) + + return myRomAccessBase[(address & 0x07FF) + myImageOffset[(address & 0x0800) ? 1 : 0]]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeAR::setAccessFlags(uInt16 address, uInt8 flags) +void CartridgeAR::setAccessFlags(uInt16 address, Device::AccessFlags flags) { - myCodeAccessBase[(address & 0x07FF) + + myRomAccessBase[(address & 0x07FF) + myImageOffset[(address & 0x0800) ? 1 : 0]] |= flags; } +#endif // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeAR::bankConfiguration(uInt8 configuration) @@ -389,7 +392,7 @@ void CartridgeAR::loadIntoRAM(uInt8 load) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeAR::bank(uInt16 bank) +bool CartridgeAR::bank(uInt16 bank, uInt16) { if(!bankLocked()) return bankConfiguration(uInt8(bank)); @@ -404,7 +407,7 @@ uInt16 CartridgeAR::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeAR::bankCount() const +uInt16 CartridgeAR::romBankCount() const { return 32; } @@ -417,10 +420,10 @@ bool CartridgeAR::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeAR::getImage(size_t& size) const +const ByteBuffer& CartridgeAR::getImage(size_t& size) const { size = mySize; - return myLoadImages.get(); + return myLoadImages; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartAR.hxx b/src/emucore/CartAR.hxx index 039d19bb8..0b4369f31 100644 --- a/src/emucore/CartAR.hxx +++ b/src/emucore/CartAR.hxx @@ -73,9 +73,12 @@ class CartridgeAR : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -87,7 +90,7 @@ class CartridgeAR : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -102,9 +105,9 @@ class CartridgeAR : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -159,19 +162,21 @@ class CartridgeAR : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: + #ifdef DEBUGGER_SUPPORT /** - Query the given address type for the associated disassembly flags. + Query the given address type for the associated access flags. @param address The address to query */ - uInt8 getAccessFlags(uInt16 address) const override; + Device::AccessFlags getAccessFlags(uInt16 address) const override; /** - Change the given address to use the given disassembly flags. + Change the given address to use the given access flags. @param address The address to modify - @param flags A bitfield of DisasmType directives for the given address + @param flags A bitfield of AccessType directives for the given address */ - void setAccessFlags(uInt16 address, uInt8 flags) override; + void setAccessFlags(uInt16 address, Device::AccessFlags flags) override; + #endif // Handle a change to the bank configuration bool bankConfiguration(uInt8 configuration); diff --git a/src/emucore/CartBF.cxx b/src/emucore/CartBF.cxx index b1f780699..cd815c518 100644 --- a/src/emucore/CartBF.cxx +++ b/src/emucore/CartBF.cxx @@ -20,146 +20,24 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeBF::CartridgeBF(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBF::reset() -{ - initializeStartBank(1); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBF::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeBF::peek(uInt16 address) +bool CartridgeBF::checkSwitchBank(uInt16 address, uInt8) { // Due to the way addressing is set up, we will only get here if the // address is in the hotspot range ($1F80 - $1FFF) - address &= 0x0FFF; + address &= ROM_MASK; // Switch banks if necessary if((address >= 0x0F80) && (address <= 0x0FBF)) + { bank(address - 0x0F80); - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBF::poke(uInt16 address, uInt8) -{ - // Due to the way addressing is set up, we will only get here if the - // address is in the hotspot range ($1F80 - $1FFF) - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0F80) && (address <= 0x0FBF)) - bank(address - 0x0F80); - + return true; + } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBF::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1F80U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeBF::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeBF::bankCount() const -{ - return 64; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBF::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeBF::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBF::save(Serializer& out) const -{ - try - { - out.putInt(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeBF::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBF::load(Serializer& in) -{ - try - { - myBankOffset = in.getInt(); - } - catch(...) - { - cerr << "ERROR: CartridgeBF::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartBF.hxx b/src/emucore/CartBF.hxx index 158f43a45..5190f73da 100644 --- a/src/emucore/CartBF.hxx +++ b/src/emucore/CartBF.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartBFWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; There are 64 4K banks (total of 256K ROM). Accessing $1F80 - $1FBF switches to each bank. - @author Mike Saarna + @author Mike Saarna, Thomas Jentzsch */ -class CartridgeBF : public Cartridge +class CartridgeBF : public CartridgeEnhanced { friend class CartridgeBFWidget; @@ -45,77 +45,13 @@ class CartridgeBF : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeBF(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 256_KB); virtual ~CartridgeBF() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,29 +71,12 @@ class CartridgeBF : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 256K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1F80; } + + uInt16 getStartBank() const override { return 1; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartBFSC.cxx b/src/emucore/CartBFSC.cxx index 00b5efc32..ac8a105b3 100644 --- a/src/emucore/CartBFSC.cxx +++ b/src/emucore/CartBFSC.cxx @@ -20,198 +20,9 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeBFSC::CartridgeBFSC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeBF(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(15); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeBFSC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeBFSC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0F80) && (address <= 0x0FBF)) - bank(address - 0x0F80); - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBFSC::poke(uInt16 address, uInt8 value) -{ - uInt16 pokeAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0F80) && (address <= 0x0FBF)) - { - bank(address - 0x0F80); - return false; - } - - if (!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], pokeAddress, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, pokeAddress, value); - myRamWriteAccess = pokeAddress; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBFSC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1F80 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1F80U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeBFSC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeBFSC::bankCount() const -{ - return 64; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBFSC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeBFSC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBFSC::save(Serializer& out) const -{ - try - { - out.putInt(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeBFSC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBFSC::load(Serializer& in) -{ - try - { - myBankOffset = in.getInt(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeBFSC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; } diff --git a/src/emucore/CartBFSC.hxx b/src/emucore/CartBFSC.hxx index b4cb72aad..4a660ecc8 100644 --- a/src/emucore/CartBFSC.hxx +++ b/src/emucore/CartBFSC.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartBF.hxx" #ifdef DEBUGGER_SUPPORT #include "CartBFSCWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; Accessing $1F80 - $1FBF switches to each bank. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class CartridgeBFSC : public Cartridge +class CartridgeBFSC : public CartridgeBF { friend class CartridgeBFSCWidget; @@ -45,77 +45,12 @@ class CartridgeBFSC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeBFSC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 256_KB); virtual ~CartridgeBFSC() = default; - public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,32 +70,12 @@ class CartridgeBFSC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + private: + uInt16 getStartBank() const override { return 15; } private: - // The 256K ROM image of the cartridge - std::array myImage; - - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; + // RAM size + static constexpr uInt32 RAM_SIZE = 0x80; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartBUS.cxx b/src/emucore/CartBUS.cxx index 5ae98c756..b6cdf66cf 100644 --- a/src/emucore/CartBUS.cxx +++ b/src/emucore/CartBUS.cxx @@ -43,30 +43,31 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) - : Cartridge(settings, md5) + : Cartridge(settings, md5), + myImage(make_unique(32_KB)) { // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); + std::copy_n(image.get(), std::min(32_KB, size), myImage.get()); // Even though the ROM is 32K, only 28K is accessible to the 6507 - createCodeAccessBase(28_KB); + createRomAccessArrays(28_KB); // Pointer to the program ROM (28K @ 0 byte offset) // which starts after the 2K BUS Driver and 2K C Code - myProgramImage = myImage.data() + 4_KB; + myProgramImage = myImage.get() + 4_KB; // Pointer to BUS driver in RAM - myBusDriverImage = myBUSRAM.data(); + myDriverImage = myRAM.data(); // Pointer to the display RAM - myDisplayImage = myBUSRAM.data() + DSRAM; + myDisplayImage = myRAM.data() + DSRAM; // Create Thumbulator ARM emulator bool devSettings = settings.getBool("dev.settings"); myThumbEmulator = make_unique( - reinterpret_cast(myImage.data()), - reinterpret_cast(myBUSRAM.data()), - static_cast(myImage.size()), + reinterpret_cast(myImage.get()), + reinterpret_cast(myRAM.data()), + static_cast(32_KB), devSettings ? settings.getBool("dev.thumb.trapfatal") : false, Thumbulator::ConfigureFor::BUS, this ); @@ -76,7 +77,7 @@ CartridgeBUS::CartridgeBUS(const ByteBuffer& image, size_t size, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeBUS::reset() { - initializeRAM(myBUSRAM.data() + 2_KB, 6_KB); + initializeRAM(myRAM.data() + 2_KB, 6_KB); // BUS always starts in bank 6 initializeStartBank(6); @@ -95,7 +96,7 @@ void CartridgeBUS::reset() void CartridgeBUS::setInitialState() { // Copy initial BUS driver to Harmony RAM - std::copy_n(myImage.begin(), 2_KB, myBusDriverImage); + std::copy_n(myImage.get(), 2_KB, myDriverImage); myMusicWaveformSize.fill(27); @@ -254,7 +255,7 @@ uInt8 CartridgeBUS::peek(uInt16 address) if (sampleaddress < 0x8000) peekvalue = myImage[sampleaddress]; else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40002000) // check for RAM - peekvalue = myBUSRAM[sampleaddress - 0x40000000]; + peekvalue = myRAM[sampleaddress - 0x40000000]; else peekvalue = 0; @@ -429,7 +430,7 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeBUS::bank(uInt16 bank) +bool CartridgeBUS::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; @@ -442,7 +443,9 @@ bool CartridgeBUS::bank(uInt16 bank) // Map Program ROM image into the system for(uInt16 addr = 0x1040; addr < 0x2000; addr += System::PAGE_SIZE) { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB]; mySystem->setPageAccess(addr, access); } return myBankChanged = true; @@ -455,7 +458,7 @@ uInt16 CartridgeBUS::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeBUS::bankCount() const +uInt16 CartridgeBUS::romBankCount() const { return 7; } @@ -476,10 +479,10 @@ bool CartridgeBUS::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeBUS::getImage(size_t& size) const +const ByteBuffer& CartridgeBUS::getImage(size_t& size) const { - size = myImage.size(); - return myImage.data(); + size = 32_KB; + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -545,7 +548,7 @@ uInt32 CartridgeBUS::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) uInt8 CartridgeBUS::internalRamGetValue(uInt16 addr) const { if(addr < internalRamSize()) - return myBUSRAM[addr]; + return myRAM[addr]; else return 0; } @@ -559,7 +562,7 @@ bool CartridgeBUS::save(Serializer& out) const out.putShort(myBankOffset); // Harmony RAM - out.putByteArray(myBUSRAM.data(), myBUSRAM.size()); + out.putByteArray(myRAM.data(), myRAM.size()); // Addresses for bus override logic out.putShort(myBusOverdriveAddress); @@ -600,7 +603,7 @@ bool CartridgeBUS::load(Serializer& in) myBankOffset = in.getShort(); // Harmony RAM - in.getByteArray(myBUSRAM.data(), myBUSRAM.size()); + in.getByteArray(myRAM.data(), myRAM.size()); // Addresses for bus override logic myBusOverdriveAddress = in.getShort(); @@ -640,40 +643,40 @@ uInt32 CartridgeBUS::getDatastreamPointer(uInt8 index) const { // index &= 0x0f; - return myBUSRAM[DSxPTR + index*4 + 0] + // low byte - (myBUSRAM[DSxPTR + index*4 + 1] << 8) + - (myBUSRAM[DSxPTR + index*4 + 2] << 16) + - (myBUSRAM[DSxPTR + index*4 + 3] << 24) ; // high byte + return myRAM[DSxPTR + index*4 + 0] + // low byte + (myRAM[DSxPTR + index*4 + 1] << 8) + + (myRAM[DSxPTR + index*4 + 2] << 16) + + (myRAM[DSxPTR + index*4 + 3] << 24) ; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeBUS::setDatastreamPointer(uInt8 index, uInt32 value) { // index &= 0x0f; - myBUSRAM[DSxPTR + index*4 + 0] = value & 0xff; // low byte - myBUSRAM[DSxPTR + index*4 + 1] = (value >> 8) & 0xff; - myBUSRAM[DSxPTR + index*4 + 2] = (value >> 16) & 0xff; - myBUSRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte + myRAM[DSxPTR + index*4 + 0] = value & 0xff; // low byte + myRAM[DSxPTR + index*4 + 1] = (value >> 8) & 0xff; + myRAM[DSxPTR + index*4 + 2] = (value >> 16) & 0xff; + myRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 CartridgeBUS::getDatastreamIncrement(uInt8 index) const { // index &= 0x0f; - return myBUSRAM[DSxINC + index*4 + 0] + // low byte - (myBUSRAM[DSxINC + index*4 + 1] << 8) + - (myBUSRAM[DSxINC + index*4 + 2] << 16) + - (myBUSRAM[DSxINC + index*4 + 3] << 24) ; // high byte + return myRAM[DSxINC + index*4 + 0] + // low byte + (myRAM[DSxINC + index*4 + 1] << 8) + + (myRAM[DSxINC + index*4 + 2] << 16) + + (myRAM[DSxINC + index*4 + 3] << 24) ; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 CartridgeBUS::getAddressMap(uInt8 index) const { // index &= 0x0f; - return myBUSRAM[DSMAPS + index*4 + 0] + // low byte - (myBUSRAM[DSMAPS + index*4 + 1] << 8) + - (myBUSRAM[DSMAPS + index*4 + 2] << 16) + - (myBUSRAM[DSMAPS + index*4 + 3] << 24) ; // high byte + return myRAM[DSMAPS + index*4 + 0] + // low byte + (myRAM[DSMAPS + index*4 + 1] << 8) + + (myRAM[DSMAPS + index*4 + 2] << 16) + + (myRAM[DSMAPS + index*4 + 3] << 24) ; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -693,10 +696,10 @@ uInt32 CartridgeBUS::getWaveform(uInt8 index) const uInt32 result; - result = myBUSRAM[WAVEFORM + index*4 + 0] + // low byte - (myBUSRAM[WAVEFORM + index*4 + 1] << 8) + - (myBUSRAM[WAVEFORM + index*4 + 2] << 16) + - (myBUSRAM[WAVEFORM + index*4 + 3] << 24); // high byte + result = myRAM[WAVEFORM + index*4 + 0] + // low byte + (myRAM[WAVEFORM + index*4 + 1] << 8) + + (myRAM[WAVEFORM + index*4 + 2] << 16) + + (myRAM[WAVEFORM + index*4 + 3] << 24); // high byte result -= 0x40000800; @@ -711,10 +714,10 @@ uInt32 CartridgeBUS::getSample() { uInt32 result; - result = myBUSRAM[WAVEFORM + 0] + // low byte - (myBUSRAM[WAVEFORM + 1] << 8) + - (myBUSRAM[WAVEFORM + 2] << 16) + - (myBUSRAM[WAVEFORM + 3] << 24); // high byte + result = myRAM[WAVEFORM + 0] + // low byte + (myRAM[WAVEFORM + 1] << 8) + + (myRAM[WAVEFORM + 2] << 16) + + (myRAM[WAVEFORM + 3] << 24); // high byte return result; } @@ -729,10 +732,10 @@ uInt32 CartridgeBUS::getWaveformSize(uInt8 index) const void CartridgeBUS::setAddressMap(uInt8 index, uInt32 value) { // index &= 0x0f; - myBUSRAM[DSMAPS + index*4 + 0] = value & 0xff; // low byte - myBUSRAM[DSMAPS + index*4 + 1] = (value >> 8) & 0xff; - myBUSRAM[DSMAPS + index*4 + 2] = (value >> 16) & 0xff; - myBUSRAM[DSMAPS + index*4 + 3] = (value >> 24) & 0xff; // high byte + myRAM[DSMAPS + index*4 + 0] = value & 0xff; // low byte + myRAM[DSMAPS + index*4 + 1] = (value >> 8) & 0xff; + myRAM[DSMAPS + index*4 + 2] = (value >> 16) & 0xff; + myRAM[DSMAPS + index*4 + 3] = (value >> 24) & 0xff; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartBUS.hxx b/src/emucore/CartBUS.hxx index 2aa1e9610..70cf61300 100644 --- a/src/emucore/CartBUS.hxx +++ b/src/emucore/CartBUS.hxx @@ -84,9 +84,12 @@ class CartridgeBUS : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -98,7 +101,7 @@ class CartridgeBUS : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -113,9 +116,9 @@ class CartridgeBUS : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -225,7 +228,7 @@ class CartridgeBUS : public Cartridge private: // The 32K ROM image of the cartridge - std::array myImage; + ByteBuffer myImage; // Pointer to the 28K program ROM image of the cartridge uInt8* myProgramImage{nullptr}; @@ -234,13 +237,13 @@ class CartridgeBUS : public Cartridge uInt8* myDisplayImage{nullptr}; // Pointer to the 2K BUS driver image in RAM - uInt8* myBusDriverImage{nullptr}; + uInt8* myDriverImage{nullptr}; // The BUS 8k RAM image, used as: // $0000 - 2K BUS driver // $0800 - 4K Display Data // $1800 - 2K C Variable & Stack - std::array myBUSRAM; + std::array myRAM; // Pointer to the Thumb ARM emulator object unique_ptr myThumbEmulator; diff --git a/src/emucore/CartCDF.cxx b/src/emucore/CartCDF.cxx index c47154fb8..0e9ef03dc 100644 --- a/src/emucore/CartCDF.cxx +++ b/src/emucore/CartCDF.cxx @@ -59,32 +59,34 @@ namespace { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) - : Cartridge(settings, md5) + : Cartridge(settings, md5), + myImage(make_unique(32_KB)) { // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); + std::fill_n(myImage.get(), 32_KB, 0); + std::copy_n(image.get(), std::min(32_KB, size), myImage.get()); // even though the ROM is 32K, only 28K is accessible to the 6507 - createCodeAccessBase(28_KB); + createRomAccessArrays(28_KB); // Pointer to the program ROM (28K @ 0 byte offset) // which starts after the 2K CDF Driver and 2K C Code - myProgramImage = myImage.data() + 4_KB; + myProgramImage = myImage.get() + 4_KB; // Pointer to CDF driver in RAM - myBusDriverImage = myCDFRAM.data(); + myDriverImage = myRAM.data(); // Pointer to the display RAM - myDisplayImage = myCDFRAM.data() + DSRAM; + myDisplayImage = myRAM.data() + DSRAM; setupVersion(); // Create Thumbulator ARM emulator bool devSettings = settings.getBool("dev.settings"); myThumbEmulator = make_unique( - reinterpret_cast(myImage.data()), - reinterpret_cast(myCDFRAM.data()), - static_cast(myImage.size()), + reinterpret_cast(myImage.get()), + reinterpret_cast(myRAM.data()), + static_cast(32_KB), devSettings ? settings.getBool("dev.thumb.trapfatal") : false, thumulatorConfiguration(myCDFSubtype), this); setInitialState(); @@ -93,7 +95,7 @@ CartridgeCDF::CartridgeCDF(const ByteBuffer& image, size_t size, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeCDF::reset() { - initializeRAM(myCDFRAM.data()+2_KB, myCDFRAM.size()-2_KB); + initializeRAM(myRAM.data()+2_KB, myRAM.size()-2_KB); // CDF always starts in bank 6 initializeStartBank(6); @@ -111,7 +113,7 @@ void CartridgeCDF::reset() void CartridgeCDF::setInitialState() { // Copy initial CDF driver to Harmony RAM - std::copy_n(myImage.begin(), 2_KB, myBusDriverImage); + std::copy_n(myImage.get(), 2_KB, myDriverImage); myMusicWaveformSize.fill(27); @@ -255,7 +257,7 @@ uInt8 CartridgeCDF::peek(uInt16 address) if (sampleaddress < 0x8000) peekvalue = myImage[sampleaddress]; else if (sampleaddress >= 0x40000000 && sampleaddress < 0x40002000) // check for RAM - peekvalue = myCDFRAM[sampleaddress - 0x40000000]; + peekvalue = myRAM[sampleaddress - 0x40000000]; else peekvalue = 0; @@ -402,7 +404,7 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCDF::bank(uInt16 bank) +bool CartridgeCDF::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; @@ -415,7 +417,9 @@ bool CartridgeCDF::bank(uInt16 bank) // Map Program ROM image into the system for(uInt16 addr = 0x1040; addr < 0x2000; addr += System::PAGE_SIZE) { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 28_KB]; mySystem->setPageAccess(addr, access); } return myBankChanged = true; @@ -428,7 +432,7 @@ uInt16 CartridgeCDF::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeCDF::bankCount() const +uInt16 CartridgeCDF::romBankCount() const { return 7; } @@ -449,10 +453,10 @@ bool CartridgeCDF::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeCDF::getImage(size_t& size) const +const ByteBuffer& CartridgeCDF::getImage(size_t& size) const { - size = myImage.size(); - return myImage.data(); + size = 32_KB; + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -491,7 +495,7 @@ uInt32 CartridgeCDF::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) uInt8 CartridgeCDF::internalRamGetValue(uInt16 addr) const { if(addr < internalRamSize()) - return myCDFRAM[addr]; + return myRAM[addr]; else return 0; } @@ -515,7 +519,7 @@ bool CartridgeCDF::save(Serializer& out) const out.putShort(myJMPoperandAddress); // Harmony RAM - out.putByteArray(myCDFRAM.data(), myCDFRAM.size()); + out.putByteArray(myRAM.data(), myRAM.size()); // Audio info out.putIntArray(myMusicCounters.data(), myMusicCounters.size()); @@ -555,7 +559,7 @@ bool CartridgeCDF::load(Serializer& in) myJMPoperandAddress = in.getShort(); // Harmony RAM - in.getByteArray(myCDFRAM.data(), myCDFRAM.size()); + in.getByteArray(myRAM.data(), myRAM.size()); // Audio info in.getIntArray(myMusicCounters.data(), myMusicCounters.size()); @@ -584,10 +588,10 @@ uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) const { uInt16 address = myDatastreamBase + index * 4; - return myCDFRAM[address + 0] + // low byte - (myCDFRAM[address + 1] << 8) + - (myCDFRAM[address + 2] << 16) + - (myCDFRAM[address + 3] << 24) ; // high byte + return myRAM[address + 0] + // low byte + (myRAM[address + 1] << 8) + + (myRAM[address + 2] << 16) + + (myRAM[address + 3] << 24) ; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -595,10 +599,10 @@ void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value) { uInt16 address = myDatastreamBase + index * 4; - myCDFRAM[address + 0] = value & 0xff; // low byte - myCDFRAM[address + 1] = (value >> 8) & 0xff; - myCDFRAM[address + 2] = (value >> 16) & 0xff; - myCDFRAM[address + 3] = (value >> 24) & 0xff; // high byte + myRAM[address + 0] = value & 0xff; // low byte + myRAM[address + 1] = (value >> 8) & 0xff; + myRAM[address + 2] = (value >> 16) & 0xff; + myRAM[address + 3] = (value >> 24) & 0xff; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -606,10 +610,10 @@ uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) const { uInt16 address = myDatastreamIncrementBase + index * 4; - return myCDFRAM[address + 0] + // low byte - (myCDFRAM[address + 1] << 8) + - (myCDFRAM[address + 2] << 16) + - (myCDFRAM[address + 3] << 24) ; // high byte + return myRAM[address + 0] + // low byte + (myRAM[address + 1] << 8) + + (myRAM[address + 2] << 16) + + (myRAM[address + 3] << 24) ; // high byte } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -617,10 +621,10 @@ uInt32 CartridgeCDF::getWaveform(uInt8 index) const { uInt16 address = myWaveformBase + index * 4; - uInt32 result = myCDFRAM[address + 0] + // low byte - (myCDFRAM[address + 1] << 8) + - (myCDFRAM[address + 2] << 16) + - (myCDFRAM[address + 3] << 24); // high byte + uInt32 result = myRAM[address + 0] + // low byte + (myRAM[address + 1] << 8) + + (myRAM[address + 2] << 16) + + (myRAM[address + 3] << 24); // high byte result -= (0x40000000 + DSRAM); @@ -635,10 +639,10 @@ uInt32 CartridgeCDF::getSample() { uInt16 address = myWaveformBase; - uInt32 result = myCDFRAM[address + 0] + // low byte - (myCDFRAM[address + 1] << 8) + - (myCDFRAM[address + 2] << 16) + - (myCDFRAM[address + 3] << 24); // high byte + uInt32 result = myRAM[address + 0] + // low byte + (myRAM[address + 1] << 8) + + (myRAM[address + 2] << 16) + + (myRAM[address + 3] << 24); // high byte return result; } diff --git a/src/emucore/CartCDF.hxx b/src/emucore/CartCDF.hxx index 614744e23..d32127547 100644 --- a/src/emucore/CartCDF.hxx +++ b/src/emucore/CartCDF.hxx @@ -90,9 +90,12 @@ class CartridgeCDF : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -104,7 +107,7 @@ class CartridgeCDF : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -119,9 +122,9 @@ class CartridgeCDF : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -225,7 +228,7 @@ class CartridgeCDF : public Cartridge private: // The 32K ROM image of the cartridge - std::array myImage; + ByteBuffer myImage; // Pointer to the 28K program ROM image of the cartridge uInt8* myProgramImage{nullptr}; @@ -234,13 +237,13 @@ class CartridgeCDF : public Cartridge uInt8* myDisplayImage{nullptr}; // Pointer to the 2K CDF driver image in RAM - uInt8* myBusDriverImage{nullptr}; + uInt8* myDriverImage{nullptr}; // The CDF 8k RAM image, used as: // $0000 - 2K CDF driver // $0800 - 4K Display Data // $1800 - 2K C Variable & Stack - std::array myCDFRAM; + std::array myRAM; // Pointer to the Thumb ARM emulator object unique_ptr myThumbEmulator; diff --git a/src/emucore/CartCM.cxx b/src/emucore/CartCM.cxx index c460e72ff..dbaac7a54 100644 --- a/src/emucore/CartCM.cxx +++ b/src/emucore/CartCM.cxx @@ -23,11 +23,12 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeCM::CartridgeCM(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) - : Cartridge(settings, md5) + : Cartridge(settings, md5), + myImage(make_unique(16_KB)) { // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); + std::copy_n(image.get(), std::min(16_KB, size), myImage.get()); + createRomAccessArrays(16_KB); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -98,7 +99,7 @@ uInt8 CartridgeCM::column() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCM::bank(uInt16 bank) +bool CartridgeCM::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; @@ -119,7 +120,9 @@ bool CartridgeCM::bank(uInt16 bank) for(uInt16 addr = 0x1000; addr < 0x1800; addr += System::PAGE_SIZE) { access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize]; mySystem->setPageAccess(addr, access); } @@ -131,12 +134,16 @@ bool CartridgeCM::bank(uInt16 bank) if(mySWCHA & 0x10) { access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize]; } else { access.directPeekBase = &myRAM[addr & 0x7FF]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x07FF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x07FF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x07FF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x07FF) + myAccessSize]; } if((mySWCHA & 0x30) == 0x20) @@ -157,7 +164,7 @@ uInt16 CartridgeCM::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeCM::bankCount() const +uInt16 CartridgeCM::romBankCount() const { // We report 4 banks (of ROM), even though RAM can overlap the upper 2K // of cart address space at some times @@ -178,10 +185,10 @@ bool CartridgeCM::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeCM::getImage(size_t& size) const +const ByteBuffer& CartridgeCM::getImage(size_t& size) const { - size = myImage.size(); - return myImage.data(); + size = 16_KB; + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartCM.hxx b/src/emucore/CartCM.hxx index 2c0cf54d2..3a58889b4 100644 --- a/src/emucore/CartCM.hxx +++ b/src/emucore/CartCM.hxx @@ -141,9 +141,12 @@ class CartridgeCM : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -155,7 +158,7 @@ class CartridgeCM : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -170,9 +173,9 @@ class CartridgeCM : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -243,7 +246,7 @@ class CartridgeCM : public Cartridge shared_ptr myCompuMate; // The 16K ROM image of the cartridge - std::array myImage; + ByteBuffer myImage; // The 2K of RAM std::array myRAM; diff --git a/src/emucore/CartCTY.cxx b/src/emucore/CartCTY.cxx index 22472dc0f..67647f89c 100644 --- a/src/emucore/CartCTY.cxx +++ b/src/emucore/CartCTY.cxx @@ -24,18 +24,19 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeCTY::CartridgeCTY(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) - : Cartridge(settings, md5) + : Cartridge(settings, md5), + myImage(make_unique(32_KB)) { // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); + std::copy_n(image.get(), std::min(32_KB, size), myImage.get()); + createRomAccessArrays(32_KB); // Default to no tune data in case user is utilizing an old ROM myTuneData.fill(0); // Extract tune data if it exists - if(size > myImage.size()) - std::copy_n(image.get() + myImage.size(), size - myImage.size(), myTuneData.begin()); + if(size > 32_KB) + std::copy_n(image.get() + 32_KB, size - 32_KB, myTuneData.begin()); // Point to the first tune myFrequencyImage = myTuneData.data(); @@ -229,7 +230,7 @@ bool CartridgeCTY::poke(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCTY::bank(uInt16 bank) +bool CartridgeCTY::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; @@ -240,7 +241,9 @@ bool CartridgeCTY::bank(uInt16 bank) System::PageAccess access(this, System::PageAccessType::READ); for(uInt16 addr = 0x1080; addr < 0x2000; addr += System::PAGE_SIZE) { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + myAccessSize]; mySystem->setPageAccess(addr, access); } return myBankChanged = true; @@ -253,7 +256,7 @@ uInt16 CartridgeCTY::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeCTY::bankCount() const +uInt16 CartridgeCTY::romBankCount() const { return 8; } @@ -277,10 +280,10 @@ bool CartridgeCTY::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeCTY::getImage(size_t& size) const +const ByteBuffer& CartridgeCTY::getImage(size_t& size) const { - size = myImage.size(); - return myImage.data(); + size = 32_KB; + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartCTY.hxx b/src/emucore/CartCTY.hxx index 5626013a1..5af3ceff4 100644 --- a/src/emucore/CartCTY.hxx +++ b/src/emucore/CartCTY.hxx @@ -139,9 +139,12 @@ class CartridgeCTY : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -153,7 +156,7 @@ class CartridgeCTY : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -168,9 +171,9 @@ class CartridgeCTY : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -260,7 +263,7 @@ class CartridgeCTY : public Cartridge private: // The 32K ROM image of the cartridge - std::array myImage; + ByteBuffer myImage; // The 28K ROM image of the music std::array myTuneData; diff --git a/src/emucore/CartCV.cxx b/src/emucore/CartCV.cxx index 73c55954b..8fe746f1a 100644 --- a/src/emucore/CartCV.cxx +++ b/src/emucore/CartCV.cxx @@ -20,148 +20,38 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeCV::CartridgeCV(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - if(mySize == myImage.size()) - { - // Copy the ROM data into my buffer - std::copy_n(image.get(), myImage.size(), myImage.begin()); - } - else if(mySize == 4_KB) + myBankShift = BANK_SHIFT; + myRamSize = RAM_SIZE; + myRamWpHigh = RAM_HIGH_WP; + + if(size == 4_KB) { // The game has something saved in the RAM // Useful for MagiCard program listings - // Copy the ROM data into my buffer - std::copy_n(image.get() + myImage.size(), myImage.size(), myImage.begin()); + // Copy the ROM image into my buffer + std::copy_n(image.get() + 2_KB, 2_KB, myImage.get()); + myInitialRAM = make_unique(1_KB); // Copy the RAM image into a buffer for use in reset() - std::copy_n(image.get(), myInitialRAM.size(), myInitialRAM.begin()); + std::copy_n(image.get(), 1_KB, myInitialRAM.get()); } - createCodeAccessBase(myImage.size() + myRAM.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeCV::reset() { - if(mySize == 4_KB) + if(myInitialRAM != nullptr) { // Copy the RAM image into my buffer - myRAM = myInitialRAM; + std::copy_n(myInitialRAM.get(), 1_KB, myRAM.get()); } else - initializeRAM(myRAM.data(), myRAM.size()); + initializeRAM(myRAM.get(), myRamSize); myBankChanged = true; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCV::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[addr & 0x07FF]; - access.codeAccessBase = &myCodeAccessBase[addr & 0x07FF]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.directPeekBase = nullptr; - access.codeAccessBase = nullptr; - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - - // Set the page accessing method for the RAM reading pages - access.directPokeBase = nullptr; - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x03FF]; - access.codeAccessBase = &myCodeAccessBase[2048 + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeCV::peek(uInt16 address) -{ - // The only way we can get to this method is if we attempt to read from - // the write port (0xF400 - 0xF7FF, 1024 bytes), in which case an - // unwanted write is potentially triggered - return peekRAM(myRAM[address & 0x03FF], address); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCV::poke(uInt16 address, uInt8 value) -{ - pokeRAM(myRAM[address & 0x03FF], address, value); - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCV::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0800) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - // The following will work for both reads and writes - myRAM[address & 0x03FF] = value; - } - else - myImage[address & 0x07FF] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeCV::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCV::save(Serializer& out) const -{ - try - { - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeCV::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCV::load(Serializer& in) -{ - try - { - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeCV::load" << endl; - return false; - } - - return true; -} diff --git a/src/emucore/CartCV.hxx b/src/emucore/CartCV.hxx index 3b872ce9d..809d9b373 100644 --- a/src/emucore/CartCV.hxx +++ b/src/emucore/CartCV.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartCVWidget.hxx" #endif @@ -33,9 +33,9 @@ class System; $F400-$F7FF write to RAM $F800-$FFFF ROM - @author Eckhard Stolberg + @author Eckhard Stolberg, Thomas Jentzsch */ -class CartridgeCV : public Cartridge +class CartridgeCV : public CartridgeEnhanced { friend class CartridgeCVWidget; @@ -47,9 +47,10 @@ class CartridgeCV : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeCV(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 2_KB); virtual ~CartridgeCV() = default; public: @@ -58,47 +59,6 @@ class CartridgeCV : public Cartridge */ void reset() override; - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -118,35 +78,22 @@ class CartridgeCV : public Cartridge } #endif - public: - /** - Get the byte at the specified address + private: + bool checkSwitchBank(uInt16, uInt8 = 0) override { return false; } - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + protected: + // Initial RAM data from the cart (doesn't always exist) + ByteBuffer myInitialRAM{nullptr}; private: - // The 2k ROM image for the cartridge - std::array myImage; + // Calculated as: log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 11; // 2K - // Initial size of the cart data - size_t mySize{0}; + // RAM size + static constexpr uInt32 RAM_SIZE = 0x400; // 1K - // The 1024 bytes of RAM - std::array myRAM; - - // Initial RAM data from the cart (doesn't always exist) - std::array myInitialRAM; + // Write port for extra RAM is at high address + static constexpr bool RAM_HIGH_WP = true; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartCVPlus.cxx b/src/emucore/CartCVPlus.cxx deleted file mode 100644 index eb3bb1023..000000000 --- a/src/emucore/CartCVPlus.cxx +++ /dev/null @@ -1,218 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include "System.hxx" -#include "TIA.hxx" -#include "CartCVPlus.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeCVPlus::CartridgeCVPlus(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) -{ - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize + myRAM.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlus::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); - - // We'll map the startup bank into the first segment upon reset - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeCVPlus::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READWRITE); - - // The hotspot ($3D) is in TIA address space, so we claim it here - for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.directPeekBase = access.directPokeBase = nullptr; - access.codeAccessBase = nullptr; - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[mySize + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x03FF]; - access.codeAccessBase = &myCodeAccessBase[mySize + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank into the first segment - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeCVPlus::peek(uInt16 address) -{ - if((address & 0x0FFF) < 0x0800) // Write port is at 0xF400 - 0xF7FF (1024 bytes) - return peekRAM(myRAM[address & 0x03FF], address); - else - return myImage[(address & 0x07FF) + (myCurrentBank << 11)]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCVPlus::poke(uInt16 address, uInt8 value) -{ - uInt16 pokeAddress = address; - address &= 0x0FFF; - - if(address < 0x0040) - { - // Switch banks if necessary - if(address == 0x003D) - bank(value); - - // Handle TIA space that we claimed above - return mySystem->tia().poke(address, value); - } - else - pokeRAM(myRAM[address & 0x03FF], pokeAddress, value); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCVPlus::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Make sure the bank they're asking for is reasonable - if((uInt32(bank) << 11) < mySize) - { - myCurrentBank = bank; - } - else - { - // Oops, the bank they're asking for isn't valid so let's wrap it - // around to a valid bank number - myCurrentBank = bank % (mySize >> 11); - } - - uInt32 offset = myCurrentBank << 11; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1800; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x07FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x07FF)]; - mySystem->setPageAccess(addr, access); - } - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeCVPlus::getBank(uInt16) const -{ - return myCurrentBank; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeCVPlus::bankCount() const -{ - return uInt16(mySize >> 11); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCVPlus::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0800) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - // The following will work for both reads and writes - myRAM[address & 0x03FF] = value; - } - else - myImage[(address & 0x07FF) + (myCurrentBank << 11)] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeCVPlus::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCVPlus::save(Serializer& out) const -{ - try - { - out.putShort(myCurrentBank); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeCVPlus::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeCVPlus::load(Serializer& in) -{ - try - { - myCurrentBank = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeCVPlus::load" << endl; - return false; - } - - // Now, go to the current bank - bank(myCurrentBank); - - return true; -} diff --git a/src/emucore/CartCVPlus.hxx b/src/emucore/CartCVPlus.hxx deleted file mode 100644 index 63fcb62da..000000000 --- a/src/emucore/CartCVPlus.hxx +++ /dev/null @@ -1,188 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef CARTRIDGECVPlus_HXX -#define CARTRIDGECVPlus_HXX - -class System; - -#include "bspf.hxx" -#include "Cart.hxx" -#ifdef DEBUGGER_SUPPORT - #include "CartCVPlusWidget.hxx" -#endif - -/** - Cartridge class based on both Commavid and 3F/3E schemes: - - Commavid (RAM): - $F000-$F3FF read from RAM - $F400-$F7FF write to RAM - - 3F/3E (ROM): - $F800-$FFFF ROM - - In this bankswitching scheme the 2600's 4K cartridge - address space is broken into two 2K segments. The lower 2K - is RAM, as decribed above (same as CV/Commavid scheme). - To map ROM, the desired bank number of the upper 2K segment is - selected by storing its value into $3D. - - @author Stephen Anthony, LS_Dracon -*/ - -class CartridgeCVPlus : public Cartridge -{ - friend class CartridgeCVPlusWidget; - - public: - /** - Create a new cartridge using the specified image and size - - @param image Pointer to the ROM image - @param size The size of the ROM image - @param settings A reference to the various settings (read-only) - */ - CartridgeCVPlus(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); - virtual ~CartridgeCVPlus() = default; - - public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - - /** - Get a descriptor for the device name (used in error checking). - - @return The name of the object - */ - string name() const override { return "CartridgeCV+"; } - - #ifdef DEBUGGER_SUPPORT - /** - Get debugger widget responsible for accessing the inner workings - of the cart. - */ - CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, - const GUI::Font& nfont, int x, int y, int w, int h) override - { - return new CartridgeCVPlusWidget(boss, lfont, nfont, x, y, w, h, *this); - } - #endif - - public: - /** - Get the byte at the specified address - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - - private: - // Pointer to a dynamically allocated ROM image of the cartridge - ByteBuffer myImage; - - // The 1024 bytes of RAM - std::array myRAM; - - // Size of the ROM image - size_t mySize{0}; - - // Indicates which bank is currently active for the first segment - uInt16 myCurrentBank{0}; - - private: - // Following constructors and assignment operators not supported - CartridgeCVPlus() = delete; - CartridgeCVPlus(const CartridgeCVPlus&) = delete; - CartridgeCVPlus(CartridgeCVPlus&&) = delete; - CartridgeCVPlus& operator=(const CartridgeCVPlus&) = delete; - CartridgeCVPlus& operator=(CartridgeCVPlus&&) = delete; -}; - -#endif diff --git a/src/emucore/CartCreator.cxx b/src/emucore/CartCreator.cxx new file mode 100644 index 000000000..fe7faed55 --- /dev/null +++ b/src/emucore/CartCreator.cxx @@ -0,0 +1,348 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "bspf.hxx" +#include "Cart.hxx" +#include "Cart0840.hxx" +#include "Cart2K.hxx" +#include "Cart3E.hxx" +#include "Cart3EX.hxx" +#include "Cart3EPlus.hxx" +#include "Cart3F.hxx" +#include "Cart4A50.hxx" +#include "Cart4K.hxx" +#include "Cart4KSC.hxx" +#include "CartAR.hxx" +#include "CartBF.hxx" +#include "CartBFSC.hxx" +#include "CartBUS.hxx" +#include "CartCDF.hxx" +#include "CartCM.hxx" +#include "CartCTY.hxx" +#include "CartCV.hxx" +#include "CartDF.hxx" +#include "CartDFSC.hxx" +#include "CartDPC.hxx" +#include "CartDPCPlus.hxx" +#include "CartE0.hxx" +#include "CartE7.hxx" +#include "CartE78K.hxx" +#include "CartEF.hxx" +#include "CartEFSC.hxx" +#include "CartF0.hxx" +#include "CartF4.hxx" +#include "CartF4SC.hxx" +#include "CartF6.hxx" +#include "CartF6SC.hxx" +#include "CartF8.hxx" +#include "CartF8SC.hxx" +#include "CartFA.hxx" +#include "CartFA2.hxx" +#include "CartFC.hxx" +#include "CartFE.hxx" +#include "CartMDM.hxx" +#include "CartSB.hxx" +#include "CartTVBoy.hxx" +#include "CartUA.hxx" +#include "CartWD.hxx" +#include "CartX07.hxx" +#include "MD5.hxx" +#include "Props.hxx" +#include "Logger.hxx" +#include "OSystem.hxx" + +#include "CartDetector.hxx" +#include "CartCreator.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +unique_ptr CartCreator::create(const FilesystemNode& file, + const ByteBuffer& image, size_t size, string& md5, + const string& propertiesType, Settings& settings) +{ + unique_ptr cartridge; + Bankswitch::Type type = Bankswitch::nameToType(propertiesType), + detectedType = type; + string id; + + // Collect some info about the ROM + ostringstream buf; + + // First inspect the file extension itself + // If a valid type is found, it will override the one passed into this method + Bankswitch::Type typeByName = Bankswitch::typeFromExtension(file); + if(typeByName != Bankswitch::Type::_AUTO) + type = detectedType = typeByName; + + // See if we should try to auto-detect the cartridge type + // If we ask for extended info, always do an autodetect + if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo")) + { + detectedType = CartDetector::autodetectType(image, size); + if(type != Bankswitch::Type::_AUTO && type != detectedType) + cerr << "Auto-detection not consistent: " + << Bankswitch::typeToName(type) << ", " + << Bankswitch::typeToName(detectedType) << endl; + + type = detectedType; + buf << Bankswitch::typeToName(type) << "*"; + } + else + buf << Bankswitch::typeToName(type); + + // Check for multicart first; if found, get the correct part of the image + switch(type) + { + case Bankswitch::Type::_2IN1: + // Make sure we have a valid sized image + if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB) + { + cartridge = + createFromMultiCart(image, size, 2, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_4IN1: + // Make sure we have a valid sized image + if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB) + { + cartridge = + createFromMultiCart(image, size, 4, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_8IN1: + // Make sure we have a valid sized image + if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB) + { + cartridge = + createFromMultiCart(image, size, 8, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_16IN1: + // Make sure we have a valid sized image + if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB) + { + cartridge = + createFromMultiCart(image, size, 16, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_32IN1: + // Make sure we have a valid sized image + if(size == 32*2_KB || size == 32*4_KB) + { + cartridge = + createFromMultiCart(image, size, 32, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_64IN1: + // Make sure we have a valid sized image + if(size == 64*2_KB || size == 64*4_KB) + { + cartridge = + createFromMultiCart(image, size, 64, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + case Bankswitch::Type::_128IN1: + // Make sure we have a valid sized image + if(size == 128*2_KB || size == 128*4_KB) + { + cartridge = + createFromMultiCart(image, size, 128, md5, detectedType, id, settings); + buf << id; + } + else + throw runtime_error("Invalid cart size for type '" + + Bankswitch::typeToName(type) + "'"); + break; + + default: + cartridge = createFromImage(image, size, detectedType, md5, settings); + break; + } + + if(size < 1_KB) + buf << " (" << size << "B) "; + else + buf << " (" << (size/1_KB) << "K) "; + + cartridge->setAbout(buf.str(), Bankswitch::typeToName(type), id); + + return cartridge; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +unique_ptr +CartCreator::createFromMultiCart(const ByteBuffer& image, size_t& size, + uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings) +{ + // Get a piece of the larger image + uInt32 i = settings.getInt("romloadcount"); + + // Move to the next game + if(!settings.getBool("romloadprev")) + i = (i + 1) % numroms; + else + i = (i - 1) % numroms; + settings.setValue("romloadcount", i); + + size /= numroms; + ByteBuffer slice = make_unique(size); + std::copy_n(image.get()+i*size, size, slice.get()); + + // We need a new md5 and name + md5 = MD5::hash(slice, uInt32(size)); // FIXME + ostringstream buf; + buf << " [G" << (i+1) << "]"; + id = buf.str(); + + if(size <= 2_KB) type = Bankswitch::Type::_2K; + else if(size == 4_KB) type = Bankswitch::Type::_4K; + else if(size == 8_KB) type = Bankswitch::Type::_F8; + else /* default */ type = Bankswitch::Type::_4K; + + return createFromImage(slice, size, type, md5, settings); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +unique_ptr +CartCreator::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, + const string& md5, Settings& settings) +{ + // We should know the cart's type by now so let's create it + switch(type) + { + case Bankswitch::Type::_0840: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_2K: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_3E: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_3EX: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_3EP: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_3F: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_4A50: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_4K: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_4KSC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_AR: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_BF: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_BFSC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_BUS: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_CDF: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_CM: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_CTY: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_CV: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_DF: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_DFSC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_DPC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_DPCP: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_E0: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_E7: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_E78K: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_EF: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_EFSC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F0: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F4: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F4SC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F6: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F6SC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F8: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_F8SC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_FA: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_FA2: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_FC: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_FE: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_MDM: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_UA: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_UASW: + return make_unique(image, size, md5, settings, true); + case Bankswitch::Type::_SB: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_TVBOY: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_WD: + case Bankswitch::Type::_WDSW: + return make_unique(image, size, md5, settings); + case Bankswitch::Type::_X07: + return make_unique(image, size, md5, settings); + default: + return nullptr; // The remaining types have already been handled + } +} diff --git a/src/emucore/CartCreator.hxx b/src/emucore/CartCreator.hxx new file mode 100644 index 000000000..757d306ba --- /dev/null +++ b/src/emucore/CartCreator.hxx @@ -0,0 +1,96 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGE_CREATOR_HXX +#define CARTRIDGE_CREATOR_HXX + +class Cartridge; +class Properties; +class Settings; + +#include "Bankswitch.hxx" +#include "bspf.hxx" + +/** + Create a cartridge based on the given information. Internally, it will + use autodetection and various heuristics to determine the cart type. + + @author Stephen Anthony +*/ +class CartCreator +{ + public: + /** + Create a new cartridge object allocated on the heap. The + type of cartridge created depends on the properties object. + + @param image A pointer to the ROM image + @param size The size of the ROM image + @param md5 The md5sum for the given ROM image (can be updated) + @param dtype The detected bankswitch type of the ROM image + @param settings The settings container + @return Pointer to the new cartridge object allocated on the heap + */ + static unique_ptr create(const FilesystemNode& file, + const ByteBuffer& image, size_t size, string& md5, + const string& dtype, Settings& settings); + + private: + /** + Create a cartridge from a multi-cart image pointer; internally this + takes a slice of the ROM image ues that for the cartridge. + + @param image A pointer to the complete ROM image + @param size The size of the ROM image slice + @param numroms The number of ROMs in the multicart + @param md5 The md5sum for the slice of the ROM image + @param type The detected type of the slice of the ROM image + @param id The ID for the slice of the ROM image + @param settings The settings container + + @return Pointer to the new cartridge object allocated on the heap + */ + static unique_ptr + createFromMultiCart(const ByteBuffer& image, size_t& size, + uInt32 numroms, string& md5, Bankswitch::Type type, string& id, + Settings& settings); + + /** + Create a cartridge from the entire image pointer. + + @param image A pointer to the complete ROM image + @param size The size of the ROM image + @param type The bankswitch type of the ROM image + @param md5 The md5sum for the ROM image + @param settings The settings container + + @return Pointer to the new cartridge object allocated on the heap + */ + static unique_ptr + createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, + const string& md5, Settings& settings); + + private: + // Following constructors and assignment operators not supported + CartCreator() = delete; + CartCreator(const CartCreator&) = delete; + CartCreator(CartCreator&&) = delete; + CartCreator& operator=(const CartCreator&) = delete; + CartCreator& operator=(CartCreator&&) = delete; +}; + +#endif diff --git a/src/emucore/CartDASH.cxx b/src/emucore/CartDASH.cxx deleted file mode 100644 index f721a1edb..000000000 --- a/src/emucore/CartDASH.cxx +++ /dev/null @@ -1,343 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include "System.hxx" -#include "TIA.hxx" -#include "CartDASH.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CartridgeDASH::CartridgeDASH(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) -{ - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize + myRAM.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASH::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - - // Remember startup bank (0 per spec, rather than last per 3E scheme). - // Set this to go to 3rd 1K Bank. - initializeStartBank(0); - - // Initialise bank values for all ROM/RAM access - // This is used to reverse-lookup from address to bank location - for(uInt32 b = 0; b < 8; ++b) - { - bankInUse[b] = BANK_UNDEFINED; // bank is undefined and inaccessible! - segmentInUse[b/2] = BANK_UNDEFINED; - } - initializeBankState(); - - // We'll map the startup banks 0 and 3 from the image into the third 1K bank upon reset - bankROM((0 << BANK_BITS) | 0); - bankROM((3 << BANK_BITS) | 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASH::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READWRITE); - - // The hotspots are in TIA address space, so we claim it here - for (uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - - // Initialise bank values for all ROM/RAM access - // This is used to reverse-lookup from address to bank location - for (uInt32 b = 0; b < 8; ++b) - { - bankInUse[b] = BANK_UNDEFINED; // bank is undefined and inaccessible! - segmentInUse[b/2] = BANK_UNDEFINED; - } - initializeBankState(); - - // Setup the last segment (of 4, each 1K) to point to the first ROM slice - // Actually we DO NOT want "always". It's just on bootup, and can be out switched later - bankROM((0 << BANK_BITS) | 0); - bankROM((3 << BANK_BITS) | 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeDASH::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; // restrict to 4K address range - - uInt8 value = 0; - uInt32 bank = (address >> (ROM_BANK_TO_POWER - 1)) & 7; // convert to 512 byte bank index (0-7) - uInt16 imageBank = bankInUse[bank]; // the ROM/RAM bank that's here - - if(imageBank == BANK_UNDEFINED) // an uninitialised bank? - { - // accessing invalid bank, so return should be... random? - value = mySystem->randGenerator().next(); - - } - else if(imageBank & BITMASK_ROMRAM) // a RAM bank - { - Int32 ramBank = imageBank & BIT_BANK_MASK; // discard irrelevant bits - Int32 offset = ramBank << RAM_BANK_TO_POWER; // base bank address in RAM - offset += (address & BITMASK_RAM_BANK); // + byte offset in RAM bank - - return peekRAM(myRAM[offset], peekAddress); - } - - return value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::poke(uInt16 address, uInt8 value) -{ - bool changed = false; - - // Check for write to the bank switch address. RAM/ROM and bank # are encoded in 'value' - // There are NO mirrored hotspots. - - if (address == BANK_SWITCH_HOTSPOT_RAM) - changed = bankRAM(value); - else if (address == BANK_SWITCH_HOTSPOT_ROM) - changed = bankROM(value); - - if(!(address & 0x1000)) - { - // Handle TIA space that we claimed above - changed = changed || mySystem->tia().poke(address, value); - } - else - { - uInt32 bankNumber = (address >> RAM_BANK_TO_POWER) & 7; // now 512 byte bank # (ie: 0-7) - Int16 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference - - if(whichBankIsThere & BITMASK_ROMRAM) - { - uInt32 byteOffset = address & BITMASK_RAM_BANK; - uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset; - pokeRAM(myRAM[baseAddress], address, value); - changed = true; - } - } - - return changed; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::bankRAM(uInt8 bank) -{ - if (bankLocked()) // debugger can lock RAM - return false; - - // Each RAM bank uses two slots, separated by 0x800 in memory -- one read, one write. - bankRAMSlot(bank | BITMASK_ROMRAM | 0); - bankRAMSlot(bank | BITMASK_ROMRAM | BITMASK_LOWERUPPER); - - // Remember that this hotspot was accessed for RAM - segmentInUse[(bank >> BANK_BITS) & 3] = bank | BITMASK_ROMRAM; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASH::bankRAMSlot(uInt16 bank) -{ - uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) to 512 byte block - uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range - bool upper = bank & BITMASK_LOWERUPPER; // is this the read or write port - - uInt32 startCurrentBank = currentBank << RAM_BANK_TO_POWER; // Effectively * 512 bytes - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - if(upper) // We're mapping the write port - { - bankInUse[bankNumber + 4] = Int16(bank); - access.type = System::PageAccessType::WRITE; - } - else // We're mapping the read port - { - bankInUse[bankNumber] = Int16(bank); - access.type = System::PageAccessType::READ; - } - - uInt16 start = 0x1000 + (bankNumber << RAM_BANK_TO_POWER) + (upper ? RAM_WRITE_OFFSET : 0); - uInt16 end = start + RAM_BANK_SIZE - 1; - - for (uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - { - if(!upper) - access.directPeekBase = &myRAM[startCurrentBank + (addr & (RAM_BANK_SIZE - 1))]; - - access.codeAccessBase = &myCodeAccessBase[mySize + startCurrentBank + (addr & (RAM_BANK_SIZE - 1))]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::bankROM(uInt8 bank) -{ - if (bankLocked()) // debugger can lock ROM - return false; - - // Map ROM bank image into the system into the correct slot - // Memory map is 1K slots at 0x1000, 0x1400, 0x1800, 0x1C00 - // Each ROM uses 2 consecutive 512 byte slots - bankROMSlot(bank | 0); - bankROMSlot(bank | BITMASK_LOWERUPPER); - - // Remember that this hotspot was accessed for ROM - segmentInUse[(bank >> BANK_BITS) & 3] = bank; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASH::bankROMSlot(uInt16 bank) -{ - uInt16 bankNumber = (bank >> BANK_BITS) & 3; // which bank # we are switching TO (BITS D6,D7) - uInt16 currentBank = bank & BIT_BANK_MASK; // Wrap around/restrict to valid range - bool upper = bank & BITMASK_LOWERUPPER; // is this the lower or upper 512b - - bankInUse[bankNumber * 2 + (upper ? 1 : 0)] = Int16(bank); // Record which bank switched in (as ROM) - - uInt32 startCurrentBank = currentBank << ROM_BANK_TO_POWER; // Effectively *1K - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - uInt16 start = 0x1000 + (bankNumber << ROM_BANK_TO_POWER) + (upper ? ROM_BANK_SIZE / 2 : 0); - uInt16 end = start + ROM_BANK_SIZE / 2 - 1; - - for (uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))]; - access.codeAccessBase = &myCodeAccessBase[startCurrentBank + (addr & (ROM_BANK_SIZE - 1))]; - mySystem->setPageAccess(addr, access); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDASH::initializeBankState() -{ - // Switch in each 512b slot - for(uInt32 b = 0; b < 8; ++b) - { - if(bankInUse[b] == BANK_UNDEFINED) - { - // All accesses point to peek/poke above - System::PageAccess access(this, System::PageAccessType::READ); - uInt16 start = 0x1000 + (b << RAM_BANK_TO_POWER); - uInt16 end = start + RAM_BANK_SIZE - 1; - for (uInt16 addr = start; addr <= end; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); - } - else if (bankInUse[b] & BITMASK_ROMRAM) - bankRAMSlot(bankInUse[b]); - else - bankROMSlot(bankInUse[b]); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::patch(uInt16 address, uInt8 value) -{ -#if 0 - // Patch the cartridge ROM (for debugger) - - myBankChanged = true; - - uInt32 bankNumber = (address >> RAM_BANK_TO_POWER) & 7; // now 512 byte bank # (ie: 0-7) - Int16 whichBankIsThere = bankInUse[bankNumber]; // ROM or RAM bank reference - - if (whichBankIsThere == BANK_UNDEFINED) { - - // We're trying to access undefined memory (no bank here yet). Fail! - myBankChanged = false; - - } else if (whichBankIsThere & BITMASK_ROMRAM) { // patching RAM (512 byte banks) - - uInt32 byteOffset = address & BITMASK_RAM_BANK; - uInt32 baseAddress = ((whichBankIsThere & BIT_BANK_MASK) << RAM_BANK_TO_POWER) + byteOffset; - myRAM[baseAddress] = value; // write to RAM - - // TODO: Stephen -- should we set 'myBankChanged' true when there's a RAM write? - - } else { // patching ROM (1K banks) - - uInt32 byteOffset = address & BITMASK_ROM_BANK; - uInt32 baseAddress = (whichBankIsThere << ROM_BANK_TO_POWER) + byteOffset; - myImage[baseAddress] = value; // write to the image - } - - return myBankChanged; -#else - return false; -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeDASH::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::save(Serializer& out) const -{ - try - { - out.putShortArray(bankInUse.data(), bankInUse.size()); - out.putShortArray(segmentInUse.data(), segmentInUse.size()); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch (...) - { - cerr << "ERROR: CartridgeDASH::save" << endl; - return false; - } - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDASH::load(Serializer& in) -{ - try - { - in.getShortArray(bankInUse.data(), bankInUse.size()); - in.getShortArray(segmentInUse.data(), segmentInUse.size()); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch (...) - { - cerr << "ERROR: CartridgeDASH::load" << endl; - return false; - } - - initializeBankState(); - return true; -} diff --git a/src/emucore/CartDASH.hxx b/src/emucore/CartDASH.hxx deleted file mode 100644 index 8bd9fa523..000000000 --- a/src/emucore/CartDASH.hxx +++ /dev/null @@ -1,277 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef CARTRIDGEDASH_HXX -#define CARTRIDGEDASH_HXX - -class System; - -#include "bspf.hxx" -#include "Cart.hxx" - -#ifdef DEBUGGER_SUPPORT -class CartridgeDASHWidget; - #include "CartDASHWidget.hxx" -#endif - -/** - Cartridge class for new tiling engine "Boulder Dash" format games with RAM. - Kind of a combination of 3F and 3E, with better switchability. - B.Watson's Cart3E was used as a template for building this implementation. - - The destination bank (0-3) is held in the top bits of the value written to - $3E (for RAM switching) or $3F (for ROM switching). The low 6 bits give - the actual bank number (0-63) corresponding to 512 byte blocks for RAM and - 1024 byte blocks for ROM. The maximum size is therefore 32K RAM and 64K ROM. - - D7D6 indicate the bank number (0-3) - D5D4D3D2D1D0 indicate the actual # (0-63) from the image/ram - - ROM: - - Note: in descriptions $F000 is equivalent to $1000 -- that is, we only deal - with the low 13 bits of addressing. Stella code uses $1000, I'm used to $F000 - So, mask with top bits clear :) when reading this document. - - In this scheme, the 4K address space is broken into four 1K ROM segments. - living at 0x1000, 0x1400, 0x1800, 0x1C00 (or, same thing, 0xF000... etc.), - and four 512 byte RAM segments, living at 0x1000, 0x1200, 0x1400, 0x1600 - with write-mirrors +0x800 of these. The last 1K ROM ($FC00-$FFFF) segment - in the 6502 address space (ie: $1C00-$1FFF) is initialised to point to the - FIRST 1K of the ROM image, so the reset vectors must be placed at the - end of the first 1K in the ROM image. Note, this is DIFFERENT to 3E which - switches in the UPPER bank and this bank is fixed. This allows variable sized - ROM without having to detect size. First bank (0) in ROM is the default fixed - bank mapped to $FC00. - - The system requires the reset vectors to be valid on a reset, so either the - hardware first switches in the first bank, or the programmer must ensure - that the reset vector is present in ALL ROM banks which might be switched - into the last bank area. Currently the latter (programmer onus) is required, - but it would be nice for the cartridge hardware to auto-switch on reset. - - ROM switching (write of block+bank number to $3F) D7D6 upper 2 bits of bank # - indicates the destination segment (0-3, corresponding to $F000, $F400, $F800, - $FC00), and lower 6 bits indicate the 1K bank to switch in. Can handle 64 - x 1K ROM banks (64K total). - - D7 D6 D5D4D3D2D1D0 - 0 0 x x x x x x switch a 1K ROM bank xxxxx to $F000 - 0 1 switch a 1K ROM bank xxxxx to $F400 - 1 0 switch a 1K ROM bank xxxxx to $F800 - 1 1 switch a 1K ROM bank xxxxx to $FC00 - - RAM switching (write of segment+bank number to $3E) with D7D6 upper 2 bits of - bank # indicates the destination RAM segment (0-3, corresponding to $F000, - $F200, $F400, $F600). Note that this allows contiguous 2K of RAM to be - configured by setting 4 consecutive RAM segments each 512 bytes with - consecutive addresses. However, as the write address of RAM is +0x800, this - invalidates ROM access as described below. - - can handle 64 x 512 byte RAM banks (32K total) - - D7 D6 D5D4D3D2D1D0 - 0 0 x x x x x x switch a 512 byte RAM bank xxxxx to $F000 with write @ $F800 - 0 1 switch a 512 byte RAM bank xxxxx to $F200 with write @ $FA00 - 1 0 switch a 512 byte RAM bank xxxxx to $F400 with write @ $FC00 - 1 1 switch a 512 byte RAM bank xxxxx to $F600 with write @ $FE00 - - It is possible to switch multiple RAM banks and ROM banks together - - For example, - F000-F1FF RAM bank A (512 byte READ) - F200-F3FF high 512 bytes of ROM bank previously loaded at F000 - F400 ROM bank 0 (1K) - F800 RAM bank A (512 byte WRITE) - FA00-FBFF high 512 bytes of ROM bank previously loaded at F400 - FC00 ROM bank 1 - - This example shows 512 bytes of RAM, and 2 1K ROM banks and two 512 byte ROM - bank halves. - - Switching RAM blocks (D7D6 of $3E) partially invalidates ROM blocks, as below... - - RAM block Invalidates ROM block - 0 0 (lower half), 2 (lower half) - 1 0 (upper half), 2 (upper half) - 2 1 (lower half), 3 (upper half) - 3 1 (upper half), 3 (lower half) - - For example, RAM block 1 uses address $F200-$F3FF and $FA00-$FBFF - ROM block 0 uses address $F000-$F3FF, and ROM block 2 uses address $F800-$FBFF - Switching in RAM block 1 makes F200-F3FF ROM inaccessible, however F000-F1FF is - still readable. So, care must be paid. - - This crazy RAM layout is useful as it allows contiguous RAM to be switched in, - up to 2K in one sequentially accessible block. This means you CAN have 2K of - consecutive RAM (don't forget to copy your reset vectors!) - - @author Andrew Davie -*/ - -class CartridgeDASH: public Cartridge -{ - friend class CartridgeDASHWidget; - - public: - /** - Create a new cartridge using the specified image and size - - @param image Pointer to the ROM image - @param size The size of the ROM image - @param md5 The md5sum of the ROM image - @param settings A reference to the various settings (read-only) - */ - CartridgeDASH(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); - virtual ~CartridgeDASH() = default; - - public: - /** Reset device to its power-on state */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - - /** - Get a descriptor for the device name (used in error checking). - - @return The name of the object - */ - string name() const override { return "CartridgeDASH"; } - - #ifdef DEBUGGER_SUPPORT - /** - Get debugger widget responsible for accessing the inner workings - of the cart. - */ - CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, - const GUI::Font& nfont, int x, int y, int w, int h) override - { - return new CartridgeDASHWidget(boss, lfont, nfont, x, y, w, h, *this); - } - #endif - - public: - /** - Get the byte at the specified address - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - - private: - bool bankRAM(uInt8 bank); // switch a RAM bank - bool bankROM(uInt8 bank); // switch a ROM bank - - void bankRAMSlot(uInt16 bank); // switch in a 512b RAM slot (lower or upper 1/2 bank) - void bankROMSlot(uInt16 bank); // switch in a 512b RAM slot (read or write port) - - void initializeBankState(); // set all banks according to current bankInUse state - - // We have an array that indicates for each of the 8 512 byte areas of the address space, which ROM/RAM - // bank is used in that area. ROM switches 1K so occupies 2 successive entries for each switch. RAM occupies - // two as well, one 512 byte for read and one for write. The RAM locations are +0x800 apart, and the ROM - // are consecutive. This allows us to determine on a read/write exactly where the data is. - - static constexpr uInt16 BANK_UNDEFINED = 0x8000; // bank is undefined and inaccessible - std::array bankInUse; // bank being used for ROM/RAM (eight 512 byte areas) - std::array segmentInUse; // set by bank methods, to know which hotspot was accessed - - static constexpr uInt16 BANK_SWITCH_HOTSPOT_RAM = 0x3E; // writes to this address cause bankswitching - static constexpr uInt16 BANK_SWITCH_HOTSPOT_ROM = 0x3F; // writes to this address cause bankswitching - - static constexpr uInt8 BANK_BITS = 6; // # bits for bank - static constexpr uInt8 BIT_BANK_MASK = (1 << BANK_BITS) - 1; // mask for those bits - static constexpr uInt16 BITMASK_LOWERUPPER = 0x100; // flags lower or upper section of bank (1==upper) - static constexpr uInt16 BITMASK_ROMRAM = 0x200; // flags ROM or RAM bank switching (1==RAM) - - static constexpr uInt16 MAXIMUM_BANK_COUNT = (1 << BANK_BITS); - static constexpr uInt16 RAM_BANK_TO_POWER = 9; // 2^n = 512 - static constexpr uInt16 RAM_BANK_SIZE = (1 << RAM_BANK_TO_POWER); - static constexpr uInt16 BITMASK_RAM_BANK = (RAM_BANK_SIZE - 1); - static constexpr uInt32 RAM_TOTAL_SIZE = MAXIMUM_BANK_COUNT * RAM_BANK_SIZE; - - static constexpr uInt16 ROM_BANK_TO_POWER = 10; // 2^n = 1024 - static constexpr uInt16 ROM_BANK_SIZE = (1 << ROM_BANK_TO_POWER); - static constexpr uInt16 BITMASK_ROM_BANK = (ROM_BANK_SIZE - 1); - - static constexpr uInt16 ROM_BANK_COUNT = 64; - - static constexpr uInt16 RAM_WRITE_OFFSET = 0x800; - - ByteBuffer myImage; // Pointer to a dynamically allocated ROM image of the cartridge - size_t mySize{0}; // Size of the ROM image - std::array myRAM; - - private: - // Following constructors and assignment operators not supported - CartridgeDASH() = delete; - CartridgeDASH(const CartridgeDASH&) = delete; - CartridgeDASH(CartridgeDASH&&) = delete; - CartridgeDASH& operator=(const CartridgeDASH&) = delete; - CartridgeDASH& operator=(CartridgeDASH&&) = delete; -}; - -#endif diff --git a/src/emucore/CartDF.cxx b/src/emucore/CartDF.cxx index d837f9631..58206a3b5 100644 --- a/src/emucore/CartDF.cxx +++ b/src/emucore/CartDF.cxx @@ -20,142 +20,22 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDF::CartridgeDF(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDF::reset() +bool CartridgeDF::checkSwitchBank(uInt16 address, uInt8) { - initializeStartBank(1); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDF::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeDF::peek(uInt16 address) -{ - address &= 0x0FFF; + address &= ROM_MASK; // Switch banks if necessary if((address >= 0x0FC0) && (address <= 0x0FDF)) + { bank(address - 0x0FC0); - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDF::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FC0) && (address <= 0x0FDF)) - bank(address - 0x0FC0); - + return true; + } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDF::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FC0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDF::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDF::bankCount() const -{ - return 32; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDF::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeDF::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDF::save(Serializer& out) const -{ - try - { - out.putInt(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeDF::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDF::load(Serializer& in) -{ - try - { - myBankOffset = in.getInt(); - } - catch(...) - { - cerr << "ERROR: CartridgeDF::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartDF.hxx b/src/emucore/CartDF.hxx index 04804b957..18d0f2489 100644 --- a/src/emucore/CartDF.hxx +++ b/src/emucore/CartDF.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartDFWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; There are 32 4K banks (total of 128K ROM). Accessing $1FC0 - $1FDF switches to each bank. - @author Mike Saarna + @author Mike Saarna, Thomas Jentzsch */ -class CartridgeDF : public Cartridge +class CartridgeDF : public CartridgeEnhanced { friend class CartridgeDFWidget; @@ -45,77 +45,13 @@ class CartridgeDF : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeDF(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 128_KB); virtual ~CartridgeDF() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,29 +71,12 @@ class CartridgeDF : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 128K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1FC0; } + + uInt16 getStartBank() const override { return 15; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartDFSC.cxx b/src/emucore/CartDFSC.cxx index 1df44e638..4dafe3bb7 100644 --- a/src/emucore/CartDFSC.cxx +++ b/src/emucore/CartDFSC.cxx @@ -20,198 +20,9 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDFSC::CartridgeDFSC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeDF(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(15); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeDFSC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeDFSC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FC0) && (address <= 0x0FDF)) - bank(address - 0x0FC0); - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDFSC::poke(uInt16 address, uInt8 value) -{ - uInt16 pokeAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FC0) && (address <= 0x0FDF)) - { - bank(address - 0x0FC0); - return false; - } - - if(!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], pokeAddress, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, pokeAddress, value); - myRamWriteAccess = pokeAddress; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDFSC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FC0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1FC0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDFSC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDFSC::bankCount() const -{ - return 32; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDFSC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeDFSC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDFSC::save(Serializer& out) const -{ - try - { - out.putInt(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeDFSC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDFSC::load(Serializer& in) -{ - try - { - myBankOffset = in.getInt(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeDFSC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; } diff --git a/src/emucore/CartDFSC.hxx b/src/emucore/CartDFSC.hxx index af35f476b..efc6d30e8 100644 --- a/src/emucore/CartDFSC.hxx +++ b/src/emucore/CartDFSC.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartDF.hxx" #ifdef DEBUGGER_SUPPORT #include "CartDFSCWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; Accessing $1FC0 - $1FDF switches to each bank. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class CartridgeDFSC : public Cartridge +class CartridgeDFSC : public CartridgeDF { friend class CartridgeDFSCWidget; @@ -45,77 +45,13 @@ class CartridgeDFSC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeDFSC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 128_KB); virtual ~CartridgeDFSC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,34 +71,11 @@ class CartridgeDFSC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 128K ROM image of the cartridge - std::array myImage; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; - - private: +private: // Following constructors and assignment operators not supported CartridgeDFSC() = delete; CartridgeDFSC(const CartridgeDFSC&) = delete; diff --git a/src/emucore/CartDPC.cxx b/src/emucore/CartDPC.cxx index e382c8707..c77aacd8a 100644 --- a/src/emucore/CartDPC.cxx +++ b/src/emucore/CartDPC.cxx @@ -15,52 +15,45 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "Settings.hxx" #include "System.hxx" #include "AudioSettings.hxx" #include "CartDPC.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeDPC::CartridgeDPC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeF8(image, size, md5, settings, bsSize) { - // Make a copy of the entire image - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(8_KB); - - // Pointer to the program ROM (8K @ 0 byte offset) - myProgramImage = myImage.data(); - - // Pointer to the display ROM (2K @ 8K offset) - myDisplayImage = myProgramImage + 8_KB; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeDPC::reset() { + CartridgeEnhanced::reset(); + myAudioCycles = 0; myFractionalClocks = 0.0; - - // Upon reset we switch to the startup bank - initializeStartBank(1); - bank(startBank()); - myDpcPitch = mySettings.getInt(AudioSettings::SETTING_DPC_PITCH); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeDPC::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); + + myRomOffset = 0x80; + + // Pointer to the display ROM (2K @ 8K offset) + myDisplayImage = myImage.get() + 8_KB; + + createRomAccessArrays(8_KB); // Set the page accessing method for the DPC reading & writing pages System::PageAccess access(this, System::PageAccessType::READWRITE); for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); - - // Install pages for the startup bank - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -128,12 +121,15 @@ inline void CartridgeDPC::updateMusicModeDataFetchers() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeDPC::peek(uInt16 address) { + uInt16 peekAddress = address; + address &= 0x0FFF; // In debugger/bank-locked mode, we ignore all hotspots and in general // anything that can change the internal state of the cart if(bankLocked()) - return myProgramImage[myBankOffset + address]; + return myImage[myCurrentSegOffset[0] + address]; + // Clock the random number generator. This should be done for every // cartridge access, however, we're only doing it for the DPC and @@ -232,30 +228,14 @@ uInt8 CartridgeDPC::peek(uInt16 address) return result; } else - { - // Switch banks if necessary - switch(address) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0FF9: - // Set the current bank to the upper 4k bank - bank(1); - break; - - default: - break; - } - return myProgramImage[myBankOffset + address]; - } + return CartridgeEnhanced::peek(peekAddress); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeDPC::poke(uInt16 address, uInt8 value) { + uInt16 pokeAddress = address; + address &= 0x0FFF; // Clock the random number generator. This should be done for every @@ -338,98 +318,31 @@ bool CartridgeDPC::poke(uInt16 address, uInt8 value) } } else - { - // Switch banks if necessary - switch(address) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - break; + CartridgeEnhanced::poke(pokeAddress, value); - case 0x0FF9: - // Set the current bank to the upper 4k bank - bank(1); - break; - - default: - break; - } - } return false; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDPC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1080; addr < static_cast(0x1FF8U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myProgramImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDPC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDPC::bankCount() const -{ - return 2; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeDPC::patch(uInt16 address, uInt8 value) { - address &= 0x0FFF; - // For now, we ignore attempts to patch the DPC address space - if(address >= 0x0080) + if((address & ADDR_MASK) >= ROM_OFFSET + myRomOffset) { - myProgramImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; + return CartridgeEnhanced::patch(address, value); } else return false; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeDPC::getImage(size_t& size) const -{ - size = mySize; - return myImage.data(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeDPC::save(Serializer& out) const { + if(!CartridgeEnhanced::save(out)) + return false; + try { - // Indicates which bank is currently active - out.putShort(myBankOffset); - // The top registers for the data fetchers out.putByteArray(myTops.data(), myTops.size()); @@ -464,11 +377,11 @@ bool CartridgeDPC::save(Serializer& out) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeDPC::load(Serializer& in) { + if(!CartridgeEnhanced::load(in)) + return false; + try { - // Indicates which bank is currently active - myBankOffset = in.getShort(); - // The top registers for the data fetchers in.getByteArray(myTops.data(), myTops.size()); @@ -497,9 +410,5 @@ bool CartridgeDPC::load(Serializer& in) cerr << "ERROR: CartridgeDPC::load" << endl; return false; } - - // Now, go to the current bank - bank(myBankOffset >> 12); - return true; } diff --git a/src/emucore/CartDPC.hxx b/src/emucore/CartDPC.hxx index 330a0086a..4d90fb140 100644 --- a/src/emucore/CartDPC.hxx +++ b/src/emucore/CartDPC.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGE_DPC_HXX #define CARTRIDGE_DPC_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartF8.hxx" #ifdef DEBUGGER_SUPPORT #include "CartDPCWidget.hxx" #endif @@ -35,9 +32,9 @@ class System; For complete details on the DPC chip see David P. Crane's United States Patent Number 4,644,495. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeDPC : public Cartridge +class CartridgeDPC : public CartridgeF8 { friend class CartridgeDPCWidget; @@ -49,17 +46,13 @@ class CartridgeDPC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeDPC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 10_KB); virtual ~CartridgeDPC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -69,23 +62,9 @@ class CartridgeDPC : public Cartridge void install(System& system) override; /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system + Reset device to its power-on state */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; + void reset() override; /** Patch the cartridge ROM. @@ -96,14 +75,6 @@ class CartridgeDPC : public Cartridge */ bool patch(uInt16 address, uInt8 value) override; - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - /** Save the current state of this cart to the given Serializer. @@ -127,6 +98,11 @@ class CartridgeDPC : public Cartridge */ string name() const override { return "CartridgeDPC"; } + /** + Change the DPC audio pitch + + @param pitch The new pitch value + */ void setDpcPitch(double pitch) { myDpcPitch = pitch; } #ifdef DEBUGGER_SUPPORT @@ -171,15 +147,6 @@ class CartridgeDPC : public Cartridge void updateMusicModeDataFetchers(); private: - // The ROM image - std::array myImage; - - // (Actual) Size of the ROM image - size_t mySize{0}; - - // Pointer to the 8K program ROM image of the cartridge - uInt8* myProgramImage{nullptr}; - // Pointer to the 2K display ROM image of the cartridge uInt8* myDisplayImage{nullptr}; @@ -207,9 +174,6 @@ class CartridgeDPC : public Cartridge // Fractional DPC music OSC clocks unused during the last update double myFractionalClocks{0.0}; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; - // DPC pitch double myDpcPitch{0.0}; diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index 5758479d2..a867f0a91 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -29,17 +29,18 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings) : Cartridge(settings, md5), - mySize(std::min(size, myImage.size())) + myImage(make_unique(32_KB)), + mySize(std::min(size, 32_KB)) { - // Image is always 32K, but in the case of ROM > 29K, the image is + // Image is always 32K, but in the case of ROM < 32K, the image is // copied to the end of the buffer - if(mySize < myImage.size()) - myImage.fill(0); - std::copy_n(image.get(), size, myImage.begin() + (myImage.size() - mySize)); - createCodeAccessBase(24_KB); + if(mySize < 32_KB) + std::fill_n(myImage.get(), mySize, 0); + std::copy_n(image.get(), size, myImage.get() + (32_KB - mySize)); + createRomAccessArrays(24_KB); // Pointer to the program ROM (24K @ 3K offset; ignore first 3K) - myProgramImage = myImage.data() + 3_KB; + myProgramImage = myImage.get() + 3_KB; // Pointer to the display RAM myDisplayImage = myDPCRAM.data() + 3_KB; @@ -50,16 +51,27 @@ CartridgeDPCPlus::CartridgeDPCPlus(const ByteBuffer& image, size_t size, // Create Thumbulator ARM emulator bool devSettings = settings.getBool("dev.settings"); myThumbEmulator = make_unique - (reinterpret_cast(myImage.data()), + (reinterpret_cast(myImage.get()), reinterpret_cast(myDPCRAM.data()), - static_cast(myImage.size()), + static_cast(32_KB), devSettings ? settings.getBool("dev.thumb.trapfatal") : false, Thumbulator::ConfigureFor::DPCplus, this); - // Currently only one known DPC+ ARM driver exhibits a problem - // with the default mask to use for DFxFRACLOW - if(MD5::hash(image, 3_KB) == "8dd73b44fd11c488326ce507cbeb19d1") + // Currently 4 DPC+ driver versions have been identified: + // 17884ec14f9b1d06fe8d617a1fbdcf47 Jitter Encore Compatible + // 5f80b5a5adbe483addc3f6e6f1b472f8 Stable Encore Compatible + // 8dd73b44fd11c488326ce507cbeb19d1 Stable NOT Encore Compatible + // b328dbdf787400c0f0e2b88b425872a5 Jitter Encore Compatible + // + // Jitter/Stable refers to the appearance of the playfield in bB games if + // the DFxFRACINC registers are not updated before every drawscreen. + // + // The default mask for DFxFRACLOW implements the Jitter behavior. This + // changes the mask to implement the Stable behavior. + myDriverMD5 = MD5::hash(image, 3_KB); + if(myDriverMD5 == "5f80b5a5adbe483addc3f6e6f1b472f8" || + myDriverMD5 == "8dd73b44fd11c488326ce507cbeb19d1" ) myFractionalLowMask = 0x0F0000; setInitialState(); @@ -580,7 +592,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeDPCPlus::bank(uInt16 bank) +bool CartridgeDPCPlus::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; @@ -593,7 +605,9 @@ bool CartridgeDPCPlus::bank(uInt16 bank) // Map Program ROM image into the system for(uInt16 addr = 0x1080; addr < 0x2000; addr += System::PAGE_SIZE) { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romAccessBase = &myRomAccessBase[myBankOffset + (addr & 0x0FFF)]; + access.romPeekCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF)]; + access.romPokeCounter = &myRomAccessCounter[myBankOffset + (addr & 0x0FFF) + 24_KB]; mySystem->setPageAccess(addr, access); } return myBankChanged = true; @@ -606,7 +620,7 @@ uInt16 CartridgeDPCPlus::getBank(uInt16) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeDPCPlus::bankCount() const +uInt16 CartridgeDPCPlus::romBankCount() const { return 6; } @@ -627,10 +641,10 @@ bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeDPCPlus::getImage(size_t& size) const +const ByteBuffer& CartridgeDPCPlus::getImage(size_t& size) const { size = mySize; - return myImage.data() + (myImage.size() - mySize); + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartDPCPlus.hxx b/src/emucore/CartDPCPlus.hxx index cc2997396..393fd35be 100644 --- a/src/emucore/CartDPCPlus.hxx +++ b/src/emucore/CartDPCPlus.hxx @@ -86,9 +86,12 @@ class CartridgeDPCPlus : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -100,7 +103,7 @@ class CartridgeDPCPlus : public Cartridge /** Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -115,9 +118,9 @@ class CartridgeDPCPlus : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -215,7 +218,7 @@ class CartridgeDPCPlus : public Cartridge private: // The ROM image and size - std::array myImage; + ByteBuffer myImage; size_t mySize{0}; // Pointer to the 24K program ROM image of the cartridge @@ -287,6 +290,10 @@ class CartridgeDPCPlus : public Cartridge // Indicates the offset into the ROM image (aligns to current bank) uInt16 myBankOffset{0}; + // MD5 value of the 3K DPC+ driver. Used to determine which mask to use, + // and shown in the Cartridge tab of the debugger + string myDriverMD5; + // Older DPC+ driver code had different behaviour wrt the mask used // to retrieve 'DFxFRACLOW' (fractional data pointer low byte) // ROMs built with an old DPC+ driver and using the newer mask can diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx index b6e6f150a..0ecc6e82e 100644 --- a/src/emucore/CartDetector.cxx +++ b/src/emucore/CartDetector.cxx @@ -16,341 +16,17 @@ //============================================================================ #include "bspf.hxx" -#include "Cart.hxx" -#include "Cart0840.hxx" -#include "Cart2K.hxx" -#include "Cart3E.hxx" -#include "Cart3EPlus.hxx" -#include "Cart3F.hxx" -#include "Cart4A50.hxx" -#include "Cart4K.hxx" -#include "Cart4KSC.hxx" -#include "CartAR.hxx" -#include "CartBF.hxx" -#include "CartBFSC.hxx" -#include "CartBUS.hxx" -#include "CartCDF.hxx" -#include "CartCM.hxx" -#include "CartCTY.hxx" -#include "CartCV.hxx" -#include "CartCVPlus.hxx" -#include "CartDASH.hxx" -#include "CartDF.hxx" -#include "CartDFSC.hxx" -#include "CartDPC.hxx" -#include "CartDPCPlus.hxx" -#include "CartE0.hxx" -#include "CartE7.hxx" -#include "CartE78K.hxx" -#include "CartEF.hxx" -#include "CartEFSC.hxx" -#include "CartF0.hxx" -#include "CartF4.hxx" -#include "CartF4SC.hxx" -#include "CartF6.hxx" -#include "CartF6SC.hxx" -#include "CartF8.hxx" -#include "CartF8SC.hxx" -#include "CartFA.hxx" -#include "CartFA2.hxx" -#include "CartFC.hxx" -#include "CartFE.hxx" -#include "CartMDM.hxx" -#include "CartSB.hxx" -#include "CartUA.hxx" -#include "CartWD.hxx" -#include "CartX07.hxx" -#include "MD5.hxx" -#include "Props.hxx" #include "Logger.hxx" #include "CartDetector.hxx" -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unique_ptr CartDetector::create(const FilesystemNode& file, - const ByteBuffer& image, size_t size, string& md5, - const string& propertiesType, Settings& settings) -{ - unique_ptr cartridge; - Bankswitch::Type type = Bankswitch::nameToType(propertiesType), - detectedType = type; - string id; - - // Collect some info about the ROM - ostringstream buf; - - // First inspect the file extension itself - // If a valid type is found, it will override the one passed into this method - Bankswitch::Type typeByName = Bankswitch::typeFromExtension(file); - if(typeByName != Bankswitch::Type::_AUTO) - type = detectedType = typeByName; - - // See if we should try to auto-detect the cartridge type - // If we ask for extended info, always do an autodetect - if(type == Bankswitch::Type::_AUTO || settings.getBool("rominfo")) - { - detectedType = autodetectType(image, size); - if(type != Bankswitch::Type::_AUTO && type != detectedType) - cerr << "Auto-detection not consistent: " - << Bankswitch::typeToName(type) << ", " - << Bankswitch::typeToName(detectedType) << endl; - - type = detectedType; - buf << Bankswitch::typeToName(type) << "*"; - } - else - buf << Bankswitch::typeToName(type); - - // Check for multicart first; if found, get the correct part of the image - switch(type) - { - case Bankswitch::Type::_2IN1: - // Make sure we have a valid sized image - if(size == 2*2_KB || size == 2*4_KB || size == 2*8_KB || size == 2*16_KB) - { - cartridge = - createFromMultiCart(image, size, 2, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_4IN1: - // Make sure we have a valid sized image - if(size == 4*2_KB || size == 4*4_KB || size == 4*8_KB) - { - cartridge = - createFromMultiCart(image, size, 4, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_8IN1: - // Make sure we have a valid sized image - if(size == 8*2_KB || size == 8*4_KB || size == 8*8_KB) - { - cartridge = - createFromMultiCart(image, size, 8, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_16IN1: - // Make sure we have a valid sized image - if(size == 16*2_KB || size == 16*4_KB || size == 16*8_KB) - { - cartridge = - createFromMultiCart(image, size, 16, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_32IN1: - // Make sure we have a valid sized image - if(size == 32*2_KB || size == 32*4_KB) - { - cartridge = - createFromMultiCart(image, size, 32, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_64IN1: - // Make sure we have a valid sized image - if(size == 64*2_KB || size == 64*4_KB) - { - cartridge = - createFromMultiCart(image, size, 64, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - case Bankswitch::Type::_128IN1: - // Make sure we have a valid sized image - if(size == 128*2_KB || size == 128*4_KB) - { - cartridge = - createFromMultiCart(image, size, 128, md5, detectedType, id, settings); - buf << id; - } - else - throw runtime_error("Invalid cart size for type '" + - Bankswitch::typeToName(type) + "'"); - break; - - default: - cartridge = createFromImage(image, size, detectedType, md5, settings); - break; - } - - if(size < 1_KB) - buf << " (" << size << "B) "; - else - buf << " (" << (size/1_KB) << "K) "; - - cartridge->setAbout(buf.str(), Bankswitch::typeToName(type), id); - - return cartridge; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unique_ptr -CartDetector::createFromMultiCart(const ByteBuffer& image, size_t& size, - uInt32 numroms, string& md5, Bankswitch::Type type, string& id, Settings& settings) -{ - // Get a piece of the larger image - uInt32 i = settings.getInt("romloadcount"); - size /= numroms; - ByteBuffer slice = make_unique(size); - std::copy_n(image.get()+i*size, size, slice.get()); - - // We need a new md5 and name - md5 = MD5::hash(slice, uInt32(size)); // FIXME - ostringstream buf; - buf << " [G" << (i+1) << "]"; - id = buf.str(); - - // Move to the next game the next time this ROM is loaded - settings.setValue("romloadcount", (i+1)%numroms); - - if(size <= 2_KB) type = Bankswitch::Type::_2K; - else if(size == 4_KB) type = Bankswitch::Type::_4K; - else if(size == 8_KB) type = Bankswitch::Type::_F8; - else /* default */ type = Bankswitch::Type::_4K; - - return createFromImage(slice, size, type, md5, settings); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unique_ptr -CartDetector::createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, - const string& md5, Settings& settings) -{ - // We should know the cart's type by now so let's create it - switch(type) - { - case Bankswitch::Type::_0840: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_2K: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_3E: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_3EP: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_3F: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_4A50: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_4K: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_4KSC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_AR: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_BF: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_BFSC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_BUS: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_CDF: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_CM: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_CTY: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_CV: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_CVP: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_DASH: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_DF: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_DFSC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_DPC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_DPCP: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_E0: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_E7: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_E78K: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_EF: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_EFSC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F0: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F4: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F4SC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F6: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F6SC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F8: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_F8SC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_FA: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_FA2: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_FC: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_FE: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_MDM: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_UA: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_UASW: - return make_unique(image, size, md5, settings, true); - case Bankswitch::Type::_SB: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_WD: - case Bankswitch::Type::_WDSW: - return make_unique(image, size, md5, settings); - case Bankswitch::Type::_X07: - return make_unique(image, size, md5, settings); - default: - return nullptr; // The remaining types have already been handled - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t size) { // Guess type based on size Bankswitch::Type type = Bankswitch::Type::_AUTO; - if(isProbablyCVPlus(image, size)) - { - type = Bankswitch::Type::_CVP; - } - else if((size % 8448) == 0 || size == 6144) + if((size % 8448) == 0 || size == 6144) { type = Bankswitch::Type::_AR; } @@ -381,8 +57,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si { 0x8D, 0xF9, 0x1F }, // STA $1FF9 { 0x8D, 0xF9, 0xFF } // STA $FFF9 }; - bool f8 = searchForBytes(image.get(), size, signature[0], 3, 2) || - searchForBytes(image.get(), size, signature[1], 3, 2); + bool f8 = searchForBytes(image, size, signature[0], 3, 2) || + searchForBytes(image, size, signature[1], 3, 2); if(isProbablySC(image, size)) type = Bankswitch::Type::_F8SC; @@ -390,6 +66,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_4K; else if(isProbablyE0(image, size)) type = Bankswitch::Type::_E0; + else if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) @@ -429,6 +107,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_E7; else if (isProbablyFC(image, size)) type = Bankswitch::Type::_FC; + else if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; /* no known 16K 3F ROMS @@ -455,6 +135,8 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_CTY; else if(isProbablySC(image, size)) type = Bankswitch::Type::_F4SC; + else if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) @@ -481,7 +163,9 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si } else if(size == 64_KB) { - if(isProbably3E(image, size)) + if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; + else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; @@ -496,7 +180,9 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si } else if(size == 128_KB) { - if(isProbably3E(image, size)) + if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; + else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbablyDF(image, size, type)) ; // type has been set directly in the function @@ -504,12 +190,14 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si type = Bankswitch::Type::_3F; else if(isProbably4A50(image, size)) type = Bankswitch::Type::_4A50; - else if(isProbablySB(image, size)) + else /*if(isProbablySB(image, size))*/ type = Bankswitch::Type::_SB; } else if(size == 256_KB) { - if(isProbably3E(image, size)) + if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; + else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbablyBF(image, size, type)) ; // type has been set directly in the function @@ -518,26 +206,38 @@ Bankswitch::Type CartDetector::autodetectType(const ByteBuffer& image, size_t si else /*if(isProbablySB(image, size))*/ type = Bankswitch::Type::_SB; } - else // what else can we do? + else if(size == 512_KB) { - if(isProbably3E(image, size)) + if(isProbablyTVBoy(image, size)) + type = Bankswitch::Type::_TVBOY; + else if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; + else if(isProbably3E(image, size)) + type = Bankswitch::Type::_3E; + else if(isProbably3F(image, size)) + type = Bankswitch::Type::_3F; + } + else // what else can we do? + { + if(isProbably3EX(image, size)) + type = Bankswitch::Type::_3EX; + else if(isProbably3E(image, size)) type = Bankswitch::Type::_3E; else if(isProbably3F(image, size)) type = Bankswitch::Type::_3F; - else - type = Bankswitch::Type::_4K; // Most common bankswitching type } // Variable sized ROM formats are independent of image size and come last - if(isProbablyDASH(image, size)) - type = Bankswitch::Type::_DASH; - else if(isProbably3EPlus(image, size)) + if(isProbably3EPlus(image, size)) type = Bankswitch::Type::_3EP; else if(isProbablyMDM(image, size)) type = Bankswitch::Type::_MDM; - ostringstream ss; + // If we get here and autodetection failed, then we force '4K' + if(type == Bankswitch::Type::_AUTO) + type = Bankswitch::Type::_4K; // Most common bankswitching type + ostringstream ss; ss << "Bankswitching type '" << Bankswitch::typeToDesc(type) << "' detected"; Logger::debug(ss.str()); @@ -550,26 +250,25 @@ bool CartDetector::searchForBytes(const uInt8* image, size_t imagesize, uInt32 minhits) { uInt32 count = 0; + for(uInt32 i = 0; i < imagesize - sigsize; ++i) { - uInt32 matches = 0; - for(uInt32 j = 0; j < sigsize; ++j) + uInt32 j; + + for(j = 0; j < sigsize; ++j) { - if(image[i+j] == signature[j]) - ++matches; - else + if(image[i + j] != signature[j]) break; } - if(matches == sigsize) + if(j == sigsize) { - ++count; + if(++count == minhits) + break; i += sigsize; // skip past this signature 'window' entirely } - if(count >= minhits) - break; } - return (count >= minhits); + return (count == minhits); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -598,10 +297,10 @@ bool CartDetector::isProbablyARM(const ByteBuffer& image, size_t size) { 0xA0, 0xC1, 0x1F, 0xE0 }, { 0x00, 0x80, 0x02, 0xE0 } }; - if(searchForBytes(image.get(), std::min(size, 1_KB), signature[0], 4, 1)) + if(searchForBytes(image, std::min(size, 1_KB), signature[0], 4)) return true; else - return searchForBytes(image.get(), std::min(size, 1_KB), signature[1], 4, 1); + return searchForBytes(image, std::min(size, 1_KB), signature[1], 4); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -615,7 +314,7 @@ bool CartDetector::isProbably0840(const ByteBuffer& image, size_t size) { 0x2C, 0x00, 0x08 } // BIT $0800 }; for(uInt32 i = 0; i < 3; ++i) - if(searchForBytes(image.get(), size, signature1[i], 3, 2)) + if(searchForBytes(image, size, signature1[i], 3, 2)) return true; uInt8 signature2[2][4] = { @@ -623,7 +322,7 @@ bool CartDetector::isProbably0840(const ByteBuffer& image, size_t size) { 0x0C, 0xFF, 0x0F, 0x4C } // NOP $0FFF; JMP ... }; for(uInt32 i = 0; i < 2; ++i) - if(searchForBytes(image.get(), size, signature2[i], 4, 2)) + if(searchForBytes(image, size, signature2[i], 4, 2)) return true; return false; @@ -632,11 +331,24 @@ bool CartDetector::isProbably0840(const ByteBuffer& image, size_t size) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbably3E(const ByteBuffer& image, size_t size) { - // 3E cart bankswitching is triggered by storing the bank number - // in address 3E using 'STA $3E', commonly followed by an - // immediate mode LDA - uInt8 signature[] = { 0x85, 0x3E, 0xA9, 0x00 }; // STA $3E; LDA #$00 - return searchForBytes(image.get(), size, signature, 4, 1); + // 3E cart RAM bankswitching is triggered by storing the bank number + // in address 3E using 'STA $3E', ROM bankswitching is triggered by + // storing the bank number in address 3F using 'STA $3F'. + // We expect the latter will be present at least 2 times, since there + // are at least two banks + + uInt8 signature1[] = { 0x85, 0x3E }; // STA $3E + uInt8 signature2[] = { 0x85, 0x3F }; // STA $3F + return searchForBytes(image, size, signature1, 2) + && searchForBytes(image, size, signature2, 2, 2); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDetector::isProbably3EX(const ByteBuffer& image, size_t size) +{ + // 3EX cart have at least 2 occurrences of the string "3EX" + uInt8 _3EX[] = { '3', 'E', 'X'}; + return searchForBytes(image, size, _3EX, 3, 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -644,7 +356,7 @@ bool CartDetector::isProbably3EPlus(const ByteBuffer& image, size_t size) { // 3E+ cart is identified key 'TJ3E' in the ROM uInt8 tj3e[] = { 'T', 'J', '3', 'E' }; - return searchForBytes(image.get(), size, tj3e, 4, 1); + return searchForBytes(image, size, tj3e, 4); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -655,7 +367,7 @@ bool CartDetector::isProbably3F(const ByteBuffer& image, size_t size) // We expect it will be present at least 2 times, since there are // at least two banks uInt8 signature[] = { 0x85, 0x3F }; // STA $3F - return searchForBytes(image.get(), size, signature, 2, 2); + return searchForBytes(image, size, signature, 2, 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -701,12 +413,12 @@ bool CartDetector::isProbablyBF(const ByteBuffer& image, size_t size, // This signature is attributed to "RevEng" of AtariAge uInt8 bf[] = { 'B', 'F', 'B', 'F' }; uInt8 bfsc[] = { 'B', 'F', 'S', 'C' }; - if(searchForBytes(image.get()+size-8, 8, bf, 4, 1)) + if(searchForBytes(image.get()+size-8, 8, bf, 4)) { type = Bankswitch::Type::_BF; return true; } - else if(searchForBytes(image.get()+size-8, 8, bfsc, 4, 1)) + else if(searchForBytes(image.get()+size-8, 8, bfsc, 4)) { type = Bankswitch::Type::_BFSC; return true; @@ -722,7 +434,7 @@ bool CartDetector::isProbablyBUS(const ByteBuffer& image, size_t size) // Note: all Harmony/Melody custom drivers also contain the value // 0x10adab1e (LOADABLE) if needed for future improvement uInt8 bus[] = { 'B', 'U', 'S'}; - return searchForBytes(image.get(), size, bus, 3, 2); + return searchForBytes(image, size, bus, 3, 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -732,14 +444,14 @@ bool CartDetector::isProbablyCDF(const ByteBuffer& image, size_t size) // Note: all Harmony/Melody custom drivers also contain the value // 0x10adab1e (LOADABLE) if needed for future improvement uInt8 cdf[] = { 'C', 'D', 'F' }; - return searchForBytes(image.get(), size, cdf, 3, 3); + return searchForBytes(image, size, cdf, 3, 3); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablyCTY(const ByteBuffer& image, size_t size) { uInt8 lenin[] = { 'L', 'E', 'N', 'I', 'N' }; - return searchForBytes(image.get(), size, lenin, 5, 1); + return searchForBytes(image, size, lenin, 5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -751,28 +463,10 @@ bool CartDetector::isProbablyCV(const ByteBuffer& image, size_t size) { 0x9D, 0xFF, 0xF3 }, // STA $F3FF.X { 0x99, 0x00, 0xF4 } // STA $F400.Y }; - if(searchForBytes(image.get(), size, signature[0], 3, 1)) + if(searchForBytes(image, size, signature[0], 3)) return true; else - return searchForBytes(image.get(), size, signature[1], 3, 1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartDetector::isProbablyCVPlus(const ByteBuffer& image, size_t) -{ - // CV+ cart is identified key 'commavidplus' @ $04 in the ROM - // We inspect only this area to speed up the search - uInt8 cvp[12] = { 'c', 'o', 'm', 'm', 'a', 'v', 'i', 'd', - 'p', 'l', 'u', 's' }; - return searchForBytes(image.get()+4, 24, cvp, 12, 1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartDetector::isProbablyDASH(const ByteBuffer& image, size_t size) -{ - // DASH cart is identified key 'TJAD' in the ROM - uInt8 tjad[] = { 'T', 'J', 'A', 'D' }; - return searchForBytes(image.get(), size, tjad, 4, 1); + return searchForBytes(image, size, signature[1], 3); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -784,12 +478,12 @@ bool CartDetector::isProbablyDF(const ByteBuffer& image, size_t size, // This signature is attributed to "RevEng" of AtariAge uInt8 df[] = { 'D', 'F', 'D', 'F' }; uInt8 dfsc[] = { 'D', 'F', 'S', 'C' }; - if(searchForBytes(image.get()+size-8, 8, df, 4, 1)) + if(searchForBytes(image.get()+size-8, 8, df, 4)) { type = Bankswitch::Type::_DF; return true; } - else if(searchForBytes(image.get()+size-8, 8, dfsc, 4, 1)) + else if(searchForBytes(image.get()+size-8, 8, dfsc, 4)) { type = Bankswitch::Type::_DFSC; return true; @@ -805,7 +499,7 @@ bool CartDetector::isProbablyDPCplus(const ByteBuffer& image, size_t size) // Note: all Harmony/Melody custom drivers also contain the value // 0x10adab1e (LOADABLE) if needed for future improvement uInt8 dpcp[] = { 'D', 'P', 'C', '+' }; - return searchForBytes(image.get(), size, dpcp, 4, 2); + return searchForBytes(image, size, dpcp, 4, 2); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -828,7 +522,7 @@ bool CartDetector::isProbablyE0(const ByteBuffer& image, size_t size) { 0xAD, 0xF3, 0xBF } // LDA $BFF3 }; for(uInt32 i = 0; i < 8; ++i) - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) return true; return false; @@ -853,7 +547,7 @@ bool CartDetector::isProbablyE7(const ByteBuffer& image, size_t size) { 0x8D, 0xE7, 0x1F } // STA $1FE7 }; for(uInt32 i = 0; i < 7; ++i) - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) return true; return false; @@ -872,7 +566,7 @@ bool CartDetector::isProbablyE78K(const ByteBuffer& image, size_t size) { 0xAD, 0xE6, 0xFF }, // LDA $FFE6 }; for(uInt32 i = 0; i < 3; ++i) - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) return true; return false; @@ -886,12 +580,12 @@ bool CartDetector::isProbablyEF(const ByteBuffer& image, size_t size, // This signature is attributed to "RevEng" of AtariAge uInt8 efef[] = { 'E', 'F', 'E', 'F' }; uInt8 efsc[] = { 'E', 'F', 'S', 'C' }; - if(searchForBytes(image.get()+size-8, 8, efef, 4, 1)) + if(searchForBytes(image.get()+size-8, 8, efef, 4)) { type = Bankswitch::Type::_EF; return true; } - else if(searchForBytes(image.get()+size-8, 8, efsc, 4, 1)) + else if(searchForBytes(image.get()+size-8, 8, efsc, 4)) { type = Bankswitch::Type::_EFSC; return true; @@ -909,7 +603,7 @@ bool CartDetector::isProbablyEF(const ByteBuffer& image, size_t size, }; for(uInt32 i = 0; i < 4; ++i) { - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) { isEF = true; break; @@ -935,7 +629,7 @@ bool CartDetector::isProbablyFA2(const ByteBuffer& image, size_t) // file sizes // 32K version has all zeros in 29K-32K area - for(uInt32 i = 29_KB; i < 32_KB; ++i) + for(size_t i = 29_KB; i < 32_KB; ++i) if(image[i] != 0) return false; @@ -951,14 +645,13 @@ bool CartDetector::isProbablyFC(const ByteBuffer& image, size_t size) { 0x8d, 0xf8, 0xff, 0x8d, 0xfc, 0xff }, // STA $FFF8, STA $FFFC Surf's Up (4K) { 0x8c, 0xf9, 0xff, 0xad, 0xfc, 0xff } // STY $FFF9, LDA $FFFC 3-D Havoc }; - for (uInt32 i = 0; i < 3; ++i) - if (searchForBytes(image.get(), size, signature[i], 6, 1)) + for(uInt32 i = 0; i < 3; ++i) + if(searchForBytes(image, size, signature[i], 6)) return true; return false; } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablyFE(const ByteBuffer& image, size_t size) { @@ -972,7 +665,7 @@ bool CartDetector::isProbablyFE(const ByteBuffer& image, size_t size) { 0x20, 0x00, 0xF0, 0x84, 0xD6 } // JSR $F000; $84, $D6 }; for(uInt32 i = 0; i < 4; ++i) - if(searchForBytes(image.get(), size, signature[i], 5, 1)) + if(searchForBytes(image, size, signature[i], 5)) return true; return false; @@ -983,7 +676,7 @@ bool CartDetector::isProbablyMDM(const ByteBuffer& image, size_t size) { // MDM cart is identified key 'MDMC' in the first 8K of ROM uInt8 mdmc[] = { 'M', 'D', 'M', 'C' }; - return searchForBytes(image.get(), std::min(size, 8_KB), mdmc, 4, 1); + return searchForBytes(image, std::min(size, 8_KB), mdmc, 4); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -994,10 +687,18 @@ bool CartDetector::isProbablySB(const ByteBuffer& image, size_t size) { 0xBD, 0x00, 0x08 }, // LDA $0800,x { 0xAD, 0x00, 0x08 } // LDA $0800 }; - if(searchForBytes(image.get(), size, signature[0], 3, 1)) + if(searchForBytes(image, size, signature[0], 3)) return true; else - return searchForBytes(image.get(), size, signature[1], 3, 1); + return searchForBytes(image, size, signature[1], 3); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartDetector::isProbablyTVBoy(const ByteBuffer& image, size_t size) +{ + // TV Boy cart bankswitching switches banks by accessing addresses 0x1800..$187F + uInt8 signature[5] = {0x91, 0x82, 0x6c, 0xfc, 0xff}; // STA ($82),Y; JMP ($FFFC) + return searchForBytes(image, size, signature, 5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1016,7 +717,7 @@ bool CartDetector::isProbablyUA(const ByteBuffer& image, size_t size) { 0xAD, 0xC0, 0x02 } // LDA $2C0 (Mickey) }; for(uInt32 i = 0; i < 6; ++i) - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) return true; return false; @@ -1029,10 +730,9 @@ bool CartDetector::isProbablyWD(const ByteBuffer& image, size_t size) uInt8 signature[1][3] = { { 0xA5, 0x39, 0x4C } // LDA $39, JMP }; - return searchForBytes(image.get(), size, signature[0], 3, 1); + return searchForBytes(image, size, signature[0], 3); } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartDetector::isProbablyX07(const ByteBuffer& image, size_t size) { @@ -1046,7 +746,7 @@ bool CartDetector::isProbablyX07(const ByteBuffer& image, size_t size) { 0x0C, 0x2D, 0x08 } // NOP $082D }; for(uInt32 i = 0; i < 6; ++i) - if(searchForBytes(image.get(), size, signature[i], 3, 1)) + if(searchForBytes(image, size, signature[i], 3)) return true; return false; diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx index 5f6a60674..810ed24a7 100644 --- a/src/emucore/CartDetector.hxx +++ b/src/emucore/CartDetector.hxx @@ -18,12 +18,8 @@ #ifndef CARTRIDGE_DETECTOR_HXX #define CARTRIDGE_DETECTOR_HXX -class Cartridge; -class Properties; - #include "Bankswitch.hxx" #include "bspf.hxx" -#include "Settings.hxx" /** Auto-detect cart type based on various attributes (file size, signatures, @@ -34,21 +30,6 @@ class Properties; class CartDetector { public: - /** - Create a new cartridge object allocated on the heap. The - type of cartridge created depends on the properties object. - - @param image A pointer to the ROM image - @param size The size of the ROM image - @param md5 The md5sum for the given ROM image (can be updated) - @param dtype The detected bankswitch type of the ROM image - @param settings The settings container - @return Pointer to the new cartridge object allocated on the heap - */ - static unique_ptr create(const FilesystemNode& file, - const ByteBuffer& image, size_t size, string& md5, - const string& dtype, Settings& settings); - /** Try to auto-detect the bankswitching type of the cartridge @@ -60,40 +41,6 @@ class CartDetector static Bankswitch::Type autodetectType(const ByteBuffer& image, size_t size); private: - /** - Create a cartridge from a multi-cart image pointer; internally this - takes a slice of the ROM image ues that for the cartridge. - - @param image A pointer to the complete ROM image - @param size The size of the ROM image slice - @param numroms The number of ROMs in the multicart - @param md5 The md5sum for the slice of the ROM image - @param type The detected type of the slice of the ROM image - @param id The ID for the slice of the ROM image - @param settings The settings container - - @return Pointer to the new cartridge object allocated on the heap - */ - static unique_ptr - createFromMultiCart(const ByteBuffer& image, size_t& size, - uInt32 numroms, string& md5, Bankswitch::Type type, string& id, - Settings& settings); - - /** - Create a cartridge from the entire image pointer. - - @param image A pointer to the complete ROM image - @param size The size of the ROM image - @param type The bankswitch type of the ROM image - @param md5 The md5sum for the ROM image - @param settings The settings container - - @return Pointer to the new cartridge object allocated on the heap - */ - static unique_ptr - createFromImage(const ByteBuffer& image, size_t size, Bankswitch::Type type, - const string& md5, Settings& settings); - /** Search the image for the specified byte signature @@ -107,7 +54,14 @@ class CartDetector */ static bool searchForBytes(const uInt8* image, size_t imagesize, const uInt8* signature, uInt32 sigsize, - uInt32 minhits); + uInt32 minhits = 1); + + static bool searchForBytes(const ByteBuffer& image, size_t imagesize, + const uInt8* signature, uInt32 sigsize, + uInt32 minhits = 1) + { + return searchForBytes(image.get(), imagesize, signature, sigsize, minhits); + } /** Returns true if the image is probably a SuperChip (128 bytes RAM) @@ -130,6 +84,11 @@ class CartDetector */ static bool isProbably3E(const ByteBuffer& image, size_t size); + /** + Returns true if the image is probably a 3EX bankswitching cartridge + */ + static bool isProbably3EX(const ByteBuffer& image, size_t size); + /** Returns true if the image is probably a 3E+ bankswitching cartridge */ @@ -175,16 +134,6 @@ class CartDetector */ static bool isProbablyCV(const ByteBuffer& image, size_t size); - /** - Returns true if the image is probably a CV+ bankswitching cartridge - */ - static bool isProbablyCVPlus(const ByteBuffer& image, size_t size); - - /** - Returns true if the image is probably a DASH bankswitching cartridge - */ - static bool isProbablyDASH(const ByteBuffer& image, size_t size); - /** Returns true if the image is probably a DF/DFSC bankswitching cartridge */ @@ -245,6 +194,11 @@ class CartDetector */ static bool isProbablySB(const ByteBuffer& image, size_t size); + /** + Returns true if the image is probably a TV Boy bankswitching cartridge + */ + static bool isProbablyTVBoy(const ByteBuffer& image, size_t size); + /** Returns true if the image is probably a UA bankswitching cartridge */ diff --git a/src/emucore/CartE0.cxx b/src/emucore/CartE0.cxx index 0c1921464..9204d5619 100644 --- a/src/emucore/CartE0.cxx +++ b/src/emucore/CartE0.cxx @@ -20,221 +20,52 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeE0::CartridgeE0(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); + myBankShift = BANK_SHIFT; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeE0::reset() { - // Setup segments to some default slices + // Setup segments to some default banks if(randomStartBank()) { - segmentZero(mySystem->randGenerator().next() % 8); - segmentOne(mySystem->randGenerator().next() % 8); - segmentTwo(mySystem->randGenerator().next() % 8); + bank(mySystem->randGenerator().next() % 8, 0); + bank(mySystem->randGenerator().next() % 8, 1); + bank(mySystem->randGenerator().next() % 8, 2); } else { - segmentZero(4); - segmentOne(5); - segmentTwo(6); + bank(4, 0); + bank(5, 1); + bank(6, 2); } - myCurrentSlice[3] = 7; // fixed - myBankChanged = true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0::install(System& system) +bool CartridgeE0::checkSwitchBank(uInt16 address, uInt8) { - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page acessing methods for the first part of the last segment - for(uInt16 addr = 0x1C00; addr < static_cast(0x1FE0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[0x1C00 + (addr & 0x03FF)]; - access.codeAccessBase = &myCodeAccessBase[0x1C00 + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing methods for the hot spots in the last segment - access.directPeekBase = nullptr; - access.codeAccessBase = &myCodeAccessBase[0x1FC0]; // TJ: is this the correct address (or 0x1FE0)? - access.type = System::PageAccessType::READ; - for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeE0::getBank(uInt16 address) const -{ - return myCurrentSlice[(address & 0xFFF) >> 10]; // 1K slices -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeE0::bankCount() const -{ - return 8; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeE0::peek(uInt16 address) -{ - address &= 0x0FFF; + address &= ROM_MASK; // Switch banks if necessary if((address >= 0x0FE0) && (address <= 0x0FE7)) { - segmentZero(address & 0x0007); + bank(address & 0x0007, 0); + return true; } else if((address >= 0x0FE8) && (address <= 0x0FEF)) { - segmentOne(address & 0x0007); + bank(address & 0x0007, 1); + return true; } else if((address >= 0x0FF0) && (address <= 0x0FF7)) { - segmentTwo(address & 0x0007); - } - - return myImage[(myCurrentSlice[address >> 10] << 10) + (address & 0x03FF)]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeE0::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FE0) && (address <= 0x0FE7)) - { - segmentZero(address & 0x0007); - } - else if((address >= 0x0FE8) && (address <= 0x0FEF)) - { - segmentOne(address & 0x0007); - } - else if((address >= 0x0FF0) && (address <= 0x0FF7)) - { - segmentTwo(address & 0x0007); + bank(address & 0x0007, 2); + return true; } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0::segmentZero(uInt16 slice) -{ - if(bankLocked()) return; - - // Remember the new slice - myCurrentSlice[0] = slice; - uInt16 offset = slice << 10; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1000; addr < 0x1400; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x03FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0::segmentOne(uInt16 slice) -{ - if(bankLocked()) return; - - // Remember the new slice - myCurrentSlice[1] = slice; - uInt16 offset = slice << 10; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x03FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeE0::segmentTwo(uInt16 slice) -{ - if(bankLocked()) return; - - // Remember the new slice - myCurrentSlice[2] = slice; - uInt16 offset = slice << 10; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x03FF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeE0::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - myImage[(myCurrentSlice[address >> 10] << 10) + (address & 0x03FF)] = value; - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeE0::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeE0::save(Serializer& out) const -{ - try - { - out.putShortArray(myCurrentSlice.data(), myCurrentSlice.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeE0::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeE0::load(Serializer& in) -{ - try - { - in.getShortArray(myCurrentSlice.data(), myCurrentSlice.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeE0::load" << endl; - return false; - } - - return true; -} diff --git a/src/emucore/CartE0.hxx b/src/emucore/CartE0.hxx index 0a9453ab2..70af8f85d 100644 --- a/src/emucore/CartE0.hxx +++ b/src/emucore/CartE0.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartE0Widget.hxx" #endif @@ -29,19 +29,19 @@ class System; /** This is the cartridge class for Parker Brothers' 8K games. In this bankswitching scheme the 2600's 4K cartridge address space - is broken into four 1K segments. The desired 1K slice of the + is broken into four 1K segments. The desired 1K bank of the ROM is selected by accessing $1FE0 to $1FE7 for the first 1K. - $1FE8 to $1FEF selects the slice for the second 1K, and $1FF0 to - $1FF7 selects the slice for the third 1K. The last 1K segment + $1FE8 to $1FEF selects the bank for the second 1K, and $1FF0 to + $1FF7 selects the bank for the third 1K. The last 1K segment always points to the last 1K of the ROM image. Because of the complexity of this scheme, the cart reports having only one actual bank, in which pieces of it can be swapped out in many different ways. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeE0 : public Cartridge +class CartridgeE0 : public CartridgeEnhanced { friend class CartridgeE0Widget; @@ -53,9 +53,10 @@ class CartridgeE0 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeE0(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~CartridgeE0() = default; public: @@ -64,60 +65,6 @@ class CartridgeE0 : public Cartridge */ void reset() override; - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -137,51 +84,14 @@ class CartridgeE0 : public Cartridge } #endif - public: - /** - Get the byte at the specified address. + private: + bool checkSwitchBank(uInt16 address, uInt8 = 0) override; - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + uInt16 hotspot() const override { return 0x1FE0; } private: - /** - Install the specified slice for segment zero - - @param slice The slice to map into the segment - */ - void segmentZero(uInt16 slice); - - /** - Install the specified slice for segment one - - @param slice The slice to map into the segment - */ - void segmentOne(uInt16 slice); - - /** - Install the specified slice for segment two - - @param slice The slice to map into the segment - */ - void segmentTwo(uInt16 slice); - - private: - // The 8K ROM image of the cartridge - std::array myImage; - - // Indicates the slice mapped into each of the four segments - std::array myCurrentSlice; + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400 private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartEF.cxx b/src/emucore/CartEF.cxx index f89e3b441..c063b0c05 100644 --- a/src/emucore/CartEF.cxx +++ b/src/emucore/CartEF.cxx @@ -20,142 +20,22 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeEF::CartridgeEF(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEF::reset() +bool CartridgeEF::checkSwitchBank(uInt16 address, uInt8) { - initializeStartBank(1); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEF::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeEF::peek(uInt16 address) -{ - address &= 0x0FFF; + address &= ROM_MASK; // Switch banks if necessary if((address >= 0x0FE0) && (address <= 0x0FEF)) + { bank(address - 0x0FE0); - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEF::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FE0) && (address <= 0x0FEF)) - bank(address - 0x0FE0); - + return true; + } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEF::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FE0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeEF::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeEF::bankCount() const -{ - return 16; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEF::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeEF::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEF::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeEF::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEF::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeEF::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartEF.hxx b/src/emucore/CartEF.hxx index 62a10975d..2c86d0d71 100644 --- a/src/emucore/CartEF.hxx +++ b/src/emucore/CartEF.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartEFWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; There are 16 4K banks (total of 64K ROM). Accessing $1FE0 - $1FEF switches to each bank. - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class CartridgeEF : public Cartridge +class CartridgeEF : public CartridgeEnhanced { friend class CartridgeEFWidget; @@ -45,77 +45,13 @@ class CartridgeEF : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeEF(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 64_KB); virtual ~CartridgeEF() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,29 +71,12 @@ class CartridgeEF : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 64K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1FE0; } + + uInt16 getStartBank() const override { return 1; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartEFSC.cxx b/src/emucore/CartEFSC.cxx index 15f8470c0..f73557245 100644 --- a/src/emucore/CartEFSC.cxx +++ b/src/emucore/CartEFSC.cxx @@ -20,198 +20,9 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeEFSC::CartridgeEFSC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEF(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(15); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeEFSC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeEFSC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FE0) && (address <= 0x0FEF)) - bank(address - 0x0FE0); - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEFSC::poke(uInt16 address, uInt8 value) -{ - uInt16 pokeAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FE0) && (address <= 0x0FEF)) - { - bank(address - 0x0FE0); - return false; - } - - if (!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], pokeAddress, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, pokeAddress, value); - myRamWriteAccess = pokeAddress; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEFSC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1FE0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeEFSC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeEFSC::bankCount() const -{ - return 16; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEFSC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeEFSC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEFSC::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeEFSC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeEFSC::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeEFSC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; } diff --git a/src/emucore/CartEFSC.hxx b/src/emucore/CartEFSC.hxx index 810b27b22..ac95c9e2c 100644 --- a/src/emucore/CartEFSC.hxx +++ b/src/emucore/CartEFSC.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEF.hxx" #ifdef DEBUGGER_SUPPORT #include "CartEFSCWidget.hxx" #endif @@ -32,9 +32,9 @@ class System; Accessing $1FE0 - $1FEF switches to each bank. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class CartridgeEFSC : public Cartridge +class CartridgeEFSC : public CartridgeEF { friend class CartridgeEFSCWidget; @@ -46,77 +46,13 @@ class CartridgeEFSC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeEFSC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 64_KB); virtual ~CartridgeEFSC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -136,32 +72,12 @@ class CartridgeEFSC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + private: + uInt16 getStartBank() const override { return 15; } private: - // The 64K ROM image of the cartridge - std::array myImage; - - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartEnhanced.cxx b/src/emucore/CartEnhanced.cxx new file mode 100644 index 000000000..633104cf3 --- /dev/null +++ b/src/emucore/CartEnhanced.cxx @@ -0,0 +1,410 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Logger.hxx" +#include "System.hxx" +#include "CartEnhanced.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size, + const string& md5, const Settings& settings, + size_t bsSize) + : Cartridge(settings, md5) +{ + // ROMs are not always at the 'legal' size for their associated + // bankswitching scheme; here we deal with the differing sizes + + // Is the ROM too large? If so, we cap it + if(size > bsSize) + { + ostringstream buf; + buf << "ROM larger than expected (" << size << " > " << bsSize + << "), truncating " << (size - bsSize) << " bytes\n"; + Logger::info(buf.str()); + } + else if(size < mySize) + { + ostringstream buf; + buf << "ROM smaller than expected (" << mySize << " > " << size + << "), appending " << (mySize - size) << " bytes\n"; + Logger::info(buf.str()); + } + + mySize = bsSize; + + // Initialize ROM with all 0's, to fill areas that the ROM may not cover + myImage = make_unique(mySize); + std::fill_n(myImage.get(), mySize, 0); + + // Directly copy the ROM image into the buffer + // Only copy up to the amount of data the ROM provides; extra unused + // space will be filled with 0's from above + std::copy_n(image.get(), std::min(mySize, size), myImage.get()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhanced::install(System& system) +{ + // limit banked RAM size to the size of one RAM bank + const uInt32 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : uInt32(myRamSize); + + // calculate bank switching and RAM sizes and masks + myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000 + myBankMask = myBankSize - 1; // e.g. = 0x0FFF + // Either the bankswitching supports multiple segments + // or the ROM is < 4K (-> 1 segment) + myBankSegs = std::min(1 << (MAX_BANK_SHIFT - myBankShift), + int(mySize) / myBankSize); // e.g. = 1 + myRomOffset = myRamBankCount > 0U ? 0U : static_cast(myRamSize * 2); + myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0) + myWriteOffset = myRamWpHigh ? ramSize : 0; // e.g. = 0x0000 + myReadOffset = myRamWpHigh ? 0 : ramSize; // e.g. = 0x0080 + + createRomAccessArrays(mySize + (myRomOffset > 0 ? 0 : myRamSize)); + + // Allocate array for the segment's current bank offset + myCurrentSegOffset = make_unique(myBankSegs); + + // Allocate array for the RAM area + if(myRamSize > 0) + myRAM = make_unique(myRamSize); + + mySystem = &system; + + if(myRomOffset > 0) + { + // Setup page access for extended RAM; banked RAM will be setup in bank() + System::PageAccess access(this, System::PageAccessType::READ); + + // Set the page accessing method for the RAM writing pages + // Map access to this class, since we need to inspect all accesses to + // check if RWP happens + access.type = System::PageAccessType::WRITE; + for(uInt16 addr = ROM_OFFSET + myWriteOffset; addr < ROM_OFFSET + myWriteOffset + myRamSize; addr += System::PAGE_SIZE) + { + const uInt16 offset = addr & myRamMask; + + access.directPokeBase = &myRAM[offset]; + access.romAccessBase = &myRomAccessBase[myWriteOffset + offset]; + access.romPeekCounter = &myRomAccessCounter[myWriteOffset + offset]; + access.romPokeCounter = &myRomAccessCounter[myWriteOffset + offset + myAccessSize]; + mySystem->setPageAccess(addr, access); + } + + // Set the page accessing method for the RAM reading pages + access.type = System::PageAccessType::READ; + access.directPokeBase = nullptr; + for(uInt16 addr = ROM_OFFSET + myReadOffset; addr < ROM_OFFSET + myReadOffset + myRamSize; addr += System::PAGE_SIZE) + { + const uInt16 offset = addr & myRamMask; + + access.directPeekBase = &myRAM[offset]; + access.romAccessBase = &myRomAccessBase[myReadOffset + offset]; + access.romPeekCounter = &myRomAccessCounter[myReadOffset + offset]; + access.romPokeCounter = &myRomAccessCounter[myReadOffset + offset + myAccessSize]; + mySystem->setPageAccess(addr, access); + } + } + + // Install pages for the startup bank (TODO: currently only in first bank segment) + bank(startBank(), 0); + if(mySize >= 4_KB && myBankSegs > 1) + // Setup the last bank segment to always point to the last ROM segment + bank(romBankCount() - 1, myBankSegs - 1); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartridgeEnhanced::reset() +{ + if(myRamSize > 0) + initializeRAM(myRAM.get(), myRamSize); + + initializeStartBank(getStartBank()); + + // Upon reset we switch to the reset bank + bank(startBank()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeEnhanced::peek(uInt16 address) +{ + const uInt16 peekAddress = address; + + // hotspots in TIA range are reacting to pokes only + if (hotspot() >= 0x80) + checkSwitchBank(address & ADDR_MASK); + + if(isRamBank(address)) + { + address &= myRamMask; + + // This is a read access to a write port! + // Reading from the write port triggers an unwanted write + // The RAM banks follow the ROM banks and are half the size of a ROM bank + return peekRAM(myRAM[ramAddressSegmentOffset(peekAddress) + address], peekAddress); + } + address &= ROM_MASK; + + // Write port is e.g. at 0xF000 - 0xF07F (128 bytes) + if(address < myReadOffset + myRamSize && address >= myReadOffset) + { + // This is a read access to a write port! + // Reading from the write port triggers an unwanted write + return peekRAM(myRAM[address], peekAddress); + } + + return myImage[romAddressSegmentOffset(peekAddress) + (peekAddress & myBankMask)]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::poke(uInt16 address, uInt8 value) +{ + // Switch banks if necessary + if (checkSwitchBank(address & ADDR_MASK, value)) + return false; + + if(myRamSize > 0) + { + // Code should never get here (System::PageAccess::directPoke() handles this) + const uInt16 pokeAddress = address; + + if(isRamBank(address)) + { + if(bool(address & (myBankSize >> 1)) == myRamWpHigh) + { + address &= myRamMask; + // The RAM banks follow the ROM banks and are half the size of a ROM bank + pokeRAM(myRAM[ramAddressSegmentOffset(pokeAddress) + address], + pokeAddress, value); + return true; + } + } + else + { + //address &= myBankMask; + if(bool(address & myRamSize) == myRamWpHigh) + { + pokeRAM(myRAM[address & myRamMask], pokeAddress, value); + return true; + } + } + // Writing to the read port should be ignored, but trigger a break if option enabled + uInt8 dummy; + + pokeRAM(dummy, pokeAddress, value); + myRamWriteAccess = pokeAddress; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment) +{ + if(bankLocked()) return false; + + const uInt16 segmentOffset = segment << myBankShift; + + if(myRamBankCount == 0 || bank < romBankCount()) + { + // Setup ROM bank + const uInt16 romBank = bank % romBankCount(); + // Remember what bank is in this segment + const uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift; + const uInt16 hotspot = this->hotspot(); + uInt16 hotSpotAddr; + // Skip extra RAM; if existing it is only mapped into first segment + const uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK; + // for ROMs < 4_KB, the whole address space will be mapped. + const uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK; + + if(hotspot & 0x1000) + hotSpotAddr = (hotspot & ~System::PAGE_MASK); + else + hotSpotAddr = 0xFFFF; // none + + System::PageAccess access(this, System::PageAccessType::READ); + // Setup the page access methods for the current bank + for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) + { + const uInt32 offset = bankOffset + (addr & myBankMask); + + if(myDirectPeek && addr != hotSpotAddr) + access.directPeekBase = &myImage[offset]; + else + access.directPeekBase = nullptr; + access.romAccessBase = &myRomAccessBase[offset]; + access.romPeekCounter = &myRomAccessCounter[offset]; + access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize]; + mySystem->setPageAccess(addr, access); + } + } + else + { + // Setup RAM bank + const uInt16 ramBank = (bank - romBankCount()) % myRamBankCount; + // The RAM banks follow the ROM banks and are half the size of a ROM bank + const uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1)); + + // Remember what bank is in this segment + myCurrentSegOffset[segment] = uInt32(mySize) + (ramBank << myBankShift); + + // Set the page accessing method for the RAM writing pages + uInt16 fromAddr = (ROM_OFFSET + segmentOffset + myWriteOffset) & ~System::PAGE_MASK; + uInt16 toAddr = (ROM_OFFSET + segmentOffset + myWriteOffset + (myBankSize >> 1)) & ~System::PAGE_MASK; + System::PageAccess access(this, System::PageAccessType::WRITE); + + for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) + { + const uInt32 offset = bankOffset + (addr & myRamMask); + + access.directPokeBase = &myRAM[offset - mySize]; + access.romAccessBase = &myRomAccessBase[offset]; + access.romPeekCounter = &myRomAccessCounter[offset]; + access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize]; + mySystem->setPageAccess(addr, access); + } + + // Set the page accessing method for the RAM reading pages + fromAddr = (ROM_OFFSET + segmentOffset + myReadOffset) & ~System::PAGE_MASK; + toAddr = (ROM_OFFSET + segmentOffset + myReadOffset + (myBankSize >> 1)) & ~System::PAGE_MASK; + access.type = System::PageAccessType::READ; + access.directPokeBase = nullptr; + + for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE) + { + const uInt32 offset = bankOffset + (addr & myRamMask); + + access.directPeekBase = &myRAM[offset - mySize]; + access.romAccessBase = &myRomAccessBase[offset]; + access.romPeekCounter = &myRomAccessCounter[offset]; + access.romPokeCounter = &myRomAccessCounter[offset + myAccessSize]; + mySystem->setPageAccess(addr, access); + } + } + return myBankChanged = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +inline uInt16 CartridgeEnhanced::romAddressSegmentOffset(uInt16 address) const +{ + return myCurrentSegOffset[((address & ROM_MASK) >> myBankShift) % myBankSegs]; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +inline uInt16 CartridgeEnhanced::ramAddressSegmentOffset(uInt16 address) const +{ + return uInt16(myCurrentSegOffset[((address & ROM_MASK) >> myBankShift) % myBankSegs] - mySize) >> 1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeEnhanced::getBank(uInt16 address) const +{ + return romAddressSegmentOffset(address) >> myBankShift; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeEnhanced::getSegmentBank(uInt16 segment) const +{ + return myCurrentSegOffset[segment % myBankSegs] >> myBankShift; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeEnhanced::romBankCount() const +{ + return uInt16(mySize >> myBankShift); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 CartridgeEnhanced::ramBankCount() const +{ + return myRamBankCount; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::isRamBank(uInt16 address) const +{ + return myRamBankCount > 0 ? getBank(address) >= romBankCount() : false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::patch(uInt16 address, uInt8 value) +{ + if(isRamBank(address)) + { + myRAM[ramAddressSegmentOffset(address) + (address & myRamMask)] = value; + } + else + { + if(static_cast(address & myBankMask) < myRamSize * 2) + { + // Normally, a write to the read port won't do anything + // However, the patch command is special in that ignores such + // cart restrictions + myRAM[address & myRamMask] = value; + } + else + myImage[romAddressSegmentOffset(address) + (address & myBankMask)] = value; + } + + return myBankChanged = true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const ByteBuffer& CartridgeEnhanced::getImage(size_t& size) const +{ + size = mySize; + return myImage; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::save(Serializer& out) const +{ + try + { + out.putIntArray(myCurrentSegOffset.get(), myBankSegs); + if(myRamSize > 0) + out.putByteArray(myRAM.get(), myRamSize); + } + catch(...) + { + cerr << "ERROR: << " << name() << "::save" << endl; + return false; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeEnhanced::load(Serializer& in) +{ + try + { + in.getIntArray(myCurrentSegOffset.get(), myBankSegs); + if(myRamSize > 0) + in.getByteArray(myRAM.get(), myRamSize); + } + catch(...) + { + cerr << "ERROR: " << name() << "::load" << endl; + return false; + } + // Restore bank segments + for(uInt16 i = 0; i < myBankSegs; ++i) + bank(getSegmentBank(i), i); + + return true; +} diff --git a/src/emucore/CartEnhanced.hxx b/src/emucore/CartEnhanced.hxx new file mode 100644 index 000000000..e99afc917 --- /dev/null +++ b/src/emucore/CartEnhanced.hxx @@ -0,0 +1,297 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGEENHANCED_HXX +#define CARTRIDGEENHANCED_HXX + +class System; + +#include "bspf.hxx" +#include "Cart.hxx" +#ifdef DEBUGGER_SUPPORT + #include "CartEnhancedWidget.hxx" +#endif + +/** + Enhanced cartridge base class used for multiple cart types. + + @author Thomas Jentzsch +*/ +class CartridgeEnhanced : public Cartridge +{ + friend class CartridgeEnhancedWidget; + + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + @param size The size of the ROM image + @param md5 The md5sum of the ROM image + @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + */ + CartridgeEnhanced(const ByteBuffer& image, size_t size, + const string& md5, const Settings& settings, + size_t bsSize); + virtual ~CartridgeEnhanced() = default; + + public: + /** + Install cartridge in the specified system. Invoked by the system + when the cartridge is attached to it. + + @param system The system the device should install itself in + */ + void install(System& system) override; + + /** + Reset device to its power-on state + */ + void reset() override; + + /** + Install pages for the specified bank in the system. + + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed + */ + bool bank(uInt16 bank, uInt16 segment = 0) override; + + /** + Get the current bank. + + @param address The address to use when querying the bank + */ + uInt16 getBank(uInt16 address = 0) const override; + + /** + Get the current bank for a bank segment. + + @param segment The segment to get the bank for + */ + uInt16 getSegmentBank(uInt16 segment = 0) const; + + /** + Query the number of banks supported by the cartridge. + */ + uInt16 romBankCount() const override; + + /** + Query the number of RAM 'banks' supported by the cartridge. + */ + uInt16 ramBankCount() const override; + + /** + Check if the segment at that address contains a RAM bank + + @param address The address which defines the segment + + @return true, if the segment is currently mapped to a RAM bank + */ + bool isRamBank(uInt16 address) const; + + /** + Patch the cartridge ROM. + + @param address The ROM address to patch + @param value The value to place into the address + @return Success or failure of the patch operation + */ + bool patch(uInt16 address, uInt8 value) override; + + /** + Access the internal ROM image for this cartridge. + + @param size Set to the size of the internal ROM image data + @return A reference to the internal ROM image data + */ + const ByteBuffer& getImage(size_t& size) const override; + + /** + Save the current state of this cart to the given Serializer. + + @param out The Serializer object to use + @return False on any errors, else true + */ + bool save(Serializer& out) const override; + + /** + Load the current state of this cart from the given Serializer. + + @param in The Serializer object to use + @return False on any errors, else true + */ + bool load(Serializer& in) override; + + /** + Get the byte at the specified address. + + @return The byte at the specified address + */ + uInt8 peek(uInt16 address) override; + + /** + Change the byte at the specified address to the given value + + @param address The address where the value should be stored + @param value The value to be stored at the address + @return True if the poke changed the device address space, else false + */ + bool poke(uInt16 address, uInt8 value) override; + + /** + Get the hotspot in ROM address space. + + @return The first hotspot address (ususally in ROM) space or 0 + */ + virtual uInt16 hotspot() const { return 0; } + // TODO: handle cases where there the hotspots cover multiple pages + + protected: + // The '2 ^ N = bank segment size' exponent + uInt16 myBankShift{BANK_SHIFT}; // default 12 (-> one 4K segment) + + // The size of a bank's segment + uInt16 myBankSize{uInt16(4_KB)}; + + // The mask for a bank segment + uInt16 myBankMask{ROM_MASK}; + + protected: + // The extra RAM size + size_t myRamSize{RAM_SIZE}; // default 0 + + // The number of RAM banks + uInt16 myRamBankCount{RAM_BANKS}; // default 0 + + // The mask for the extra RAM + uInt16 myRamMask{0}; // RAM_SIZE - 1, but doesn't matter when RAM_SIZE is 0 + + // The number of segments a bank is split into (default 1) + uInt16 myBankSegs{1}; + + // The offset into ROM space for reading from ROM + // This is zero for types without RAM and with banked RAM + // - xxSC = 0x0100 + // - FA(2) = 0x0200 + // - CV = 0x0800 + uInt16 myRomOffset{0}; + + // The offset into ROM space for writing to RAM + // - xxSC = 0x0000 + // - FA(2) = 0x0000 + // - CV = 0x0400 + uInt16 myWriteOffset{0}; + + // The offset into ROM space for reading from RAM + // - xxSC = 0x0080 + // - FA(2) = 0x0100 + // - CV = 0x0000 + uInt16 myReadOffset{0}; + + // Flag, true if write port is at high and read port is at low address + bool myRamWpHigh{RAM_HIGH_WP}; + + // Pointer to a dynamically allocated ROM image of the cartridge + ByteBuffer myImage{nullptr}; + + // Contains the offset into the ROM image for each of the bank segments + DWordBuffer myCurrentSegOffset{nullptr}; + + // Indicates whether to use direct ROM peeks or not + bool myDirectPeek{true}; + + // Pointer to a dynamically allocated RAM area of the cartridge + ByteBuffer myRAM{nullptr}; + + // The size of the ROM image + size_t mySize{0}; + + protected: + // The mask for 6507 address space + static constexpr uInt16 ADDR_MASK = 0x1FFF; + + // The offset into address space for accessing ROM + static constexpr uInt16 ROM_OFFSET = 0x1000; + + // The mask for ROM address space + static constexpr uInt16 ROM_MASK = 0x0FFF; + + private: + // Calculated as: log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 12; // default = 4K + + // The size of extra RAM in ROM address space + static constexpr size_t RAM_SIZE = 0; // default = none + + // The number of RAM banks + static constexpr uInt16 RAM_BANKS = 0; + + // Write port for extra RAM is at low address by default + static constexpr bool RAM_HIGH_WP = false; + + // The maximum shift (for a 4K bank size) + static constexpr uInt16 MAX_BANK_SHIFT = 12; // -> 4K + + protected: + /** + Check hotspots and switch bank if triggered. + + @param address The address to check + @param value The optional value used to determine the bank switched to + + @return True if a bank switch happened. + */ + virtual bool checkSwitchBank(uInt16 address, uInt8 value = 0) = 0; + + private: + /** + Get the ROM's startup bank. + + @return The bank the ROM will start in + */ + virtual uInt16 getStartBank() const { return 0; } + + /** + Get the ROM offset of the segment of the given address + + @param address The address to get the offset for + @return The calculated offset + */ + uInt16 romAddressSegmentOffset(uInt16 address) const; + + /** + Get the RAM offset of the segment of the given address + + @param address The address to get the offset for + @return The calculated offset + */ + uInt16 ramAddressSegmentOffset(uInt16 address) const; + + private: + // Following constructors and assignment operators not supported + CartridgeEnhanced() = delete; + CartridgeEnhanced(const CartridgeEnhanced&) = delete; + CartridgeEnhanced(CartridgeEnhanced&&) = delete; + CartridgeEnhanced& operator=(const CartridgeEnhanced&) = delete; + CartridgeEnhanced& operator=(CartridgeEnhanced&&) = delete; +}; + +#endif diff --git a/src/emucore/CartF0.cxx b/src/emucore/CartF0.cxx index 14ace4375..0429109e3 100644 --- a/src/emucore/CartF0.cxx +++ b/src/emucore/CartF0.cxx @@ -15,155 +15,26 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF0.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF0::CartridgeF0(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF0::reset() +bool CartridgeF0::checkSwitchBank(uInt16 address, uInt8) { - // Upon reset we switch to the startup bank - initializeStartBank(15); - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF0::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF0::peek(uInt16 address) -{ - address &= 0x0FFF; - - // Switch to next bank - if(address == 0x0FF0) - incbank(); - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF0::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch to next bank - if(address == 0x0FF0) - incbank(); - + // Switch banks if necessary + if(address == 0x1FF0) + { + // Switch to next bank + uInt8 nextBank = ((getBank()) + 1) & 0x0F; + bank(nextBank); + return true; + } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF0::incbank() -{ - // Determine current bank, and increment to the next one - uInt8 nextBank = ((myBankOffset >> 12) + 1) & 0x0F; - bank(nextBank); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF0::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF0 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FF0U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF0::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF0::bankCount() const -{ - return 16; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF0::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF0::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF0::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeF0::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF0::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeF0::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartF0.hxx b/src/emucore/CartF0.hxx index d4733a784..e49b8ce31 100644 --- a/src/emucore/CartF0.hxx +++ b/src/emucore/CartF0.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF0_HXX #define CARTRIDGEF0_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF0Widget.hxx" #endif @@ -31,9 +28,9 @@ class System; There are 16 4K banks. Accessing $1FF0 switches to next bank. - @author Eckhard Stolberg + @author Eckhard Stolberg, Thomas Jentzsch */ -class CartridgeF0 : public Cartridge +class CartridgeF0 : public CartridgeEnhanced { friend class CartridgeF0Widget; @@ -45,77 +42,13 @@ class CartridgeF0 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF0(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 64_KB); virtual ~CartridgeF0() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,35 +68,12 @@ class CartridgeF0 : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - /** - Install pages for the next bank in the system - */ - void incbank(); + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - private: - // The 64K ROM image of the cartridge - std::array myImage; + uInt16 hotspot() const override { return 0x1FF0; } - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 getStartBank() const override { return 15; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartF4.cxx b/src/emucore/CartF4.cxx index 82d3f61bb..c00163efb 100644 --- a/src/emucore/CartF4.cxx +++ b/src/emucore/CartF4.cxx @@ -15,151 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Random.hxx" -#include "System.hxx" #include "CartF4.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF4::CartridgeF4(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4::reset() +bool CartridgeF4::checkSwitchBank(uInt16 address, uInt8) { - // Upon reset we switch to the startup bank - initializeStartBank(0); - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF4::peek(uInt16 address) -{ - address &= 0x0FFF; - // Switch banks if necessary - if((address >= 0x0FF4) && (address <= 0x0FFB)) + // Note: addresses could be calculated from hotspot and bank count + if((address >= 0x1FF4) && (address <= 0x1FFB)) { - bank(address - 0x0FF4); + bank(address - 0x1FF4); + return true; } - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FF4) && (address <= 0x0FFB)) - { - bank(address - 0x0FF4); - } - return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FF4U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF4::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF4::bankCount() const -{ - return 8; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF4::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeF4::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeF4::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartF4.hxx b/src/emucore/CartF4.hxx index d9c8fd346..81a5e176e 100644 --- a/src/emucore/CartF4.hxx +++ b/src/emucore/CartF4.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF4_HXX #define CARTRIDGEF4_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF4Widget.hxx" #endif @@ -30,9 +27,9 @@ class System; Cartridge class used for Atari's 32K bankswitched games. There are eight 4K banks, accessible by read/write to $1FF4 - $1FFB. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF4 : public Cartridge +class CartridgeF4 : public CartridgeEnhanced { friend class CartridgeF4Widget; @@ -44,77 +41,13 @@ class CartridgeF4 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF4(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 32_KB); virtual ~CartridgeF4() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -134,31 +67,12 @@ class CartridgeF4 : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 32K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1FF4; } - private: +private: // Following constructors and assignment operators not supported CartridgeF4() = delete; CartridgeF4(const CartridgeF4&) = delete; diff --git a/src/emucore/CartF4SC.cxx b/src/emucore/CartF4SC.cxx index 45ec2ec88..d012874c6 100644 --- a/src/emucore/CartF4SC.cxx +++ b/src/emucore/CartF4SC.cxx @@ -15,203 +15,14 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF4SC.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF4SC::CartridgeF4SC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeF4(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF4SC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF4SC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FF4) && (address <= 0x0FFB)) - bank(address - 0x0FF4); - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4SC::poke(uInt16 address, uInt8 value) -{ - uInt16 pokeAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - if((address >= 0x0FF4) && (address <= 0x0FFB)) - { - bank(address - 0x0FF4); - return false; - } - - if(!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], pokeAddress, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, pokeAddress, value); - myRamWriteAccess = pokeAddress; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4SC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1FF4U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF4SC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF4SC::bankCount() const -{ - return 8; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4SC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF4SC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4SC::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF4SC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF4SC::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF4SC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; + myRamMask = RAM_SIZE - 1; } diff --git a/src/emucore/CartF4SC.hxx b/src/emucore/CartF4SC.hxx index 20c003970..49f1278ac 100644 --- a/src/emucore/CartF4SC.hxx +++ b/src/emucore/CartF4SC.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF4SC_HXX #define CARTRIDGEF4SC_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartF4.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF4SCWidget.hxx" #endif @@ -31,9 +28,9 @@ class System; RAM. There are eight 4K banks, accessible by read/write to $1FF4 - $1FFB. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF4SC : public Cartridge +class CartridgeF4SC : public CartridgeF4 { friend class CartridgeF4SCWidget; @@ -45,77 +42,13 @@ class CartridgeF4SC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF4SC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 32_KB); virtual ~CartridgeF4SC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,32 +68,12 @@ class CartridgeF4SC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 32K ROM image of the cartridge - std::array myImage; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + // RAM mask + static constexpr uInt16 RAM_MASK = RAM_SIZE - 1; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartF6.cxx b/src/emucore/CartF6.cxx index a5ed70ce3..7b120d0b0 100644 --- a/src/emucore/CartF6.cxx +++ b/src/emucore/CartF6.cxx @@ -15,191 +15,25 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF6.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6::reset() +bool CartridgeF6::checkSwitchBank(uInt16 address, uInt8) { - // Upon reset we switch to the startup bank - initializeStartBank(0); - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6::install(System& system) -{ - mySystem = &system; - - // Upon install we'll setup the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF6::peek(uInt16 address) -{ - address &= 0x0FFF; - // Switch banks if necessary - switch(address) + // Note: addresses could be calculated from hotspot and bank count + if((address >= 0x1FF6) && (address <= 0x1FF9)) { - case 0x0FF6: - // Set the current bank to the first 4k bank - bank(0); - break; - - case 0x0FF7: - // Set the current bank to the second 4k bank - bank(1); - break; - - case 0x0FF8: - // Set the current bank to the third 4k bank - bank(2); - break; - - case 0x0FF9: - // Set the current bank to the forth 4k bank - bank(3); - break; - - default: - break; - } - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) - { - case 0x0FF6: - // Set the current bank to the first 4k bank - bank(0); - break; - - case 0x0FF7: - // Set the current bank to the second 4k bank - bank(1); - break; - - case 0x0FF8: - // Set the current bank to the third 4k bank - bank(2); - break; - - case 0x0FF9: - // Set the current bank to the forth 4k bank - bank(3); - break; - - default: - break; + bank(address - 0x1FF6); + return true; } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF6 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FF6U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF6::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF6::bankCount() const -{ - return 4; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF6::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeF6::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeF6::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartF6.hxx b/src/emucore/CartF6.hxx index 4dc2c62b5..7707f1ef6 100644 --- a/src/emucore/CartF6.hxx +++ b/src/emucore/CartF6.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF6_HXX #define CARTRIDGEF6_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF6Widget.hxx" #endif @@ -30,9 +27,9 @@ class System; Cartridge class used for Atari's 16K bankswitched games. There are four 4K banks, accessible by read/write to $1FF6 - $1FF9. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF6 : public Cartridge +class CartridgeF6 : public CartridgeEnhanced { friend class CartridgeF6Widget; @@ -44,77 +41,13 @@ class CartridgeF6 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF6(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 16_KB); virtual ~CartridgeF6() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -134,29 +67,10 @@ class CartridgeF6 : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 16K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1FF6; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartF6SC.cxx b/src/emucore/CartF6SC.cxx index 513560824..084091d12 100644 --- a/src/emucore/CartF6SC.cxx +++ b/src/emucore/CartF6SC.cxx @@ -15,243 +15,14 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF6SC.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF6SC::CartridgeF6SC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeF6(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF6SC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF6SC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) - { - case 0x0FF6: - // Set the current bank to the first 4k bank - bank(0); - break; - - case 0x0FF7: - // Set the current bank to the second 4k bank - bank(1); - break; - - case 0x0FF8: - // Set the current bank to the third 4k bank - bank(2); - break; - - case 0x0FF9: - // Set the current bank to the forth 4k bank - bank(3); - break; - - default: - break; - } - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6SC::poke(uInt16 address, uInt8 value) -{ - // Switch banks if necessary - switch(address & 0x0FFF) - { - case 0x0FF6: - // Set the current bank to the first 4k bank - bank(0); - return false; - - case 0x0FF7: - // Set the current bank to the second 4k bank - bank(1); - return false; - - case 0x0FF8: - // Set the current bank to the third 4k bank - bank(2); - return false; - - case 0x0FF9: - // Set the current bank to the forth 4k bank - bank(3); - return false; - - default: - break; - } - - if(!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], address, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6SC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF6 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1FF6U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF6SC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF6SC::bankCount() const -{ - return 4; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6SC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF6SC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6SC::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF6SC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF6SC::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF6SC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; + myRamMask = RAM_SIZE - 1; } diff --git a/src/emucore/CartF6SC.hxx b/src/emucore/CartF6SC.hxx index 45a7c5ac3..4365036bb 100644 --- a/src/emucore/CartF6SC.hxx +++ b/src/emucore/CartF6SC.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF6SC_HXX #define CARTRIDGEF6SC_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartF6.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF6SCWidget.hxx" #endif @@ -31,9 +28,9 @@ class System; RAM. There are four 4K banks, accessible by read/write to $1FF6 - $1FF9. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF6SC : public Cartridge +class CartridgeF6SC : public CartridgeF6 { friend class CartridgeF6SCWidget; @@ -45,77 +42,13 @@ class CartridgeF6SC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF6SC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 16_KB); virtual ~CartridgeF6SC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,32 +68,12 @@ class CartridgeF6SC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 16K ROM image of the cartridge - std::array myImage; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + // RAM mask + static constexpr uInt16 RAM_MASK = RAM_SIZE - 1; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartF8.cxx b/src/emucore/CartF8.cxx index 34e8ae7d7..732cb306d 100644 --- a/src/emucore/CartF8.cxx +++ b/src/emucore/CartF8.cxx @@ -15,172 +15,34 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF8.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF8::CartridgeF8(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8::reset() +bool CartridgeF8::checkSwitchBank(uInt16 address, uInt8) { - initializeStartBank(1); - - // Upon reset we switch to the reset bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8::install(System& system) -{ - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF8::peek(uInt16 address) -{ - address &= 0x0FFF; - // Switch banks if necessary switch(address) { - case 0x0FF8: + case 0x1FF8: // Set the current bank to the lower 4k bank bank(0); - break; + return true; - case 0x0FF9: + case 0x1FF9: // Set the current bank to the upper 4k bank bank(1); - break; - - default: - break; - } - - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8::poke(uInt16 address, uInt8) -{ - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0FF9: - // Set the current bank to the upper 4k bank - bank(1); - break; + return true; default: break; } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1000; addr < static_cast(0x1FF8U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF8::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF8::bankCount() const -{ - return 2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF8::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeF8::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeF8::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartF8.hxx b/src/emucore/CartF8.hxx index b586d70ff..90b34497a 100644 --- a/src/emucore/CartF8.hxx +++ b/src/emucore/CartF8.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF8_HXX #define CARTRIDGEF8_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF8Widget.hxx" #endif @@ -30,9 +27,9 @@ class System; Cartridge class used for Atari's 8K bankswitched games. There are two 4K banks, accessible by read/write to $1FF8 - $1FF9. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF8 : public Cartridge +class CartridgeF8 : public CartridgeEnhanced { friend class CartridgeF8Widget; @@ -44,77 +41,13 @@ class CartridgeF8 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF8(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~CartridgeF8() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -134,29 +67,12 @@ class CartridgeF8 : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 8K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + uInt16 hotspot() const override { return 0x1FF8; } + + uInt16 getStartBank() const override { return 1; } private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartF8SC.cxx b/src/emucore/CartF8SC.cxx index d07cf9cb7..9607d9687 100644 --- a/src/emucore/CartF8SC.cxx +++ b/src/emucore/CartF8SC.cxx @@ -15,223 +15,13 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "System.hxx" #include "CartF8SC.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeF8SC::CartridgeF8SC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeF8(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SC::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(1); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeF8SC::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x007F]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x007F]; - access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeF8SC::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0FF9: - // Set the current bank to the upper 4k bank - bank(1); - break; - - default: - break; - } - - if(address < 0x0080) // Write port is at 0xF000 - 0xF07F (128 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8SC::poke(uInt16 address, uInt8 value) -{ - // Switch banks if necessary - switch(address & 0x0FFF) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - return false; - - case 0x0FF9: - // Set the current bank to the upper 4k bank - bank(1); - return false; - - default: - break; - } - - if (!(address & 0x080)) - { - pokeRAM(myRAM[address & 0x007F], address, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8SC::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1100; addr < static_cast(0x1FF8U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF8SC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeF8SC::bankCount() const -{ - return 2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8SC::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0100) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x007F] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeF8SC::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8SC::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF8SC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeF8SC::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeF8SC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + myRamSize = RAM_SIZE; } diff --git a/src/emucore/CartF8SC.hxx b/src/emucore/CartF8SC.hxx index 592637d3d..3eb3539ae 100644 --- a/src/emucore/CartF8SC.hxx +++ b/src/emucore/CartF8SC.hxx @@ -18,10 +18,7 @@ #ifndef CARTRIDGEF8SC_HXX #define CARTRIDGEF8SC_HXX -class System; - -#include "bspf.hxx" -#include "Cart.hxx" +#include "CartF8.hxx" #ifdef DEBUGGER_SUPPORT #include "CartF8SCWidget.hxx" #endif @@ -31,9 +28,9 @@ class System; RAM. There are two 4K banks, accessible by read/write to $1FF8 - $1FF9. RAM read port is $1080 - $10FF, write port is $1000 - $107F. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeF8SC : public Cartridge +class CartridgeF8SC : public CartridgeF8 { friend class CartridgeF8SCWidget; @@ -45,77 +42,13 @@ class CartridgeF8SC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeF8SC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~CartridgeF8SC() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,32 +68,9 @@ class CartridgeF8SC : public Cartridge } #endif - public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; - private: - // The 8K ROM image of the cartridge - std::array myImage; - - // The 128 bytes of RAM - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + // RAM size + static constexpr size_t RAM_SIZE = 0x80; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartFA.cxx b/src/emucore/CartFA.cxx index eeef63016..ec242f615 100644 --- a/src/emucore/CartFA.cxx +++ b/src/emucore/CartFA.cxx @@ -20,228 +20,21 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFA::CartridgeFA(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); + myRamSize = RAM_SIZE; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA::reset() -{ - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(2); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1100; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[addr & 0x00FF]; - mySystem->setPageAccess(addr, access); - } - - // Set the page accessing method for the RAM reading pages - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1100; addr < 0x1200; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x00FF]; - access.codeAccessBase = &myCodeAccessBase[0x100 + (addr & 0x00FF)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeFA::peek(uInt16 address) -{ - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) - { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - break; - - case 0x0FF9: - // Set the current bank to the middle 4k bank - bank(1); - break; - - case 0x0FFA: - // Set the current bank to the upper 4k bank - bank(2); - break; - - default: - break; - } - - if(address < 0x0100) // Write port is at 0xF000 - 0xF0FF (256 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA::poke(uInt16 address, uInt8 value) +bool CartridgeFA::checkSwitchBank(uInt16 address, uInt8) { // Switch banks if necessary - switch(address & 0x0FFF) + if((address >= 0x1FF8) && (address <= 0x1FFA)) { - case 0x0FF8: - // Set the current bank to the lower 4k bank - bank(0); - return false; - - case 0x0FF9: - // Set the current bank to the middle 4k bank - bank(1); - return false; - - case 0x0FFA: - // Set the current bank to the upper 4k bank - bank(2); - return false; - - default: - break; - } - - if (!(address & 0x100)) - { - pokeRAM(myRAM[address & 0x00FF], address, value); + bank(address - 0x1FF8); return true; } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1200; addr < static_cast(0x1FF8U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFA::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFA::bankCount() const -{ - return 3; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0200) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x00FF] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeFA::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeFA::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeFA::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + return false; } diff --git a/src/emucore/CartFA.hxx b/src/emucore/CartFA.hxx index 9729a366f..d234de743 100644 --- a/src/emucore/CartFA.hxx +++ b/src/emucore/CartFA.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartFAWidget.hxx" #endif @@ -31,9 +31,9 @@ class System; banks, accessible by read/write at $1FF8 - $1FFA, and 256 bytes of RAM. RAM read port is $1100 - $11FF, write port is $1000 - $10FF. - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeFA : public Cartridge +class CartridgeFA : public CartridgeEnhanced { friend class CartridgeFAWidget; @@ -45,77 +45,13 @@ class CartridgeFA : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeFA(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 12_KB); virtual ~CartridgeFA() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -135,32 +71,16 @@ class CartridgeFA : public Cartridge } #endif - public: - /** - Get the byte at the specified address. + private: + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; + uInt16 hotspot() const override { return 0x1FF8; } - /** - Change the byte at the specified address to the given value - - @param address The address where the value should be stored - @param value The value to be stored at the address - @return True if the poke changed the device address space, else false - */ - bool poke(uInt16 address, uInt8 value) override; + uInt16 getStartBank() const override { return 2; } private: - // The 12K ROM image of the cartridge - std::array myImage; - - // The 256 bytes of RAM on the cartridge - std::array myRAM; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; + // RAM size + static constexpr size_t RAM_SIZE = 0x100; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartFA2.cxx b/src/emucore/CartFA2.cxx index ce83f4c78..2443b106a 100644 --- a/src/emucore/CartFA2.cxx +++ b/src/emucore/CartFA2.cxx @@ -15,300 +15,67 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "OSystem.hxx" -#include "Serializer.hxx" -#include "System.hxx" #include "TimerManager.hxx" #include "CartFA2.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFA2::CartridgeFA2(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeFA(image, size, md5, settings, bsSize) { // 29/32K version of FA2 has valid data @ 1K - 29K const uInt8* img_ptr = image.get(); if(size >= 29_KB) + { img_ptr += 1_KB; - else if(size < mySize) - mySize = size; + mySize = 28_KB; + } + + // Allocate array for the ROM image + myImage = make_unique(mySize); // Copy the ROM image into my buffer - std::copy_n(img_ptr, mySize, myImage.begin()); - createCodeAccessBase(mySize); + std::copy_n(img_ptr, mySize, myImage.get()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA2::reset() +bool CartridgeFA2::checkSwitchBank(uInt16 address, uInt8) { - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); - - // Upon reset we switch to the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFA2::install(System& system) -{ - mySystem = &system; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - access.type = System::PageAccessType::WRITE; - for(uInt16 addr = 0x1000; addr < 0x1100; addr += System::PAGE_SIZE) + // Switch banks if necessary + if((address >= 0x1FF5) && (address <= 0x1FFB)) { - access.codeAccessBase = &myCodeAccessBase[addr & 0x00FF]; - mySystem->setPageAccess(addr, access); + bank(address - 0x1FF5); + return true; } - - // Set the page accessing method for the RAM reading pages - access.directPokeBase = nullptr; - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1100; addr < 0x1200; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myRAM[addr & 0x00FF]; - access.codeAccessBase = &myCodeAccessBase[0x100 + (addr & 0x00FF)]; - mySystem->setPageAccess(addr, access); - } - - // Install pages for the startup bank - bank(startBank()); + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeFA2::peek(uInt16 address) { - uInt16 peekAddress = address; - address &= 0x0FFF; - - // Switch banks if necessary - switch(address) + if((address & ROM_MASK) == 0x0FF4) { - case 0x0FF4: - // Load/save RAM to/from Harmony cart flash - if(mySize == 28_KB && !bankLocked()) - return ramReadWrite(); - break; - - case 0x0FF5: - // Set the current bank to the first 4k bank - bank(0); - break; - - case 0x0FF6: - // Set the current bank to the second 4k bank - bank(1); - break; - - case 0x0FF7: - // Set the current bank to the third 4k bank - bank(2); - break; - - case 0x0FF8: - // Set the current bank to the fourth 4k bank - bank(3); - break; - - case 0x0FF9: - // Set the current bank to the fifth 4k bank - bank(4); - break; - - case 0x0FFA: - // Set the current bank to the sixth 4k bank - bank(5); - break; - - case 0x0FFB: - // Set the current bank to the seventh 4k bank - // This is only available on 28K ROMs - if(mySize == 28_KB) bank(6); - break; - - default: - break; + // Load/save RAM to/from Harmony cart flash + if(mySize == 28_KB && !bankLocked()) + return ramReadWrite(); } - if(address < 0x0100) // Write port is at 0xF000 - 0xF0FF (256 bytes) - return peekRAM(myRAM[address], peekAddress); - else - return myImage[myBankOffset + address]; + return CartridgeEnhanced::peek(address); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFA2::poke(uInt16 address, uInt8 value) { - // Switch banks if necessary - switch(address & 0x0FFF) + if((address & ROM_MASK) == 0x0FF4) { - case 0x0FF4: - // Load/save RAM to/from Harmony cart flash - if(mySize == 28_KB && !bankLocked()) - ramReadWrite(); - return false; - - case 0x0FF5: - // Set the current bank to the first 4k bank - bank(0); - return false; - - case 0x0FF6: - // Set the current bank to the second 4k bank - bank(1); - return false; - - case 0x0FF7: - // Set the current bank to the third 4k bank - bank(2); - return false; - - case 0x0FF8: - // Set the current bank to the fourth 4k bank - bank(3); - return false; - - case 0x0FF9: - // Set the current bank to the fifth 4k bank - bank(4); - return false; - - case 0x0FFA: - // Set the current bank to the sixth 4k bank - bank(5); - return false; - - case 0x0FFB: - // Set the current bank to the seventh 4k bank - // This is only available on 28K ROMs - if(mySize == 28_KB) bank(6); - return false; - - default: - break; - } - - if(!(address & 0x100)) - { - pokeRAM(myRAM[address & 0x00FF], address, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA2::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for(uInt16 addr = (0x1FF4 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for(uInt16 addr = 0x1200; addr < static_cast(0x1FF4U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFA2::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFA2::bankCount() const -{ - return uInt16(mySize / 4_KB); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA2::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - if(address < 0x0200) - { - // Normally, a write to the read port won't do anything - // However, the patch command is special in that ignores such - // cart restrictions - myRAM[address & 0x00FF] = value; - } - else - myImage[myBankOffset + address] = value; - - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeFA2::getImage(size_t& size) const -{ - size = mySize; - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA2::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - out.putByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeFA2::save" << endl; + // Load/save RAM to/from Harmony cart flash + if(mySize == 28_KB && !bankLocked()) + ramReadWrite(); return false; } - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFA2::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); - } - catch(...) - { - cerr << "ERROR: CartridgeFA2::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; + return CartridgeEnhanced::poke(address, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -353,11 +120,11 @@ uInt8 CartridgeFA2::ramReadWrite() { try { - serializer.getByteArray(myRAM.data(), myRAM.size()); + serializer.getByteArray(myRAM.get(), myRamSize); } catch(...) { - myRAM.fill(0); + std::fill_n(myRAM.get(), myRamSize, 0); } myRamAccessTimeout += 500; // Add 0.5 ms delay for read } @@ -365,7 +132,7 @@ uInt8 CartridgeFA2::ramReadWrite() { try { - serializer.putByteArray(myRAM.data(), myRAM.size()); + serializer.putByteArray(myRAM.get(), myRamSize); } catch(...) { @@ -376,7 +143,7 @@ uInt8 CartridgeFA2::ramReadWrite() } } // Bit 6 is 1, busy - return myImage[myBankOffset + 0xFF4] | 0x40; + return myImage[myCurrentSegOffset[0] + 0xFF4] | 0x40; } else { @@ -387,11 +154,11 @@ uInt8 CartridgeFA2::ramReadWrite() myRAM[255] = 0; // Successful operation // Bit 6 is 0, ready/success - return myImage[myBankOffset + 0xFF4] & ~0x40; + return myImage[myCurrentSegOffset[0] + 0xFF4] & ~0x40; } else // Bit 6 is 1, busy - return myImage[myBankOffset + 0xFF4] | 0x40; + return myImage[myCurrentSegOffset[0] + 0xFF4] | 0x40; } } @@ -416,18 +183,18 @@ void CartridgeFA2::flash(uInt8 operation) { try { - serializer.getByteArray(myRAM.data(), myRAM.size()); + serializer.getByteArray(myRAM.get(), myRamSize); } catch(...) { - myRAM.fill(0); + std::fill_n(myRAM.get(), myRamSize, 0); } } else if(operation == 2) // write { try { - serializer.putByteArray(myRAM.data(), myRAM.size()); + serializer.putByteArray(myRAM.get(), myRamSize); } catch(...) { diff --git a/src/emucore/CartFA2.hxx b/src/emucore/CartFA2.hxx index ea19b0d43..ea60fbe45 100644 --- a/src/emucore/CartFA2.hxx +++ b/src/emucore/CartFA2.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartFA.hxx" #ifdef DEBUGGER_SUPPORT #include "CartFA2Widget.hxx" #endif @@ -43,9 +43,9 @@ class System; by the emulator. Also supported is a 32K variant. In any event, only data at 1K - 29K of the ROM is used. - @author Chris D. Walton + @author Chris D. Walton, Thomas Jentzsch */ -class CartridgeFA2 : public Cartridge +class CartridgeFA2 : public CartridgeFA { friend class CartridgeFA2Widget; @@ -57,77 +57,13 @@ class CartridgeFA2 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the settings object + @param bsSize The size specified by the bankswitching scheme */ CartridgeFA2(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 28_KB); virtual ~CartridgeFA2() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -173,6 +109,12 @@ class CartridgeFA2 : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; + + uInt16 hotspot() const override { return 0x1FF5; } + + uInt16 getStartBank() const override { return 0; } + /** Either load or save internal RAM to Harmony flash (represented by a file in emulation). @@ -192,15 +134,6 @@ class CartridgeFA2 : public Cartridge void flash(uInt8 operation); private: - // The 24K/28K ROM image of the cartridge - std::array myImage; - - // Actual usable size of the ROM image - size_t mySize{28_KB}; - - // The 256 bytes of RAM on the cartridge - std::array myRAM; - // The time after which the first request of a load/save operation // will actually be completed // Due to flash RAM constraints, a read/write isn't instantaneous, @@ -211,9 +144,6 @@ class CartridgeFA2 : public Cartridge // of internal RAM to Harmony cart flash string myFlashFile; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; - private: // Following constructors and assignment operators not supported CartridgeFA2() = delete; diff --git a/src/emucore/CartFC.cxx b/src/emucore/CartFC.cxx index 251ea5a30..1b431592e 100644 --- a/src/emucore/CartFC.cxx +++ b/src/emucore/CartFC.cxx @@ -20,53 +20,38 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFC::CartridgeFC(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, + bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFC::reset() { - initializeStartBank(0); + CartridgeEnhanced::reset(); + myTargetBank = 0; - - // Upon reset we switch to the reset bank - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFC::install(System& system) +bool CartridgeFC::checkSwitchBank(uInt16 address, uInt8) { - mySystem = &system; - - // Install pages for the startup bank - bank(startBank()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeFC::peek(uInt16 address) -{ - address &= 0x0FFF; - // Switch banks if necessary - if(address == 0x0FFC) + if(address == 0x1FFC) { // Trigger the bank switch bank(myTargetBank); + return true; } - - return myImage[myBankOffset + address]; + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFC::poke(uInt16 address, uInt8 value) { - address &= 0x0FFF; + address &= myBankMask; // Switch banks if necessary switch (address) @@ -78,114 +63,18 @@ bool CartridgeFC::poke(uInt16 address, uInt8 value) case 0x0FF9: // Set the high bits of target 4k bank - if (value << 2 < bankCount()) + if (value << 2 < romBankCount()) { myTargetBank += value << 2; - myTargetBank %= bankCount(); + myTargetBank %= romBankCount(); } else // special handling when both values are identical (e.g. 4/4 or 5/5) - myTargetBank = value % bankCount(); - break; - - case 0x0FFC: - // Trigger the bank switch - bank(myTargetBank); + myTargetBank = value % romBankCount(); break; default: - break; + checkSwitchBank(address); } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFC::bank(uInt16 bank) -{ - if (bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - System::PageAccess access(this, System::PageAccessType::READ); - - // Set the page accessing methods for the hot spots - for (uInt16 addr = (0x1FF8 & ~System::PAGE_MASK); addr < 0x2000; - addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - - // Setup the page access methods for the current bank - for (uInt16 addr = 0x1000; addr < static_cast(0x1FF8U & ~System::PAGE_MASK); - addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - myCurrentBank = myTargetBank; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFC::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFC::bankCount() const -{ - return uInt16(mySize >> 12); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFC::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeFC::getImage(size_t& size) const -{ - size = mySize; - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFC::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch (...) - { - cerr << "ERROR: CartridgeFC::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFC::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch (...) - { - cerr << "ERROR: CartridgeFC::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartFC.hxx b/src/emucore/CartFC.hxx index cc96d0131..92be2a421 100644 --- a/src/emucore/CartFC.hxx +++ b/src/emucore/CartFC.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartFCWidget.hxx" @@ -30,12 +30,12 @@ class System; /** Cartridge class used for Amiga's 32K Power Play Arcade Video Game Album. There are eight 4K banks, writing to $1FF8 definies the two lowest bits - of the wanted bank, writeing to $1FF9 defines the high bits. Reading from + of the wanted bank, writeing to $1FF9 defines the high bits. Accessing $1FFC triggers the bank switching @author Thomas Jentzsch */ -class CartridgeFC : public Cartridge +class CartridgeFC : public CartridgeEnhanced { friend class CartridgeFCWidget; @@ -47,9 +47,11 @@ class CartridgeFC : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ CartridgeFC(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~CartridgeFC() = default; public: @@ -58,66 +60,6 @@ class CartridgeFC : public Cartridge */ void reset() override; - /** - Install cartridge in the specified system. Invoked by the system - when the cartridge is attached to it. - - @param system The system the device should install itself in - */ - void install(System& system) override; - - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -138,13 +80,6 @@ class CartridgeFC : public Cartridge #endif public: - /** - Get the byte at the specified address. - - @return The byte at the specified address - */ - uInt8 peek(uInt16 address) override; - /** Change the byte at the specified address to the given value @@ -155,17 +90,9 @@ class CartridgeFC : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // The 32K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Size of the ROM image - size_t mySize{0}; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; - - // Indicates which bank is currently active for the first segment - uInt16 myCurrentBank{0}; + uInt16 hotspot() const override { return 0x1FF8; } // Target bank defined by writing to $1FF8/9 uInt16 myTargetBank{0}; diff --git a/src/emucore/CartFE.cxx b/src/emucore/CartFE.cxx index 454cf4427..d0c01886b 100644 --- a/src/emucore/CartFE.cxx +++ b/src/emucore/CartFE.cxx @@ -21,49 +21,53 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeFE::CartridgeFE(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); + myDirectPeek = false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFE::reset() { - // Decathlon requires this, since there is no startup vector in bank 1 - initializeStartBank(0); - - bank(startBank()); + CartridgeEnhanced::reset(); myLastAccessWasFE = false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeFE::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // The hotspot $01FE is in a mirror of zero-page RAM // We need to claim access to it here, and deal with it in peek/poke below System::PageAccess access(this, System::PageAccessType::READWRITE); for(uInt16 addr = 0x180; addr < 0x200; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Map all of the cart accesses to call peek and poke - access.type = System::PageAccessType::READ; - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - mySystem->setPageAccess(addr, access); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeFE::checkSwitchBank(uInt16 address, uInt8 value) +{ + if(myLastAccessWasFE) + { + bank((value & 0x20) ? 0 : 1); + myLastAccessWasFE = false; // was: address == 0x01FE; + return true; + } + myLastAccessWasFE = address == 0x01FE; + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeFE::peek(uInt16 address) { uInt8 value = (address < 0x200) ? mySystem->m6532().peek(address) : - myImage[myBankOffset + (address & 0x0FFF)]; + myImage[myCurrentSegOffset[(address & myBankMask) >> myBankShift] + (address & myBankMask)]; // Check if we hit hotspot - checkBankSwitch(address, value); + checkSwitchBank(address, value); return value; } @@ -75,70 +79,17 @@ bool CartridgeFE::poke(uInt16 address, uInt8 value) mySystem->m6532().poke(address, value); // Check if we hit hotspot - checkBankSwitch(address, value); + checkSwitchBank(address, value); return false; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeFE::checkBankSwitch(uInt16 address, uInt8 value) -{ - if(bankLocked()) - return; - - // Did we detect $01FE on the last address bus access? - // If so, we bankswitch according to the upper 3 bits of the data bus - // NOTE: see the header file for the significance of 'value & 0x20' - if(myLastAccessWasFE) - bank((value & 0x20) ? 0 : 1); - - // On the next cycle, we use the (then) current data bus value to decode - // the bank to use - myLastAccessWasFE = address == 0x01FE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFE::bank(uInt16 bank) -{ - if(bankLocked()) - return false; - - myBankOffset = bank << 12; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFE::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeFE::bankCount() const -{ - return 2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeFE::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeFE::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::save(Serializer& out) const { + CartridgeEnhanced::save(out); try { - out.putShort(myBankOffset); out.putBool(myLastAccessWasFE); } catch(...) @@ -153,14 +104,14 @@ bool CartridgeFE::save(Serializer& out) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeFE::load(Serializer& in) { + CartridgeEnhanced::load(in); try { - myBankOffset = in.getShort(); myLastAccessWasFE = in.getBool(); } catch(...) { - cerr << "ERROR: CartridgeF8SC::load" << endl; + cerr << "ERROR: CartridgeFE::load" << endl; return false; } diff --git a/src/emucore/CartFE.hxx b/src/emucore/CartFE.hxx index dabfafdf4..77ebee767 100644 --- a/src/emucore/CartFE.hxx +++ b/src/emucore/CartFE.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartFEWidget.hxx" #endif @@ -72,10 +72,10 @@ class System; particular *why* the address $01FE will be placed on the address bus after both the JSR and RTS opcodes. - @author Stephen Anthony; with ideas/research from Christian Speckner and - alex_79 and TomSon (of AtariAge) + @author Stephen Anthony, Thomas Jentzsch; with ideas/research from Christian + Speckner and alex_79 and TomSon (of AtariAge) */ -class CartridgeFE : public Cartridge +class CartridgeFE : public CartridgeEnhanced { friend class CartridgeFEWidget; @@ -87,9 +87,10 @@ class CartridgeFE : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeFE(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~CartridgeFE() = default; public: @@ -106,42 +107,6 @@ class CartridgeFE : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - /** Save the current state of this cart to the given Serializer. @@ -194,20 +159,16 @@ class CartridgeFE : public Cartridge */ bool poke(uInt16 address, uInt8 value) override; - private: + protected: /** Perform bankswitch when necessary, by monitoring for $01FE on the address bus and getting the bank number from the data bus. */ - void checkBankSwitch(uInt16 address, uInt8 value); + bool checkSwitchBank(uInt16 address, uInt8 value) override; + + uInt16 hotspot() const override { return 0x01FE; } private: - // The 8K ROM image of the cartridge - std::array myImage; - - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; - // Whether previous address by peek/poke equals $01FE (hotspot) bool myLastAccessWasFE{false}; diff --git a/src/emucore/CartMDM.cxx b/src/emucore/CartMDM.cxx index da6ddbf3a..f92563ec2 100644 --- a/src/emucore/CartMDM.cxx +++ b/src/emucore/CartMDM.cxx @@ -20,31 +20,17 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeMDM::CartridgeMDM(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, + bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize) { - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeMDM::reset() -{ - initializeStartBank(0); - - // Upon reset we switch to the startup bank - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeMDM::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // Get the page accessing methods for the hot spots since they overlap // areas within the TIA we'll need to forward requests to the TIA @@ -61,9 +47,18 @@ void CartridgeMDM::install(System& system) System::PageAccess access(this, System::PageAccessType::READWRITE); for(uInt16 addr = 0x0800; addr < 0x0BFF; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Install pages for bank 0 - bank(startBank()); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeMDM::checkSwitchBank(uInt16 address, uInt8) +{ + // Switch banks if necessary + if((address & 0x1C00) == 0x0800) + { + bank(address & 0x0FF); + return true; + } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -71,8 +66,8 @@ uInt8 CartridgeMDM::peek(uInt16 address) { // Because of the way we've set up accessing above, we can only // get here when the addresses are from 0x800 - 0xBFF - if((address & 0x1C00) == 0x0800) - bank(address & 0x0FF); + + checkSwitchBank(address); int hotspot = ((address & 0x0F00) >> 8) - 8; return myHotSpotPageAccess[hotspot].device->peek(address); @@ -85,8 +80,7 @@ bool CartridgeMDM::poke(uInt16 address, uInt8 value) // about those below $1000 if(!(address & 0x1000)) { - if((address & 0x1C00) == 0x0800) - bank(address & 0x0FF); + checkSwitchBank(address); int hotspot = ((address & 0x0F00) >> 8) - 8; myHotSpotPageAccess[hotspot].device->poke(address, value); @@ -96,24 +90,11 @@ bool CartridgeMDM::poke(uInt16 address, uInt8 value) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeMDM::bank(uInt16 bank) +bool CartridgeMDM::bank(uInt16 bank, uInt16) { if(bankLocked() || myBankingDisabled) return false; - // Remember what bank we're in - // Wrap around to a valid bank number if necessary - myBankOffset = (bank % bankCount()) << 12; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } + CartridgeEnhanced::bank(bank); // Accesses above bank 127 disable further bankswitching; we're only // concerned with the lower byte @@ -121,38 +102,12 @@ bool CartridgeMDM::bank(uInt16 bank) return myBankChanged = true; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeMDM::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeMDM::bankCount() const -{ - return uInt16(mySize >> 12); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeMDM::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeMDM::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMDM::save(Serializer& out) const { + CartridgeEnhanced::save(out); try { - out.putInt(myBankOffset); out.putBool(myBankingDisabled); } catch(...) @@ -167,9 +122,9 @@ bool CartridgeMDM::save(Serializer& out) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeMDM::load(Serializer& in) { + CartridgeEnhanced::load(in); try { - myBankOffset = in.getInt(); myBankingDisabled = in.getBool(); } catch(...) @@ -178,8 +133,5 @@ bool CartridgeMDM::load(Serializer& in) return false; } - // Remember what bank we were in - bank(myBankOffset >> 12); - return true; } diff --git a/src/emucore/CartMDM.hxx b/src/emucore/CartMDM.hxx index 1c2a34cb6..4e12571e1 100644 --- a/src/emucore/CartMDM.hxx +++ b/src/emucore/CartMDM.hxx @@ -19,7 +19,7 @@ #define CARTRIDGEMDM_HXX #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #include "System.hxx" #ifdef DEBUGGER_SUPPORT #include "CartMDMWidget.hxx" @@ -42,9 +42,9 @@ Therefore, there are 128 banks / 512K possible in total. - @author Stephen Anthony, based on 0840 scheme by Fred X. Quimby + @author Stephen Anthony, Thomas Jentzsch, based on 0840 scheme by Fred X. Quimby */ -class CartridgeMDM : public Cartridge +class CartridgeMDM : public CartridgeEnhanced { friend class CartridgeMDMWidget; @@ -56,17 +56,14 @@ class CartridgeMDM : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ CartridgeMDM(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~CartridgeMDM() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -78,38 +75,12 @@ class CartridgeMDM : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Save the current state of this cart to the given Serializer. @@ -134,6 +105,8 @@ class CartridgeMDM : public Cartridge */ string name() const override { return "CartridgeMDM"; } + uInt16 hotspot() const override { return 0x0800; } + #ifdef DEBUGGER_SUPPORT /** Get debugger widget responsible for accessing the inner workings @@ -164,18 +137,12 @@ class CartridgeMDM : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // Pointer to a dynamically allocated ROM image of the cartridge - ByteBuffer myImage; - - // Size of the ROM image - size_t mySize{0}; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; + private: // Previous Device's page access std::array myHotSpotPageAccess; - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; - // Indicates whether banking has been disabled due to a bankswitch // above bank 127 bool myBankingDisabled{false}; diff --git a/src/emucore/CartMNetwork.cxx b/src/emucore/CartMNetwork.cxx index cffec53b6..78c68e6a0 100644 --- a/src/emucore/CartMNetwork.cxx +++ b/src/emucore/CartMNetwork.cxx @@ -34,9 +34,9 @@ void CartridgeMNetwork::initialize(const ByteBuffer& image, size_t size) // Copy the ROM image into my buffer std::copy_n(image.get(), std::min(romSize(), size), myImage.get()); - createCodeAccessBase(romSize() + myRAM.size()); + createRomAccessArrays(romSize() + myRAM.size()); - myRAMSlice = bankCount() - 1; + myRAMBank = romBankCount() - 1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -70,7 +70,9 @@ void CartridgeMNetwork::setAccess(uInt16 addrFrom, uInt16 size, access.directPeekBase = &directData[directOffset + (addr & addrMask)]; else if(type == System::PageAccessType::WRITE) // all RAM writes mapped to ::poke() access.directPokeBase = nullptr; - access.codeAccessBase = &myCodeAccessBase[codeOffset + (addr & addrMask)]; + access.romAccessBase = &myRomAccessBase[codeOffset + (addr & addrMask)]; + access.romPeekCounter = &myRomAccessCounter[codeOffset + (addr & addrMask)]; + access.romPokeCounter = &myRomAccessCounter[codeOffset + (addr & addrMask) + myAccessSize]; mySystem->setPageAccess(addr, access); } } @@ -86,16 +88,18 @@ void CartridgeMNetwork::install(System& system) for(uInt16 addr = (0x1FE0 & ~System::PAGE_MASK); addr < 0x2000; addr += System::PAGE_SIZE) { - access.codeAccessBase = &myCodeAccessBase[0x1fc0]; + access.romAccessBase = &myRomAccessBase[0x1fc0]; + access.romPeekCounter = &myRomAccessCounter[0x1fc0]; + access.romPokeCounter = &myRomAccessCounter[0x1fc0 + myAccessSize]; mySystem->setPageAccess(addr, access); } /*setAccess(0x1FE0 & ~System::PAGE_MASK, System::PAGE_SIZE, 0, nullptr, 0x1fc0, System::PA_NONE, 0x1fc0);*/ - // Setup the second segment to always point to the last ROM slice + // Setup the second segment to always point to the last ROM bank setAccess(0x1A00, 0x1FE0U & (~System::PAGE_MASK - 0x1A00), - myRAMSlice * BANK_SIZE, myImage.get(), myRAMSlice * BANK_SIZE, System::PageAccessType::READ, BANK_SIZE - 1); - myCurrentSlice[1] = myRAMSlice; + myRAMBank * BANK_SIZE, myImage.get(), myRAMBank * BANK_SIZE, System::PageAccessType::READ, BANK_SIZE - 1); + myCurrentBank[1] = myRAMBank; // Install some default banks for the RAM and first segment bankRAM(0); @@ -111,7 +115,7 @@ uInt8 CartridgeMNetwork::peek(uInt16 address) // Switch banks if necessary checkSwitchBank(address); - if((myCurrentSlice[0] == myRAMSlice) && (address < BANK_SIZE / 2)) + if((myCurrentBank[0] == myRAMBank) && (address < BANK_SIZE / 2)) { // Reading from the 1K write port @ $1000 triggers an unwanted write return peekRAM(myRAM[address & (BANK_SIZE / 2 - 1)], peekAddress); @@ -122,7 +126,7 @@ uInt8 CartridgeMNetwork::peek(uInt16 address) return peekRAM(myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)], peekAddress); } else - return myImage[(myCurrentSlice[address >> 11] << 11) + (address & (BANK_SIZE - 1))]; + return myImage[(myCurrentBank[address >> 11] << 11) + (address & (BANK_SIZE - 1))]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -135,15 +139,44 @@ bool CartridgeMNetwork::poke(uInt16 address, uInt8 value) checkSwitchBank(address); // All RAM writes are mapped here - if((myCurrentSlice[0] == myRAMSlice) && (address < BANK_SIZE / 2)) + if((myCurrentBank[0] == myRAMBank) && (address < BANK_SIZE / 2)) { - pokeRAM(myRAM[address & (BANK_SIZE / 2 - 1)], pokeAddress, value); - return true; + // RAM banks + if(!(address & 0x0400)) + { + pokeRAM(myRAM[address & (BANK_SIZE / 2 - 1)], pokeAddress, value); + return true; + } + else + { + // Writing to the read port should be ignored, but trigger a break if option enabled + uInt8 dummy; + + pokeRAM(dummy, pokeAddress, value); + myRamWriteAccess = pokeAddress; + return false; + } } - else if((address >= 0x0800) && (address <= 0x08FF)) + else { - pokeRAM(myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)], pokeAddress, value); - return true; + // fixed 256 bytes of RAM + if((address >= 0x0800) && (address <= 0x09FF)) + { + if(!(address & 0x100)) + { + pokeRAM(myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)], pokeAddress, value); + return true; + } + else + { + // Writing to the read port should be ignored, but trigger a break if option enabled + uInt8 dummy; + + pokeRAM(dummy, pokeAddress, value); + myRamWriteAccess = pokeAddress; + return false; + } + } } return false; @@ -156,7 +189,7 @@ void CartridgeMNetwork::bankRAM(uInt16 bank) // Remember what bank we're in myCurrentRAM = bank; - uInt16 offset = bank << 8; // * RAM_SLICE_SIZE (256) + uInt16 offset = bank << 8; // * RAM_BANK_SIZE (256) // Setup the page access methods for the current bank // Set the page accessing method for the 256 bytes of RAM reading pages @@ -168,26 +201,26 @@ void CartridgeMNetwork::bankRAM(uInt16 bank) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeMNetwork::bank(uInt16 slice) +bool CartridgeMNetwork::bank(uInt16 bank, uInt16) { if(bankLocked()) return false; // Remember what bank we're in - myCurrentSlice[0] = slice; + myCurrentBank[0] = bank; // Setup the page access methods for the current bank - if(slice != myRAMSlice) + if(bank != myRAMBank) { - uInt16 offset = slice << 11; // * BANK_SIZE (2048) + uInt16 offset = bank << 11; // * BANK_SIZE (2048) // Map ROM image into first segment setAccess(0x1000, BANK_SIZE, offset, myImage.get(), offset, System::PageAccessType::READ); } else { - // Set the page accessing method for the 1K slice of RAM writing pages + // Set the page accessing method for the 1K bank of RAM writing pages setAccess(0x1000, BANK_SIZE / 2, 0, myRAM.data(), romSize(), System::PageAccessType::WRITE); - // Set the page accessing method for the 1K slice of RAM reading pages + // Set the page accessing method for the 1K bank of RAM reading pages setAccess(0x1000 + BANK_SIZE / 2, BANK_SIZE / 2, 0, myRAM.data(), romSize(), System::PageAccessType::READ); } return myBankChanged = true; @@ -196,7 +229,7 @@ bool CartridgeMNetwork::bank(uInt16 slice) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt16 CartridgeMNetwork::getBank(uInt16 address) const { - return myCurrentSlice[(address & 0xFFF) >> 11]; // 2K slices + return myCurrentBank[(address & 0xFFF) >> 11]; // 2K segments } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -206,7 +239,7 @@ bool CartridgeMNetwork::patch(uInt16 address, uInt8 value) if(address < 0x0800) { - if(myCurrentSlice[0] == myRAMSlice) + if(myCurrentBank[0] == myRAMBank) { // Normally, a write to the read port won't do anything // However, the patch command is special in that ignores such @@ -214,7 +247,7 @@ bool CartridgeMNetwork::patch(uInt16 address, uInt8 value) myRAM[address & 0x03FF] = value; } else - myImage[(myCurrentSlice[0] << 11) + (address & (BANK_SIZE-1))] = value; + myImage[(myCurrentBank[0] << 11) + (address & (BANK_SIZE-1))] = value; } else if(address < 0x0900) { @@ -224,16 +257,16 @@ bool CartridgeMNetwork::patch(uInt16 address, uInt8 value) myRAM[0x0400 + (myCurrentRAM << 8) + (address & 0x00FF)] = value; } else - myImage[(myCurrentSlice[address >> 11] << 11) + (address & (BANK_SIZE-1))] = value; + myImage[(myCurrentBank[address >> 11] << 11) + (address & (BANK_SIZE-1))] = value; return myBankChanged = true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeMNetwork::getImage(size_t& size) const +const ByteBuffer& CartridgeMNetwork::getImage(size_t& size) const { - size = bankCount() * BANK_SIZE; - return myImage.get(); + size = romBankCount() * BANK_SIZE; + return myImage; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -241,7 +274,7 @@ bool CartridgeMNetwork::save(Serializer& out) const { try { - out.putShortArray(myCurrentSlice.data(), myCurrentSlice.size()); + out.putShortArray(myCurrentBank.data(), myCurrentBank.size()); out.putShort(myCurrentRAM); out.putByteArray(myRAM.data(), myRAM.size()); } @@ -259,7 +292,7 @@ bool CartridgeMNetwork::load(Serializer& in) { try { - in.getShortArray(myCurrentSlice.data(), myCurrentSlice.size()); + in.getShortArray(myCurrentBank.data(), myCurrentBank.size()); myCurrentRAM = in.getShort(); in.getByteArray(myRAM.data(), myRAM.size()); } @@ -271,13 +304,13 @@ bool CartridgeMNetwork::load(Serializer& in) // Set up the previously used banks for the RAM and segment bankRAM(myCurrentRAM); - bank(myCurrentSlice[0]); + bank(myCurrentBank[0]); return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeMNetwork::bankCount() const +uInt16 CartridgeMNetwork::romBankCount() const { return uInt16(mySize >> 11); } @@ -285,5 +318,5 @@ uInt16 CartridgeMNetwork::bankCount() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt16 CartridgeMNetwork::romSize() const { - return bankCount() * BANK_SIZE; + return romBankCount() * BANK_SIZE; } diff --git a/src/emucore/CartMNetwork.hxx b/src/emucore/CartMNetwork.hxx index ad0decad9..9b17a4b67 100644 --- a/src/emucore/CartMNetwork.hxx +++ b/src/emucore/CartMNetwork.hxx @@ -51,7 +51,7 @@ here by accessing 1FE8 to 1FEB. This cart reports having 8 banks; 1 for each of the possible 7 - slices in the lower 2K area, and the last for RAM in the lower + bank in the lower 2K area, and the last for RAM in the lower 2K area." There are 8K, 12K and 16K variations, with or without RAM. @@ -94,9 +94,12 @@ class CartridgeMNetwork : public Cartridge /** Install pages for the specified bank in the system. - @param bank The bank that should be installed in the system + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 segment = 0) override; /** Get the current bank. @@ -106,9 +109,9 @@ class CartridgeMNetwork : public Cartridge uInt16 getBank(uInt16 address = 0) const override; /** - Query the number of banks supported by the cartridge. + Query the number of banks supported by the cartridge. */ - uInt16 bankCount() const override; + uInt16 romBankCount() const override; /** Patch the cartridge ROM. @@ -123,9 +126,9 @@ class CartridgeMNetwork : public Cartridge Access the internal ROM image for this cartridge. @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data + @return A reference to the internal ROM image data */ - const uInt8* getImage(size_t& size) const override; + const ByteBuffer& getImage(size_t& size) const override; /** Save the current state of this cart to the given Serializer. @@ -179,7 +182,7 @@ class CartridgeMNetwork : public Cartridge private: // Size of RAM in the cart static constexpr uInt32 RAM_SIZE = 0x800; // 1K + 4 * 256B = 2K - // Number of slices with 4K address space + // Number of segment within the 4K address space static constexpr uInt32 NUM_SEGMENTS = 2; /** @@ -198,8 +201,6 @@ class CartridgeMNetwork : public Cartridge private: // Pointer to a dynamically allocated ROM image of the cartridge ByteBuffer myImage; - // The 16K ROM image of the cartridge (works for E78K too) - //uInt8 myImage[BANK_SIZE * 8]; // Size of the ROM image size_t mySize{0}; @@ -207,14 +208,14 @@ class CartridgeMNetwork : public Cartridge // The 2K of RAM std::array myRAM; - // Indicates which slice is in the segment - std::array myCurrentSlice; + // Indicates which bank is in the segment + std::array myCurrentBank; // Indicates which 256 byte bank of RAM is being used uInt16 myCurrentRAM{0}; - // The number of the RAM slice (== bankCount() - 1) - uInt32 myRAMSlice{0}; + // The number of the RAM bank (== bankCount() - 1) + uInt32 myRAMBank{0}; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CartSB.cxx b/src/emucore/CartSB.cxx index 796ecfcdf..18d160cff 100644 --- a/src/emucore/CartSB.cxx +++ b/src/emucore/CartSB.cxx @@ -20,31 +20,17 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeSB::CartridgeSB(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(size) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, + bsSize == 0 ? BSPF::nextPowerOfTwo(size) : bsSize) { - // Allocate array for the ROM image - myImage = make_unique(mySize); - - // Copy the ROM image into my buffer - std::copy_n(image.get(), mySize, myImage.get()); - createCodeAccessBase(mySize); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeSB::reset() -{ - initializeStartBank(bankCount() - 1); - - // Upon reset we switch to the startup bank - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeSB::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // Get the page accessing methods for the hot spots since they overlap // areas within the TIA we'll need to forward requests to the TIA @@ -62,19 +48,26 @@ void CartridgeSB::install(System& system) // Set the page accessing methods for the hot spots for(uInt16 addr = 0x0800; addr < 0x0FFF; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Install pages for startup bank - bank(startBank()); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeSB::checkSwitchBank(uInt16 address, uInt8) +{ + // Switch banks if necessary + if((address & 0x1800) == 0x0800) + { + bank(address & (romBankCount() - 1)); + return true; + } + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeSB::peek(uInt16 address) { - address &= (0x17FF + (mySize >> 12)); + address &= (0x17FF + romBankCount()); - // Switch banks if necessary - if ((address & 0x1800) == 0x0800) - bank(address & startBank()); + checkSwitchBank(address); if(!(address & 0x1000)) { @@ -90,11 +83,9 @@ uInt8 CartridgeSB::peek(uInt16 address) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeSB::poke(uInt16 address, uInt8 value) { - address &= (0x17FF + (mySize >> 12)); + address &= (0x17FF + romBankCount()); - // Switch banks if necessary - if((address & 0x1800) == 0x0800) - bank(address & startBank()); + checkSwitchBank(address); if(!(address & 0x1000)) { @@ -105,85 +96,3 @@ bool CartridgeSB::poke(uInt16 address, uInt8 value) } return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeSB::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeSB::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeSB::bankCount() const -{ - return uInt16(mySize >> 12); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeSB::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeSB::getImage(size_t& size) const -{ - size = mySize; - return myImage.get(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeSB::save(Serializer& out) const -{ - try - { - out.putInt(myBankOffset); - } - catch(...) - { - cerr << "ERROR: CartridgeSB::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeSB::load(Serializer& in) -{ - try - { - myBankOffset = in.getInt(); - } - catch(...) - { - cerr << "ERROR: CartridgeSB::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartSB.hxx b/src/emucore/CartSB.hxx index fe8f8b75d..17cea387c 100644 --- a/src/emucore/CartSB.hxx +++ b/src/emucore/CartSB.hxx @@ -19,7 +19,7 @@ #define CARTRIDGESB_HXX #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #include "System.hxx" #ifdef DEBUGGER_SUPPORT #include "CartSBWidget.hxx" @@ -31,9 +31,9 @@ (32 banks) and $800 - $83F (64 banks). All mirrors up to $FFF are also used ($900, $A00, ...). - @author Fred X. Quimby + @author Fred X. Quimby, Thomas Jentzsch */ -class CartridgeSB : public Cartridge +class CartridgeSB : public CartridgeEnhanced { friend class CartridgeSBWidget; @@ -45,17 +45,14 @@ class CartridgeSB : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + (where 0 means variable-sized ROM) */ CartridgeSB(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 0); virtual ~CartridgeSB() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -64,58 +61,6 @@ class CartridgeSB : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -153,13 +98,13 @@ class CartridgeSB : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // The 128-256K ROM image and size of the cartridge - ByteBuffer myImage; - size_t mySize{0}; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; - // Indicates the offset into the ROM image (aligns to current bank) - uInt32 myBankOffset{0}; + uInt16 hotspot() const override { return 0x0800; } + uInt16 getStartBank() const override { return romBankCount() - 1; } + + private: // Previous Device's page access std::array myHotSpotPageAccess; diff --git a/src/emucore/CartTVBoy.cxx b/src/emucore/CartTVBoy.cxx new file mode 100644 index 000000000..50d66cb57 --- /dev/null +++ b/src/emucore/CartTVBoy.cxx @@ -0,0 +1,88 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "System.hxx" +#include "CartTVBoy.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +CartridgeTVBoy::CartridgeTVBoy(const ByteBuffer& image, size_t size, + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) +{ +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeTVBoy::checkSwitchBank(uInt16 address, uInt8) +{ + // Switch banks if necessary + if((address & ADDR_MASK) >= 0x1800 && (address & ADDR_MASK) <= 0x187F) + { + bank(address & (romBankCount() - 1)); + return true; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeTVBoy::bank(uInt16 bank, uInt16) +{ + if(myBankingDisabled) return false; + + bool banked = CartridgeEnhanced::bank(bank); + + // Any bankswitching locks further bankswitching, we check for bank 0 + // to avoid locking on cart init. + if (banked && bank != 0) + myBankingDisabled = true; + + return banked; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeTVBoy::save(Serializer& out) const +{ + CartridgeEnhanced::save(out); + try + { + out.putBool(myBankingDisabled); + } + catch(...) + { + cerr << "ERROR: CartridgeTVBoy::save" << endl; + return false; + } + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeTVBoy::load(Serializer& in) +{ + CartridgeEnhanced::load(in); + try + { + myBankingDisabled = in.getBool(); + } + catch(...) + { + cerr << "ERROR: CartridgeTVBoy::load" << endl; + return false; + } + + return true; +} diff --git a/src/emucore/CartTVBoy.hxx b/src/emucore/CartTVBoy.hxx new file mode 100644 index 000000000..d1787e55b --- /dev/null +++ b/src/emucore/CartTVBoy.hxx @@ -0,0 +1,117 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef CARTRIDGETVBOY_HXX +#define CARTRIDGETVBOY_HXX + +#include "bspf.hxx" +#include "CartEnhanced.hxx" +#include "System.hxx" +#ifdef DEBUGGER_SUPPORT +#include "CartTVBoyWidget.hxx" +#endif + +/** + Cartridge class used for TV Boy + There are 128 4K banks, accessing $F800..$F87F selects bank and locks any + further bankswitching. + + @author Thomas Jentzsch +*/ +class CartridgeTVBoy : public CartridgeEnhanced +{ + friend class CartridgeTVBoyWidget; + + public: + /** + Create a new cartridge using the specified image + + @param image Pointer to the ROM image + @param size The size of the ROM image + @param md5 The md5sum of the ROM image + @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme + */ + CartridgeTVBoy(const ByteBuffer& image, size_t size, const string& md5, + const Settings& settings, size_t bsSize = 512_KB); + virtual ~CartridgeTVBoy() = default; + + public: + /** + Install pages for the specified bank in the system. + + @param bank The bank that should be installed in the system + @param segment The segment the bank should be using + + @return true, if bank has changed + */ + bool bank(uInt16 bank, uInt16 segment = 0) override; + + /** + Save the current state of this cart to the given Serializer. + + @param out The Serializer object to use + @return False on any errors, else true + */ + bool save(Serializer& out) const override; + + /** + Load the current state of this cart from the given Serializer. + + @param in The Serializer object to use + @return False on any errors, else true + */ + bool load(Serializer& in) override; + + /** + Get a descriptor for the device name (used in error checking). + + @return The name of the object + */ + string name() const override { return "CartridgeTVBoy"; } + + #ifdef DEBUGGER_SUPPORT + /** + Get debugger widget responsible for accessing the inner workings + of the cart. + */ + CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, + const GUI::Font& nfont, int x, int y, int w, int h) override + { + return new CartridgeTVBoyWidget(boss, lfont, nfont, x, y, w, h, *this); + } + #endif + + private: + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; + + uInt16 hotspot() const override { return 0x1800; } + + private: + // Indicates whether banking has been disabled due to a bankswitch + bool myBankingDisabled{false}; + + private: + // Following constructors and assignment operators not supported + CartridgeTVBoy() = delete; + CartridgeTVBoy(const CartridgeTVBoy&) = delete; + CartridgeTVBoy(CartridgeTVBoy&&) = delete; + CartridgeTVBoy& operator=(const CartridgeTVBoy&) = delete; + CartridgeTVBoy& operator=(CartridgeTVBoy&&) = delete; +}; + +#endif diff --git a/src/emucore/CartUA.cxx b/src/emucore/CartUA.cxx index b9de6bf4b..e73f166db 100644 --- a/src/emucore/CartUA.cxx +++ b/src/emucore/CartUA.cxx @@ -22,26 +22,15 @@ CartridgeUA::CartridgeUA(const ByteBuffer& image, size_t size, const string& md5, const Settings& settings, bool swapHotspots) - : Cartridge(settings, md5), + : CartridgeEnhanced(image, size, md5, settings, 8_KB), mySwappedHotspots(swapHotspots) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeUA::reset() -{ - // Upon reset we switch to the startup bank - initializeStartBank(0); - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeUA::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // Get the page accessing methods for the hot spots since they overlap // areas within the TIA we'll need to forward requests to the TIA @@ -60,26 +49,33 @@ void CartridgeUA::install(System& system) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 CartridgeUA::peek(uInt16 address) +bool CartridgeUA::checkSwitchBank(uInt16 address, uInt8) { - address &= 0x1FFF; - // Switch banks if necessary switch(address & 0x1260) { case 0x0220: // Set the current bank to the lower 4k bank bank(mySwappedHotspots ? 1 : 0); - break; + return true; case 0x0240: // Set the current bank to the upper 4k bank bank(mySwappedHotspots ? 0 : 1); - break; + return true; default: break; } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 CartridgeUA::peek(uInt16 address) +{ + address &= myBankMask; + + checkSwitchBank(address); // Because of the way accessing is set up, we will only get here // when doing a TIA read @@ -90,24 +86,9 @@ uInt8 CartridgeUA::peek(uInt16 address) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeUA::poke(uInt16 address, uInt8 value) { - address &= 0x1FFF; + address &= myBankMask; - // Switch banks if necessary - switch(address & 0x1260) - { - case 0x0220: - // Set the current bank to the lower 4k bank - bank(mySwappedHotspots ? 1 : 0); - break; - - case 0x0240: - // Set the current bank to the upper 4k bank - bank(mySwappedHotspots ? 0 : 1); - break; - - default: - break; - } + checkSwitchBank(address); // Because of the way accessing is set up, we will may get here by // doing a write to TIA or cart; we ignore the cart write @@ -119,85 +100,3 @@ bool CartridgeUA::poke(uInt16 address, uInt8 value) return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeUA::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myBankOffset = bank << 12; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeUA::getBank(uInt16) const -{ - return myBankOffset >> 12; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeUA::bankCount() const -{ - return 2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeUA::patch(uInt16 address, uInt8 value) -{ - myImage[myBankOffset + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeUA::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeUA::save(Serializer& out) const -{ - try - { - out.putShort(myBankOffset); - } - catch(...) - { - cerr << "ERROR: " << name() << "::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeUA::load(Serializer& in) -{ - try - { - myBankOffset = in.getShort(); - } - catch(...) - { - cerr << "ERROR: " << name() << "::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myBankOffset >> 12); - - return true; -} diff --git a/src/emucore/CartUA.hxx b/src/emucore/CartUA.hxx index 38588e4a9..77b83d10b 100644 --- a/src/emucore/CartUA.hxx +++ b/src/emucore/CartUA.hxx @@ -19,7 +19,7 @@ #define CARTRIDGEUA_HXX #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #include "System.hxx" #ifdef DEBUGGER_SUPPORT #include "CartUAWidget.hxx" @@ -30,9 +30,9 @@ are two 4K banks, which are switched by accessing $0220 (bank 0) and $0240 (bank 1). - @author Bradford W. Mott + @author Bradford W. Mott, Thomas Jentzsch */ -class CartridgeUA : public Cartridge +class CartridgeUA : public CartridgeEnhanced { friend class CartridgeUAWidget; @@ -51,11 +51,6 @@ class CartridgeUA : public Cartridge virtual ~CartridgeUA() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -64,64 +59,14 @@ class CartridgeUA : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @return The name of the object */ - string name() const override { return mySwappedHotspots ? "CartridgeUASW" : "CartridgeUA"; } + string name() const override { + return mySwappedHotspots ? "CartridgeUASW" : "CartridgeUA"; + } #ifdef DEBUGGER_SUPPORT /** @@ -153,15 +98,14 @@ class CartridgeUA : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // The 8K ROM image of the cartridge - std::array myImage; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; + uInt16 hotspot() const override { return 0x0220; } + + private: // Previous Device's page access std::array myHotSpotPageAccess; - // Indicates the offset into the ROM image (aligns to current bank) - uInt16 myBankOffset{0}; - // Indicates if banks are swapped ("Mickey" cart) bool mySwappedHotspots{false}; diff --git a/src/emucore/CartWD.cxx b/src/emucore/CartWD.cxx index d6b2bc239..d985abd00 100644 --- a/src/emucore/CartWD.cxx +++ b/src/emucore/CartWD.cxx @@ -22,67 +22,48 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeWD::CartridgeWD(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5), - mySize(std::min(8_KB + 3, size)) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { // Copy the ROM image into my buffer - if (mySize == 8_KB + 3) + if(size == 8_KB + 3) { - // swap slices 2 & 3 - std::copy_n(image.get(), 1_KB * 2, myImage.begin()); - std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.begin() + 1_KB * 2); - std::copy_n(image.get() + 1_KB * 2, 1_KB * 1, myImage.begin() + 1_KB * 3); - std::copy_n(image.get() + 1_KB * 4, 1_KB * 4, myImage.begin() + 1_KB * 4); + // swap banks 2 & 3 of bad dump and correct size + std::copy_n(image.get() + 1_KB * 3, 1_KB * 1, myImage.get() + 1_KB * 2); + std::copy_n(image.get() + 1_KB * 2, 1_KB * 1, myImage.get() + 1_KB * 3); + mySize = 8_KB; } - else - std::copy_n(image.get(), mySize, myImage.begin()); - createCodeAccessBase(8_KB); + myDirectPeek = false; + + myBankShift = BANK_SHIFT; + myRamSize = RAM_SIZE; + myRamWpHigh = RAM_HIGH_WP; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeWD::reset() { - initializeRAM(myRAM.data(), myRAM.size()); - initializeStartBank(0); + CartridgeEnhanced::reset(); myCyclesAtBankswitchInit = 0; myPendingBank = 0xF0; // one more than the allowable bank # - - // Setup segments to some default slices - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeWD::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); - // Set the page accessing method for the RAM reading pages - System::PageAccess read(this, System::PageAccessType::READ); - for(uInt16 addr = 0x1000; addr < 0x1040; addr += System::PAGE_SIZE) - { - read.directPeekBase = &myRAM[addr & 0x003F]; - read.codeAccessBase = &myCodeAccessBase[addr & 0x003F]; - mySystem->setPageAccess(addr, read); - } + System::PageAccess access(this, System::PageAccessType::READ); - // Set the page accessing method for the RAM writing pages - // Map access to this class, since we need to inspect all accesses to - // check if RWP happens - System::PageAccess write(this, System::PageAccessType::WRITE); - for(uInt16 addr = 0x1040; addr < 0x1080; addr += System::PAGE_SIZE) - { - write.codeAccessBase = &myCodeAccessBase[addr & 0x003F]; - mySystem->setPageAccess(addr, write); - } + // The hotspots are in TIA address space, so we claim it here + for(uInt16 addr = 0x00; addr < 0x40; addr += System::PAGE_SIZE) + mySystem->setPageAccess(addr, access); // Mirror all access in TIA; by doing so we're taking responsibility // for that address space in peek and poke below. - mySystem->tia().installDelegate(system, *this); - - // Setup segments to some default slices - bank(startBank()); + //mySystem->tia().installDelegate(system, *this); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -109,126 +90,31 @@ uInt8 CartridgeWD::peek(uInt16 address) return mySystem->tia().peek(address); } else - { - uInt16 peekAddress = address; - address &= 0x0FFF; - - if(address < 0x0040) // RAM read port - return myRAM[address]; - else if(address < 0x0080) // RAM write port - // Reading from the write port @ $1040 - $107F triggers an unwanted write - return peekRAM(myRAM[address & 0x003F], peekAddress); - else if(address < 0x0400) - return myImage[myOffset[0] + (address & 0x03FF)]; - else if(address < 0x0800) - return myImage[myOffset[1] + (address & 0x03FF)]; - else if(address < 0x0C00) - return myImage[myOffset[2] + (address & 0x03FF)]; - else - return mySegment3[address & 0x03FF]; - } + return CartridgeEnhanced::peek(address); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeWD::poke(uInt16 address, uInt8 value) { - if(!(address & 0x1000)) // TIA addresses + if(address < 0x40) return mySystem->tia().poke(address, value); - else - { - if(address & 0x040) - { - pokeRAM(myRAM[address & 0x003F], address, value); - return true; - } - else - { - // Writing to the read port should be ignored, but trigger a break if option enabled - uInt8 dummy; - pokeRAM(dummy, address, value); - myRamWriteAccess = address; - return false; - } - } + return CartridgeEnhanced::poke(address, value); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeWD::bank(uInt16 bank) +bool CartridgeWD::bank(uInt16 bank, uInt16) { - if(bankLocked() || bank > 15) return false; + if(bankLocked()) return false; - myCurrentBank = bank; + myCurrentBank = bank % romBankCount(); - segmentZero(ourBankOrg[bank & 0x7].zero); - segmentOne(ourBankOrg[bank & 0x7].one); - segmentTwo(ourBankOrg[bank & 0x7].two); - segmentThree(ourBankOrg[bank & 0x7].three); + CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].zero, 0); + CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].one, 1); + CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].two, 2); + CartridgeEnhanced::bank(ourBankOrg[myCurrentBank].three, 3); - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWD::segmentZero(uInt8 slice) -{ - uInt16 offset = slice << 10; - System::PageAccess access(this, System::PageAccessType::READ); - - // Skip first 128 bytes; it is always RAM - for(uInt16 addr = 0x1080; addr < 0x1400; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myOffset[0] = offset; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWD::segmentOne(uInt8 slice) -{ - uInt16 offset = slice << 10; - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1400; addr < 0x1800; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myOffset[1] = offset; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWD::segmentTwo(uInt8 slice) -{ - uInt16 offset = slice << 10; - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1800; addr < 0x1C00; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myOffset[2] = offset; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeWD::segmentThree(uInt8 slice) -{ - uInt16 offset = slice << 10; - - // Make a copy of the address space pointed to by the slice - // Then overwrite one byte with 0 - std::copy_n(myImage.begin()+offset, mySegment3.size(), mySegment3.begin()); - mySegment3[0x3FC] = 0; - - System::PageAccess access(this, System::PageAccessType::READ); - - for(uInt16 addr = 0x1C00; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x03FF)]; - mySystem->setPageAccess(addr, access); - } - myOffset[3] = offset; + return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -237,41 +123,13 @@ uInt16 CartridgeWD::getBank(uInt16) const return myCurrentBank; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeWD::bankCount() const -{ - return 16; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeWD::patch(uInt16 address, uInt8 value) -{ - address &= 0x0FFF; - - uInt16 idx = address >> 10; - myImage[myOffset[idx] + (address & 0x03FF)] = value; - - // The upper segment is mirrored, so we need to patch its buffer too - if(idx == 3) - mySegment3[(address & 0x03FF)] = value; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeWD::getImage(size_t& size) const -{ - size = mySize; - return myImage.data(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeWD::save(Serializer& out) const { + CartridgeEnhanced::save(out); try { out.putShort(myCurrentBank); - out.putByteArray(myRAM.data(), myRAM.size()); out.putLong(myCyclesAtBankswitchInit); out.putShort(myPendingBank); } @@ -287,10 +145,10 @@ bool CartridgeWD::save(Serializer& out) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool CartridgeWD::load(Serializer& in) { + CartridgeEnhanced::load(in); try { myCurrentBank = in.getShort(); - in.getByteArray(myRAM.data(), myRAM.size()); myCyclesAtBankswitchInit = in.getLong(); myPendingBank = in.getShort(); @@ -307,9 +165,9 @@ bool CartridgeWD::load(Serializer& in) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const std::array CartridgeWD::ourBankOrg = {{ - // 0 1 2 3 4 5 6 7 - { 0, 0, 1, 3 }, // Bank 0, 8 2 1 - 1 - - - - - { 0, 1, 2, 3 }, // Bank 1, 9 1 1 1 1 - - - - + // 0 1 2 3 4 5 6 7 + { 0, 0, 1, 3 }, // Bank 0, 8 2 1 - 1 - - - - + { 0, 1, 2, 3 }, // Bank 1, 9 1 1 1 1 - - - - { 4, 5, 6, 7 }, // Bank 2, 10 - - - - 1 1 1 1 { 7, 4, 2, 3 }, // Bank 3, 11 - - 1 1 1 - - 1 { 0, 0, 6, 7 }, // Bank 4, 12 2 - - - - - 1 1 diff --git a/src/emucore/CartWD.hxx b/src/emucore/CartWD.hxx index 0e2aad45c..4c1d9d3d9 100644 --- a/src/emucore/CartWD.hxx +++ b/src/emucore/CartWD.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartWDWidget.hxx" #endif @@ -30,8 +30,8 @@ class System; This is the cartridge class for a "Wickstead Design" prototype cart. The ROM has 64 bytes of RAM. In this bankswitching scheme the 2600's 4K cartridge address space - is broken into four 1K segments. The desired arrangement of 1K slices - is selected by accessing $30 - $3F of TIA address space. The slices + is broken into four 1K segments. The desired arrangement of 1K banks + is selected by accessing $30 - $3F of TIA address space. The banks are mapped into all 4 segments at once as follows: $0030, $0038: 0,0,1,3 @@ -45,15 +45,15 @@ class System; $0037, $003F: 6,0,5,1 - In the uppermost (third) segment, the byte at $3FC is overwritten by 0. + (Removed: In the uppermost (third) segment, the byte at $3FC is overwritten by 0.) The 64 bytes of RAM are accessible at $1000 - $103F (read port) and $1040 - $107F (write port). Because the RAM takes 128 bytes of address space, the range $1000 - $107F of segment 0 ROM will never be available. - @author Stephen Anthony + @author Stephen Anthony, Thomas Jentzsch */ -class CartridgeWD : public Cartridge +class CartridgeWD : public CartridgeEnhanced { friend class CartridgeWDWidget; @@ -65,9 +65,10 @@ class CartridgeWD : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeWD(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 8_KB); virtual ~CartridgeWD() = default; public: @@ -89,7 +90,7 @@ class CartridgeWD : public Cartridge @param bank The bank that should be installed in the system */ - bool bank(uInt16 bank) override; + bool bank(uInt16 bank, uInt16 = 0) override; /** Get the current bank. @@ -98,28 +99,6 @@ class CartridgeWD : public Cartridge */ uInt16 getBank(uInt16 address = 0) const override; - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - /** Save the current state of this cart to the given Serializer. @@ -173,51 +152,11 @@ class CartridgeWD : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - /** - Install the specified slice for segment zero. + bool checkSwitchBank(uInt16, uInt8 = 0) override { return false; } - @param slice The slice to map into the segment - */ - void segmentZero(uInt8 slice); - - /** - Install the specified slice for segment one. - - @param slice The slice to map into the segment - */ - void segmentOne(uInt8 slice); - - /** - Install the specified slice for segment two. - - @param slice The slice to map into the segment - */ - void segmentTwo(uInt8 slice); - - /** - Install the specified slice for segment three. - Note that this method also takes care of setting one byte to 0. - - @param slice The slice to map into the segment - */ - void segmentThree(uInt8 slice); + uInt16 hotspot() const override { return 0x0030; } private: - // The 8K ROM image of the cartridge - std::array myImage; - - // Indicates the actual size of the ROM image (either 8K or 8K + 3) - size_t mySize{0}; - - // The 64 bytes RAM of the cartridge - std::array myRAM; - - // The 1K ROM mirror of segment 3 (sometimes contains extra 3 bytes) - std::array mySegment3; - - // Indicates the offset for each of the four segments - std::array myOffset; - // Indicates the cycle at which a bankswitch was initiated uInt64 myCyclesAtBankswitchInit{0}; @@ -233,6 +172,16 @@ class CartridgeWD : public Cartridge }; static const std::array ourBankOrg; + private: + // log(ROM bank segment size) / log(2) + static constexpr uInt16 BANK_SHIFT = 10; // = 1K = 0x0400 + + // RAM size + static constexpr size_t RAM_SIZE = 0x40; + + // Write port for extra RAM is at low address by default + static constexpr bool RAM_HIGH_WP = true; + private: // Following constructors and assignment operators not supported CartridgeWD() = delete; diff --git a/src/emucore/CartX07.cxx b/src/emucore/CartX07.cxx index 0e0bb2869..4f3294d5c 100644 --- a/src/emucore/CartX07.cxx +++ b/src/emucore/CartX07.cxx @@ -22,26 +22,16 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size, - const string& md5, const Settings& settings) - : Cartridge(settings, md5) + const string& md5, const Settings& settings, + size_t bsSize) + : CartridgeEnhanced(image, size, md5, settings, bsSize) { - // Copy the ROM image into my buffer - std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin()); - createCodeAccessBase(myImage.size()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartridgeX07::reset() -{ - // Upon reset we switch to the startup bank - initializeStartBank(0); - bank(startBank()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CartridgeX07::install(System& system) { - mySystem = &system; + CartridgeEnhanced::install(system); // Set the page accessing methods for the hot spots // The hotspots use almost all addresses below 0x1000, so we simply grab them @@ -49,31 +39,42 @@ void CartridgeX07::install(System& system) System::PageAccess access(this, System::PageAccessType::READWRITE); for(uInt16 addr = 0x00; addr < 0x1000; addr += System::PAGE_SIZE) mySystem->setPageAccess(addr, access); +} - // Install pages for the startup bank - bank(startBank()); +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool CartridgeX07::checkSwitchBank(uInt16 address, uInt8) +{ + // Switch banks if necessary + if((address & 0x180f) == 0x080d) + { + bank((address & 0xf0) >> 4); + return true; + } + else if((address & 0x1880) == 0) + { + if((getBank() & 0xe) == 0xe) + { + bank(((address & 0x40) >> 6) | 0xe); + return true; + } + } + + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeX07::peek(uInt16 address) { - uInt8 value = 0; - + uInt8 value = 0; // JTZ: is this correct? // Check for RAM or TIA mirroring uInt16 lowAddress = address & 0x3ff; + if(lowAddress & 0x80) value = mySystem->m6532().peek(address); else if(!(lowAddress & 0x200)) value = mySystem->tia().peek(address); - // Switch banks if necessary - if((address & 0x180f) == 0x080d) - bank((address & 0xf0) >> 4); - else if((address & 0x1880) == 0) - { - if((myCurrentBank & 0xe) == 0xe) - bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe)); - } + checkSwitchBank(address); return value; } @@ -83,101 +84,13 @@ bool CartridgeX07::poke(uInt16 address, uInt8 value) { // Check for RAM or TIA mirroring uInt16 lowAddress = address & 0x3ff; + if(lowAddress & 0x80) mySystem->m6532().poke(address, value); else if(!(lowAddress & 0x200)) mySystem->tia().poke(address, value); - // Switch banks if necessary - if((address & 0x180f) == 0x080d) - bank((address & 0xf0) >> 4); - else if((address & 0x1880) == 0) - { - if((myCurrentBank & 0xe) == 0xe) - bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe)); - } + checkSwitchBank(address); + return false; } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeX07::bank(uInt16 bank) -{ - if(bankLocked()) return false; - - // Remember what bank we're in - myCurrentBank = (bank & 0x0f); - uInt32 offset = myCurrentBank << 12; - - // Setup the page access methods for the current bank - System::PageAccess access(this, System::PageAccessType::READ); - - // Map ROM image into the system - for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE) - { - access.directPeekBase = &myImage[offset + (addr & 0x0FFF)]; - access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x0FFF)]; - mySystem->setPageAccess(addr, access); - } - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeX07::getBank(uInt16) const -{ - return myCurrentBank; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 CartridgeX07::bankCount() const -{ - return 16; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeX07::patch(uInt16 address, uInt8 value) -{ - myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value; - return myBankChanged = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const uInt8* CartridgeX07::getImage(size_t& size) const -{ - size = myImage.size(); - return myImage.data(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeX07::save(Serializer& out) const -{ - try - { - out.putShort(myCurrentBank); - } - catch(...) - { - cerr << "ERROR: CartridgeX07::save" << endl; - return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartridgeX07::load(Serializer& in) -{ - try - { - myCurrentBank = in.getShort(); - } - catch(...) - { - cerr << "ERROR: CartridgeX07::load" << endl; - return false; - } - - // Remember what bank we were in - bank(myCurrentBank); - - return true; -} diff --git a/src/emucore/CartX07.hxx b/src/emucore/CartX07.hxx index 0beff0e0b..3f59ca7c3 100644 --- a/src/emucore/CartX07.hxx +++ b/src/emucore/CartX07.hxx @@ -21,7 +21,7 @@ class System; #include "bspf.hxx" -#include "Cart.hxx" +#include "CartEnhanced.hxx" #ifdef DEBUGGER_SUPPORT #include "CartX07Widget.hxx" #endif @@ -40,9 +40,9 @@ class System; Note that the latter will hit on almost any TIA access. - @author Eckhard Stolberg + @author Eckhard Stolberg, Thomas Jentzsch */ -class CartridgeX07 : public Cartridge +class CartridgeX07 : public CartridgeEnhanced { friend class CartridgeX07Widget; @@ -54,17 +54,13 @@ class CartridgeX07 : public Cartridge @param size The size of the ROM image @param md5 The md5sum of the ROM image @param settings A reference to the various settings (read-only) + @param bsSize The size specified by the bankswitching scheme */ CartridgeX07(const ByteBuffer& image, size_t size, const string& md5, - const Settings& settings); + const Settings& settings, size_t bsSize = 64_KB); virtual ~CartridgeX07() = default; public: - /** - Reset device to its power-on state - */ - void reset() override; - /** Install cartridge in the specified system. Invoked by the system when the cartridge is attached to it. @@ -73,58 +69,6 @@ class CartridgeX07 : public Cartridge */ void install(System& system) override; - /** - Install pages for the specified bank in the system. - - @param bank The bank that should be installed in the system - */ - bool bank(uInt16 bank) override; - - /** - Get the current bank. - - @param address The address to use when querying the bank - */ - uInt16 getBank(uInt16 address = 0) const override; - - /** - Query the number of banks supported by the cartridge. - */ - uInt16 bankCount() const override; - - /** - Patch the cartridge ROM. - - @param address The ROM address to patch - @param value The value to place into the address - @return Success or failure of the patch operation - */ - bool patch(uInt16 address, uInt8 value) override; - - /** - Access the internal ROM image for this cartridge. - - @param size Set to the size of the internal ROM image data - @return A pointer to the internal ROM image data - */ - const uInt8* getImage(size_t& size) const override; - - /** - Save the current state of this cart to the given Serializer. - - @param out The Serializer object to use - @return False on any errors, else true - */ - bool save(Serializer& out) const override; - - /** - Load the current state of this cart from the given Serializer. - - @param in The Serializer object to use - @return False on any errors, else true - */ - bool load(Serializer& in) override; - /** Get a descriptor for the device name (used in error checking). @@ -162,11 +106,7 @@ class CartridgeX07 : public Cartridge bool poke(uInt16 address, uInt8 value) override; private: - // The 64K ROM image of the cartridge - std::array myImage; - - // Indicates which bank is currently active - uInt16 myCurrentBank{0}; + bool checkSwitchBank(uInt16 address, uInt8 value = 0) override; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/CompuMate.cxx b/src/emucore/CompuMate.cxx index b39e46ab4..a3a0367cc 100644 --- a/src/emucore/CompuMate.cxx +++ b/src/emucore/CompuMate.cxx @@ -15,6 +15,9 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "Console.hxx" +#include "Event.hxx" +#include "System.hxx" #include "CompuMate.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CompuMate.hxx b/src/emucore/CompuMate.hxx index ff0e0f781..8b8d772e8 100644 --- a/src/emucore/CompuMate.hxx +++ b/src/emucore/CompuMate.hxx @@ -18,11 +18,12 @@ #ifndef COMPUMATE_HXX #define COMPUMATE_HXX +class Console; +class Event; +class System; + #include "bspf.hxx" -#include "CartCM.hxx" #include "Control.hxx" -#include "Event.hxx" -#include "Console.hxx" /** Handler for SpectraVideo CompuMate bankswitched games. diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 3a7e0841e..9cb5c5087 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -24,6 +24,7 @@ #include "Cart.hxx" #include "Control.hxx" #include "Cart.hxx" +#include "CartCM.hxx" #include "Driving.hxx" #include "Event.hxx" #include "EventHandler.hxx" @@ -72,6 +73,45 @@ #include "Console.hxx" +namespace { + // Emulation speed is a positive float that multiplies the framerate. However, the UI controls + // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following + // mapping and formatting functions implement this conversion. The speedup factor is represented + // by an integer value between -900 and 900 (0 means no speedup). + + constexpr int MAX_SPEED = 900; + constexpr int MIN_SPEED = -900; + constexpr int SPEED_STEP = 10; + + int mapSpeed(float speed) + { + speed = std::abs(speed); + + return BSPF::clamp( + static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), + MIN_SPEED, MAX_SPEED + ); + } + + float unmapSpeed(int speed) + { + float f_speed = static_cast(speed) / 100; + + return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; + } + + string formatSpeed(int speed) { + stringstream ss; + + ss + << std::setw(3) << std::fixed << std::setprecision(0) + << (unmapSpeed(speed) * 100); + + return ss.str(); + } +} + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Console::Console(OSystem& osystem, unique_ptr& cart, const Properties& props, AudioSettings& audioSettings) @@ -81,9 +121,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myCart(std::move(cart)), myAudioSettings(audioSettings) { - // Load user-defined palette for this ROM - loadUserPalette(); - // Create subsystems for the console my6502 = make_unique(myOSystem.settings()); myRiot = make_unique(*this, myOSystem.settings()); @@ -194,7 +231,7 @@ Console::Console(OSystem& osystem, unique_ptr& cart, myConsoleInfo.BankSwitch = myCart->about(); // Some carts have an associated nvram file - myCart->setNVRamFile(myOSystem.nvramDir(), myConsoleInfo.CartName); + myCart->setNVRamFile(myOSystem.nvramDir().getPath(), myConsoleInfo.CartName); // Let the other devices know about the new console mySystem->consoleChanged(myConsoleTiming); @@ -351,23 +388,20 @@ bool Console::load(Serializer& in) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleFormat(int direction) +void Console::selectFormat(int direction) { string saveformat, message; - uInt32 format = myCurrentFormat; + Int32 format = myCurrentFormat; - if(direction == 1) - format = (myCurrentFormat + 1) % 7; - else if(direction == -1) - format = myCurrentFormat > 0 ? (myCurrentFormat - 1) : 6; + format = BSPF::clampw(format + direction, 0, 6); - setFormat(format); + setFormat(format, true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::setFormat(uInt32 format) +void Console::setFormat(uInt32 format, bool force) { - if(myCurrentFormat == format) + if(!force && myCurrentFormat == format) return; string saveformat, message; @@ -378,7 +412,7 @@ void Console::setFormat(uInt32 format) { case 0: // auto-detect { - if (myFormatAutodetected) return; + if (!force && myFormatAutodetected) return; myDisplayFormat = formatFromFilename(); if (myDisplayFormat == "AUTO") @@ -437,10 +471,9 @@ void Console::setFormat(uInt32 format) myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected; - setPalette(myOSystem.settings().getString("palette")); setTIAProperties(); initializeVideo(); // takes care of refreshing the screen - initializeAudio(); // ensure that audio synthesis is set up to match emulation speed + initializeAudio(); // ensure that audio synthesis is set up to match emulation rate myOSystem.resetFps(); // Reset FPS measurement myOSystem.frameBuffer().showMessage(message); @@ -450,7 +483,7 @@ void Console::setFormat(uInt32 format) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleColorLoss() +void Console::toggleColorLoss(bool toggle) { bool colorloss = !myTIA->colorLossEnabled(); if(myTIA->enableColorLoss(colorloss)) @@ -474,95 +507,66 @@ void Console::enableColorLoss(bool state) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::togglePalette() -{ - string palette, message; - palette = myOSystem.settings().getString("palette"); - - if(palette == "standard") // switch to z26 - { - palette = "z26"; - message = "Z26 palette"; - } - else if(palette == "z26") // switch to user or standard - { - // If we have a user-defined palette, it will come next in - // the sequence; otherwise loop back to the standard one - if(myUserPaletteDefined) - { - palette = "user"; - message = "User-defined palette"; - } - else - { - palette = "standard"; - message = "Standard Stella palette"; - } - } - else if(palette == "user") // switch to standard - { - palette = "standard"; - message = "Standard Stella palette"; - } - else // switch to standard mode if we get this far - { - palette = "standard"; - message = "Standard Stella palette"; - } - - myOSystem.settings().setValue("palette", palette); - myOSystem.frameBuffer().showMessage(message); - - setPalette(palette); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::setPalette(const string& type) -{ - // Look at all the palettes, since we don't know which one is - // currently active - static constexpr BSPF::array2D palettes = {{ - { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette }, - { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 }, - { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette } - }}; - - // See which format we should be using - int paletteNum = 0; - if(type == "standard") - paletteNum = 0; - else if(type == "z26") - paletteNum = 1; - else if(type == "user" && myUserPaletteDefined) - paletteNum = 2; - - // Now consider the current display format - const PaletteArray* palette = - (myDisplayFormat.compare(0, 3, "PAL") == 0) ? palettes[paletteNum][1] : - (myDisplayFormat.compare(0, 5, "SECAM") == 0) ? palettes[paletteNum][2] : - palettes[paletteNum][0]; - - myOSystem.frameBuffer().setTIAPalette(*palette); - - if(myTIA->usingFixedColors()) - myTIA->enableFixedColors(true); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleInter() +void Console::toggleInter(bool toggle) { bool enabled = myOSystem.settings().getBool("tia.inter"); - myOSystem.settings().setValue("tia.inter", !enabled); + if(toggle) + enabled = !enabled; + + myOSystem.settings().setValue("tia.inter", enabled); // ... and apply potential setting changes to the TIA surface myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings(); ostringstream ss; - ss << "Interpolation " << (!enabled ? "enabled" : "disabled"); + ss << "Interpolation " << (enabled ? "enabled" : "disabled"); myOSystem.frameBuffer().showMessage(ss.str()); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Console::toggleTurbo() +{ + bool enabled = myOSystem.settings().getBool("turbo"); + + myOSystem.settings().setValue("turbo", !enabled); + + // update rate + initializeAudio(); + + // update VSync + initializeVideo(); + + ostringstream ss; + ss << "Turbo mode " << (!enabled ? "enabled" : "disabled"); + myOSystem.frameBuffer().showMessage(ss.str()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Console::changeSpeed(int direction) +{ + int speed = mapSpeed(myOSystem.settings().getFloat("speed")); + bool turbo = myOSystem.settings().getBool("turbo"); + + speed = BSPF::clamp(speed + direction * SPEED_STEP, MIN_SPEED, MAX_SPEED); + myOSystem.settings().setValue("speed", unmapSpeed(speed)); + + // update rate + initializeAudio(); + + if(turbo) + { + myOSystem.settings().setValue("turbo", false); + // update VSync + initializeVideo(); + } + + ostringstream val; + + val << formatSpeed(speed) << "%"; + myOSystem.frameBuffer().showMessage("Emulation speed", val.str(), speed, MIN_SPEED, MAX_SPEED); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::togglePhosphor() { @@ -585,36 +589,23 @@ void Console::changePhosphor(int direction) { int blend = BSPF::stringToInt(myProperties.get(PropType::Display_PPBlend)); - if(direction == +1) // increase blend + if(direction) { - if(blend >= 100) - { - myOSystem.frameBuffer().showMessage("Phosphor blend at maximum"); - myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 100); - return; - } - else - blend = std::min(blend+2, 100); + blend = BSPF::clamp(blend + direction * 2, 0, 100); + myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend); } - else if(direction == -1) // decrease blend - { - if(blend <= 2) - { - myOSystem.frameBuffer().showMessage("Phosphor blend at minimum"); - myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 0); - return; - } - else - blend = std::max(blend-2, 0); - } - else - return; ostringstream val; val << blend; myProperties.set(PropType::Display_PPBlend, val.str()); - myOSystem.frameBuffer().showMessage("Phosphor blend " + val.str()); - myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend); + if(blend) + val << "%"; + else + { + val.str(""); + val << "Off"; + } + myOSystem.frameBuffer().showMessage("Phosphor blend", val.str(), blend); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -633,17 +624,14 @@ FBInitStatus Console::initializeVideo(bool full) bool devSettings = myOSystem.settings().getBool("dev.settings"); const string& title = string("Stella ") + STELLA_VERSION + ": \"" + myProperties.get(PropType::Cart_Name) + "\""; - fbstatus = myOSystem.frameBuffer().createDisplay(title, + fbstatus = myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Emulator, TIAConstants::viewableWidth, TIAConstants::viewableHeight, false); if(fbstatus != FBInitStatus::Success) return fbstatus; myOSystem.frameBuffer().showFrameStats( myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats")); - generateColorLossPalette(); } - setPalette(myOSystem.settings().getString("palette")); - return fbstatus; } @@ -657,7 +645,9 @@ void Console::initializeAudio() .updatePlaybackPeriod(myAudioSettings.fragmentSize()) .updateAudioQueueExtraFragments(myAudioSettings.bufferSize()) .updateAudioQueueHeadroom(myAudioSettings.headroom()) - .updateSpeedFactor(myOSystem.settings().getFloat("speed")); + .updateSpeedFactor(myOSystem.settings().getBool("turbo") + ? 20.0F + : myOSystem.settings().getFloat("speed")); createAudioQueue(); myTIA->setAudioQueue(myAudioQueue); @@ -696,41 +686,17 @@ void Console::changeVerticalCenter(int direction) { Int32 vcenter = myTIA->vcenter(); - if(direction == +1) // increase vcenter - { - if(vcenter >= myTIA->maxVcenter()) - { - myOSystem.frameBuffer().showMessage("V-Center at maximum"); - return; - } - ++vcenter; - } - else if(direction == -1) // decrease vcenter - { - if (vcenter <= myTIA->minVcenter()) - { - myOSystem.frameBuffer().showMessage("V-Center at minimum"); - return; - } - --vcenter; - } - else - return; + vcenter = BSPF::clamp(vcenter + direction, myTIA->minVcenter(), myTIA->maxVcenter()); - ostringstream ss; + ostringstream ss, val; ss << vcenter; myProperties.set(PropType::Display_VCenter, ss.str()); if (vcenter != myTIA->vcenter()) myTIA->setVcenter(vcenter); - ss.str(""); - ss << "V-Center "; - if (!vcenter) - ss << "default"; - else - ss << (vcenter > 0 ? "+" : "") << vcenter << "px"; - - myOSystem.frameBuffer().showMessage(ss.str()); + val << (vcenter ? vcenter > 0 ? "+" : "" : " ") << vcenter << "px"; + myOSystem.frameBuffer().showMessage("V-Center", val.str(), vcenter, + myTIA->minVcenter(), myTIA->maxVcenter()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -743,30 +709,11 @@ void Console::updateVcenter(Int32 vcenter) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::changeScanlineAdjust(int direction) +void Console::changeVSizeAdjust(int direction) { - Int32 newAdjustVSize = myTIA->adjustVSize();; + Int32 newAdjustVSize = myTIA->adjustVSize(); - if (direction != -1 && direction != +1) return; - - if(direction == +1) // increase scanline adjustment - { - if (newAdjustVSize >= 5) - { - myOSystem.frameBuffer().showMessage("V-Size at maximum"); - return; - } - newAdjustVSize++; - } - else if(direction == -1) // decrease scanline adjustment - { - if (newAdjustVSize <= -5) - { - myOSystem.frameBuffer().showMessage("V-Size at minimum"); - return; - } - newAdjustVSize--; - } + newAdjustVSize = BSPF::clamp(newAdjustVSize + direction, -5, 5); if (newAdjustVSize != myTIA->adjustVSize()) { myTIA->setAdjustVSize(newAdjustVSize); @@ -774,15 +721,10 @@ void Console::changeScanlineAdjust(int direction) initializeVideo(); } - ostringstream ss; + ostringstream val; - ss << "V-Size "; - if (!newAdjustVSize) - ss << "default"; - else - ss << (newAdjustVSize > 0 ? "+" : "") << newAdjustVSize << "%"; - - myOSystem.frameBuffer().showMessage(ss.str()); + val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ") << newAdjustVSize << "%"; + myOSystem.frameBuffer().showMessage("V-Size", val.str(), newAdjustVSize, -5, 5); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -851,7 +793,7 @@ void Console::setControllers(const string& romMd5) Controller::Type leftType = Controller::getType(myProperties.get(PropType::Controller_Left)); Controller::Type rightType = Controller::getType(myProperties.get(PropType::Controller_Right)); size_t size = 0; - const uInt8* image = myCart->getImage(size); + const ByteBuffer& image = myCart->getImage(size); const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES"; // Try to detect controllers @@ -923,6 +865,11 @@ unique_ptr Console::getControllerPort(const Controller::Type type, swapAxis = true; else if(type == Controller::Type::PaddlesIAxDr) swapAxis = swapDir = true; + + Paddles::setAnalogXCenter(BSPF::stringToInt(myProperties.get(PropType::Controller_PaddlesXCenter))); + Paddles::setAnalogYCenter(BSPF::stringToInt(myProperties.get(PropType::Controller_PaddlesYCenter))); + Paddles::setAnalogSensitivity(myOSystem.settings().getInt("psense")); + controller = make_unique(port, myEvent, *mySystem, swapPaddles, swapAxis, swapDir); break; @@ -941,7 +888,8 @@ unique_ptr Console::getControllerPort(const Controller::Type type, case Controller::Type::AtariVox: { - const string& nvramfile = myOSystem.nvramDir() + "atarivox_eeprom.dat"; + FilesystemNode nvramfile = myOSystem.nvramDir(); + nvramfile /= "atarivox_eeprom.dat"; Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) { bool devSettings = os.settings().getBool("dev.settings"); if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess")) @@ -953,7 +901,8 @@ unique_ptr Console::getControllerPort(const Controller::Type type, } case Controller::Type::SaveKey: { - const string& nvramfile = myOSystem.nvramDir() + "savekey_eeprom.dat"; + FilesystemNode nvramfile = myOSystem.nvramDir(); + nvramfile /= "savekey_eeprom.dat"; Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) { bool devSettings = os.settings().getBool("dev.settings"); if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess")) @@ -988,83 +937,26 @@ unique_ptr Console::getControllerPort(const Controller::Type type, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::loadUserPalette() +void Console::changeAutoFireRate(int direction) { - if (!myOSystem.checkUserPalette(true)) - return; + const Int32 scanlines = std::max(tia().scanlinesLastFrame(), 240); + const bool isNTSC = scanlines <= 287; - const string& palette = myOSystem.paletteFile(); - ifstream in(palette, std::ios::binary); + int rate = myOSystem.settings().getInt("autofirerate"); - // Now that we have valid data, create the user-defined palettes - std::array pixbuf; // Temporary buffer for one 24-bit pixel + rate = BSPF::clamp(rate + direction, 0, isNTSC ? 30 : 25); - for(int i = 0; i < 128; i++) // NTSC palette - { - in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - ourUserNTSCPalette[(i<<1)] = pixel; - } - for(int i = 0; i < 128; i++) // PAL palette - { - in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - ourUserPALPalette[(i<<1)] = pixel; - } + myOSystem.settings().setValue("autofirerate", rate); + Controller::setAutoFireRate(rate); - std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels - for(int i = 0; i < 8; i++) // SECAM palette - { - in.read(reinterpret_cast(pixbuf.data()), 3); - uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]); - secam[(i<<1)] = pixel; - secam[(i<<1)+1] = 0; - } - uInt32* ptr = ourUserSECAMPalette.data(); - for(int i = 0; i < 16; ++i) - { - const uInt32* s = secam.data(); - for(int j = 0; j < 16; ++j) - *ptr++ = *s++; - } + ostringstream val; - myUserPaletteDefined = true; -} + if(rate) + val << rate << " Hz"; + else + val << "Off"; -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::generateColorLossPalette() -{ - // Look at all the palettes, since we don't know which one is - // currently active - std::array palette = { - ourNTSCPalette.data(), ourPALPalette.data(), ourSECAMPalette.data(), - ourNTSCPaletteZ26.data(), ourPALPaletteZ26.data(), ourSECAMPaletteZ26.data(), - nullptr, nullptr, nullptr - }; - if(myUserPaletteDefined) - { - palette[6] = ourUserNTSCPalette.data(); - palette[7] = ourUserPALPalette.data(); - palette[8] = ourUserSECAMPalette.data(); - } - - for(int i = 0; i < 9; ++i) - { - if(palette[i] == nullptr) - continue; - - // Fill the odd numbered palette entries with gray values (calculated - // using the standard RGB -> grayscale conversion formula) - for(int j = 0; j < 128; ++j) - { - const uInt32 pixel = palette[i][(j<<1)]; - const uInt8 r = (pixel >> 16) & 0xff; - const uInt8 g = (pixel >> 8) & 0xff; - const uInt8 b = (pixel >> 0) & 0xff; - const uInt8 sum = static_cast((r * 0.2989) + (g * 0.5870) + (b * 0.1140)); - palette[i][(j<<1)+1] = (sum << 16) + (sum << 8) + sum; - } - } + myOSystem.frameBuffer().showMessage("Autofire rate", val.str(), rate, 0, isNTSC ? 30 : 25); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1076,51 +968,56 @@ float Console::getFramerate() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleTIABit(TIABit bit, const string& bitname, bool show) const +void Console::toggleTIABit(TIABit bit, const string& bitname, bool show, bool toggle) const { - bool result = myTIA->toggleBit(bit); - string message = bitname + (result ? " enabled" : " disabled"); + bool result = myTIA->toggleBit(bit, toggle ? 2 : 3); + const string message = bitname + (result ? " enabled" : " disabled"); + myOSystem.frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleBits() const +void Console::toggleBits(bool toggle) const { - bool enabled = myTIA->toggleBits(); - string message = string("TIA bits") + (enabled ? " enabled" : " disabled"); + bool enabled = myTIA->toggleBits(toggle); + const string message = string("TIA bits ") + (enabled ? "enabled" : "disabled"); + myOSystem.frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleTIACollision(TIABit bit, const string& bitname, bool show) const +void Console::toggleTIACollision(TIABit bit, const string& bitname, bool show, bool toggle) const { - bool result = myTIA->toggleCollision(bit); - string message = bitname + (result ? " collision enabled" : " collision disabled"); + bool result = myTIA->toggleCollision(bit, toggle ? 2 : 3); + const string message = bitname + (result ? " collision enabled" : " collision disabled"); + myOSystem.frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleCollisions() const +void Console::toggleCollisions(bool toggle) const { - bool enabled = myTIA->toggleCollisions(); - string message = string("TIA collisions") + (enabled ? " enabled" : " disabled"); + bool enabled = myTIA->toggleCollisions(toggle); + const string message = string("TIA collisions ") + (enabled ? "enabled" : "disabled"); + myOSystem.frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleFixedColors() const +void Console::toggleFixedColors(bool toggle) const { - if(myTIA->toggleFixedColors()) - myOSystem.frameBuffer().showMessage("Fixed debug colors enabled"); - else - myOSystem.frameBuffer().showMessage("Fixed debug colors disabled"); + bool enabled = toggle ? myTIA->toggleFixedColors() : myTIA->usingFixedColors(); + const string message = string("Fixed debug colors ") + (enabled ? "enabled" : "disabled"); + + myOSystem.frameBuffer().showMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::toggleJitter() const +void Console::toggleJitter(bool toggle) const { - bool enabled = myTIA->toggleJitter(); - string message = string("TV scanline jitter") + (enabled ? " enabled" : " disabled"); + bool enabled = myTIA->toggleJitter(toggle ? 2 : 3); + const string message = string("TV scanline jitter ") + (enabled ? "enabled" : "disabled"); + myOSystem.frameBuffer().showMessage(message); } @@ -1138,228 +1035,3 @@ void Console::stateChanged(EventHandlerState state) { // only the CompuMate used to care about state changes } - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourNTSCPalette = { - 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0, - 0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0, - 0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0, - 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0, - 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0, - 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0, - 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0, - 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0, - 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0, - 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0, - 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0, - 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0, - 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0, - 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0, - 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0, - 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0, - 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0, - 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0, - 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0, - 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0, - 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0, - 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0, - 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0, - 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0, - 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0, - 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0, - 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0, - 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0, - 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0, - 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0, - 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0, - 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourPALPalette = { - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0 - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1 - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, - 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2 - 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389 - 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3 - 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0, - 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4 - 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac - 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5 - 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0, - 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6 - 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd - 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7 - 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff - 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8 - 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff - 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9 - 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0, - 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a - 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff - 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b - 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0, - 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c - 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff, - 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d - 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0, - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, - 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f - 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourSECAMPalette = { - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourNTSCPaletteZ26 = { - 0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0, - 0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0, - 0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0, - 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0, - 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0, - 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0, - 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0, - 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0, - 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0, - 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0, - 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0, - 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0, - 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0, - 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0, - 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0, - 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0, - 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0, - 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0, - 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0, - 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0, - 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0, - 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0, - 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0, - 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0, - 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0, - 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0, - 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0, - 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0, - 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0, - 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0, - 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0, - 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourPALPaletteZ26 = { - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, - 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0, - 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0, - 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0, - 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0, - 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0, - 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0, - 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0, - 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0, - 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0, - 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0, - 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0, - 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0, - 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0, - 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0, - 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0, - 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0, - 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0, - 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0, - 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0, - 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0, - 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0, - 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0, - 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0, - 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0, - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0, - 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0, - 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourSECAMPaletteZ26 = { - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0, - 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0, - 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserNTSCPalette = { 0 }; // filled from external file - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserPALPalette = { 0 }; // filled from external file - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PaletteArray Console::ourUserSECAMPalette = { 0 }; // filled from external file diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index eb85025a6..366e606a0 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -39,7 +39,6 @@ class AudioSettings; #include "FrameBufferConstants.hxx" #include "Serializable.hxx" #include "EventHandlerConstants.hxx" -#include "NTSCFilter.hxx" #include "EmulationTiming.hxx" #include "ConsoleTiming.hxx" #include "frame-manager/AbstractFrameManager.hxx" @@ -190,37 +189,36 @@ class Console : public Serializable, public ConsoleIO /** Toggle between NTSC/PAL/SECAM (and variants) display format. - @param direction +1 indicates increase, -1 indicates decrease. + @param direction +1 indicates increase, -1 indicates decrease. */ - void toggleFormat(int direction = 1); + void selectFormat(int direction = +1); /** Set NTSC/PAL/SECAM (and variants) display format. */ - void setFormat(uInt32 format); + void setFormat(uInt32 format, bool force = false); /** Get NTSC/PAL/SECAM (and variants) display format name */ string getFormatString() const { return myDisplayFormat; } - /** - Toggle between the available palettes. - */ - void togglePalette(); - - /** - Sets the palette according to the given palette name. - - @param palette The palette to switch to. - */ - void setPalette(const string& palette); - /** Toggle interpolation on/off */ - void toggleInter(); + void toggleInter(bool toggle = true); + /** + Toggle turbo mode on/off + */ + void toggleTurbo(); + + /** + Change emulation speed + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeSpeed(int direction = +1); /** Toggles phosphor effect. @@ -230,14 +228,14 @@ class Console : public Serializable, public ConsoleIO /** Change the "Display.PPBlend" variable. - @param direction +1 indicates increase, -1 indicates decrease. + @param direction +1 indicates increase, -1 indicates decrease. */ - void changePhosphor(int direction); + void changePhosphor(int direction = +1); /** Toggles the PAL color-loss effect. */ - void toggleColorLoss(); + void toggleColorLoss(bool toggle = true); void enableColorLoss(bool state); /** @@ -265,18 +263,18 @@ class Console : public Serializable, public ConsoleIO /** Change the "Display.VCenter" variable. - @param direction +1 indicates increase, -1 indicates decrease. + @param direction +1 indicates increase, -1 indicates decrease. */ - void changeVerticalCenter(int direction); + void changeVerticalCenter(int direction = +1); /** Change the "TIA scanline adjust" variable. Note that there are currently two of these (NTSC and PAL). The currently active mode will determine which one is used. - @param direction +1 indicates increase, -1 indicates decrease. + @param direction +1 indicates increase, -1 indicates decrease. */ - void changeScanlineAdjust(int direction); + void changeVSizeAdjust(int direction = +1); /** Returns the current framerate. @@ -286,34 +284,34 @@ class Console : public Serializable, public ConsoleIO /** Toggles the TIA bit specified in the method name. */ - void toggleP0Bit() const { toggleTIABit(P0Bit, "P0"); } - void toggleP1Bit() const { toggleTIABit(P1Bit, "P1"); } - void toggleM0Bit() const { toggleTIABit(M0Bit, "M0"); } - void toggleM1Bit() const { toggleTIABit(M1Bit, "M1"); } - void toggleBLBit() const { toggleTIABit(BLBit, "BL"); } - void togglePFBit() const { toggleTIABit(PFBit, "PF"); } - void toggleBits() const; + void toggleP0Bit(bool toggle = true) const { toggleTIABit(P0Bit, "P0", true, toggle); } + void toggleP1Bit(bool toggle = true) const { toggleTIABit(P1Bit, "P1", true, toggle); } + void toggleM0Bit(bool toggle = true) const { toggleTIABit(M0Bit, "M0", true, toggle); } + void toggleM1Bit(bool toggle = true) const { toggleTIABit(M1Bit, "M1", true, toggle); } + void toggleBLBit(bool toggle = true) const { toggleTIABit(BLBit, "BL", true, toggle); } + void togglePFBit(bool toggle = true) const { toggleTIABit(PFBit, "PF", true, toggle); } + void toggleBits(bool toggle = true) const; /** Toggles the TIA collisions specified in the method name. */ - void toggleP0Collision() const { toggleTIACollision(P0Bit, "P0"); } - void toggleP1Collision() const { toggleTIACollision(P1Bit, "P1"); } - void toggleM0Collision() const { toggleTIACollision(M0Bit, "M0"); } - void toggleM1Collision() const { toggleTIACollision(M1Bit, "M1"); } - void toggleBLCollision() const { toggleTIACollision(BLBit, "BL"); } - void togglePFCollision() const { toggleTIACollision(PFBit, "PF"); } - void toggleCollisions() const; + void toggleP0Collision(bool toggle = true) const { toggleTIACollision(P0Bit, "P0", true, toggle); } + void toggleP1Collision(bool toggle = true) const { toggleTIACollision(P1Bit, "P1", true, toggle); } + void toggleM0Collision(bool toggle = true) const { toggleTIACollision(M0Bit, "M0", true, toggle); } + void toggleM1Collision(bool toggle = true) const { toggleTIACollision(M1Bit, "M1", true, toggle); } + void toggleBLCollision(bool toggle = true) const { toggleTIACollision(BLBit, "BL", true, toggle); } + void togglePFCollision(bool toggle = true) const { toggleTIACollision(PFBit, "PF", true, toggle); } + void toggleCollisions(bool toggle = true) const; /** Toggles the TIA 'fixed debug colors' mode. */ - void toggleFixedColors() const; + void toggleFixedColors(bool toggle = true) const; /** Toggles the TIA 'scanline jitter' mode. */ - void toggleJitter() const; + void toggleJitter(bool toggle = true) const; /** * Update vcenter @@ -326,6 +324,11 @@ class Console : public Serializable, public ConsoleIO */ void setTIAProperties(); + /** + Change the autofire speed for all controllers + */ + void changeAutoFireRate(int direction = +1); + private: /** * Define console timing based on current display format @@ -359,21 +362,10 @@ class Console : public Serializable, public ConsoleIO unique_ptr getControllerPort(const Controller::Type type, const Controller::Jack port, const string& romMd5); - /** - Loads a user-defined palette file (from OSystem::paletteFile), filling the - appropriate user-defined palette arrays. - */ - void loadUserPalette(); - - /** - Loads all defined palettes with PAL color-loss data, even those that - normally can't have it enabled (NTSC), since it's also used for - 'greying out' the frame in the debugger. - */ - void generateColorLossPalette(); - - void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const; - void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const; + void toggleTIABit(TIABit bit, const string& bitname, + bool show = true, bool toggle = true) const; + void toggleTIACollision(TIABit bit, const string& bitname, + bool show = true, bool toggle = true) const; private: // Reference to the osystem object @@ -425,10 +417,6 @@ class Console : public Serializable, public ConsoleIO // Is the TV format autodetected? bool myFormatAutodetected{false}; - // Indicates whether an external palette was found and - // successfully loaded - bool myUserPaletteDefined{false}; - // Contains detailed info about this console ConsoleInfo myConsoleInfo; @@ -442,21 +430,6 @@ class Console : public Serializable, public ConsoleIO // The audio settings AudioSettings& myAudioSettings; - // Table of RGB values for NTSC, PAL and SECAM - static PaletteArray ourNTSCPalette; - static PaletteArray ourPALPalette; - static PaletteArray ourSECAMPalette; - - // Table of RGB values for NTSC, PAL and SECAM - Z26 version - static PaletteArray ourNTSCPaletteZ26; - static PaletteArray ourPALPaletteZ26; - static PaletteArray ourSECAMPaletteZ26; - - // Table of RGB values for NTSC, PAL and SECAM - user-defined - static PaletteArray ourUserNTSCPalette; - static PaletteArray ourUserPALPalette; - static PaletteArray ourUserSECAMPalette; - private: // Following constructors and assignment operators not supported Console() = delete; diff --git a/src/emucore/ConsoleIO.hxx b/src/emucore/ConsoleIO.hxx index d8ae106a6..2fde50ed8 100644 --- a/src/emucore/ConsoleIO.hxx +++ b/src/emucore/ConsoleIO.hxx @@ -15,12 +15,12 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#include "Control.hxx" -#include "Switches.hxx" - #ifndef CONSOLE_IO_HXX #define CONSOLE_IO_HXX +class Controller; +class Switches; + class ConsoleIO { public: diff --git a/src/emucore/ConsoleTiming.hxx b/src/emucore/ConsoleTiming.hxx index 1f75db469..fd43caa98 100644 --- a/src/emucore/ConsoleTiming.hxx +++ b/src/emucore/ConsoleTiming.hxx @@ -25,7 +25,8 @@ enum class ConsoleTiming { ntsc, // console with CPU running at 1.193182 MHz, NTSC colours pal, // console with CPU running at 1.182298 MHz, PAL colours - secam // console with CPU running at 1.187500 MHz, SECAM colours + secam, // console with CPU running at 1.187500 MHz, SECAM colours + numTimings }; #endif // CONSOLE_TIMING_HXX diff --git a/src/emucore/Control.cxx b/src/emucore/Control.cxx index 0584626de..813063c04 100644 --- a/src/emucore/Control.cxx +++ b/src/emucore/Control.cxx @@ -147,3 +147,14 @@ Controller::Type Controller::getType(const string& propName) return Type::Unknown; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Controller::setAutoFireRate(int rate, bool isNTSC) +{ + rate = BSPF::clamp(rate, 0, isNTSC ? 30 : 25); + AUTO_FIRE_RATE = 32 * 1024 * rate / (isNTSC ? 60 : 50); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int Controller::AUTO_FIRE_RATE = 0; + diff --git a/src/emucore/Control.hxx b/src/emucore/Control.hxx index 3647d1bc0..128912dcd 100644 --- a/src/emucore/Control.hxx +++ b/src/emucore/Control.hxx @@ -25,8 +25,8 @@ class System; #include -#include "Serializable.hxx" #include "bspf.hxx" +#include "Serializable.hxx" /** A controller is a device that plugs into either the left or right @@ -272,6 +272,14 @@ class Controller : public Serializable */ static Type getType(const string& propName); + /** + Sets the auto fire rate. 0 disables auto fire. + + @param rate Auto fire rate (0..30/25) in Hz + @param isNTSC NTSC or PAL frame rate + */ + static void setAutoFireRate(int rate, bool isNTSC = true); + public: /// Constant which represents maximum resistance for analog pins static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF; @@ -310,6 +318,44 @@ class Controller : public Serializable setPin(AnalogPin::Nine, MAX_RESISTANCE); } + /** + Checks for the next auto fire event. + + @param pressed True if the fire button is current pressed + @return The result of the auto fire event check + */ + inline bool getAutoFireState(bool pressed) + { + if(AUTO_FIRE_RATE && pressed) + { + myFireDelay -= AUTO_FIRE_RATE; + if(myFireDelay <= 0) + myFireDelay += 32 * 1024; + return myFireDelay > 16 * 1024; + } + myFireDelay = 0; + return pressed; + } + + /** + Checks for the next auto fire event for paddle 1. + + @param pressed True if the fire button is current pressed + @return The result of the auto fire event check + */ + inline bool getAutoFireStateP1(bool pressed) + { + if(AUTO_FIRE_RATE && pressed) + { + myFireDelayP1 -= AUTO_FIRE_RATE; + if(myFireDelayP1 <= 0) + myFireDelayP1 += 32 * 1024; + return myFireDelayP1 > 16 * 1024; + } + myFireDelayP1 = 0; + return pressed; + } + protected: /// Specifies which jack the controller is plugged in const Jack myJack; @@ -326,6 +372,13 @@ class Controller : public Serializable /// The callback that is dispatched whenver an analog pin has changed onAnalogPinUpdateCallback myOnAnalogPinUpdateCallback{nullptr}; + /// Defines the speed of the auto fire + static int AUTO_FIRE_RATE; + + /// Delay[frames] until the next fire event + int myFireDelay{0}; + int myFireDelayP1{0}; // required for paddles only + private: /// The boolean value on each digital pin std::array myDigitalPinState{true, true, true, true, true}; diff --git a/src/emucore/ControllerDetector.cxx b/src/emucore/ControllerDetector.cxx index 863721b46..95922051b 100644 --- a/src/emucore/ControllerDetector.cxx +++ b/src/emucore/ControllerDetector.cxx @@ -22,8 +22,10 @@ #include "ControllerDetector.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Controller::Type ControllerDetector::detectType(const uInt8* image, size_t size, - const Controller::Type type, const Controller::Jack port, const Settings& settings) +Controller::Type ControllerDetector::detectType( + const ByteBuffer& image, size_t size, + const Controller::Type type, const Controller::Jack port, + const Settings& settings) { if(type == Controller::Type::Unknown || settings.getBool("rominfo")) { @@ -43,7 +45,7 @@ Controller::Type ControllerDetector::detectType(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string ControllerDetector::detectName(const uInt8* image, size_t size, +string ControllerDetector::detectName(const ByteBuffer& image, size_t size, const Controller::Type controller, const Controller::Jack port, const Settings& settings) { @@ -51,7 +53,8 @@ string ControllerDetector::detectName(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Controller::Type ControllerDetector::autodetectPort(const uInt8* image, size_t size, +Controller::Type ControllerDetector::autodetectPort( + const ByteBuffer& image, size_t size, Controller::Jack port, const Settings& settings) { // default type joystick @@ -73,6 +76,9 @@ Controller::Type ControllerDetector::autodetectPort(const uInt8* image, size_t s type = Controller::Type::Genesis; else if(isProbablyLightGun(image, size, port)) type = Controller::Type::Lightgun; + // add check for games which support joystick and paddles, prefer paddles here + else if(usesPaddle(image, size, port, settings)) + type = Controller::Type::Paddles; } else { @@ -85,7 +91,7 @@ Controller::Type ControllerDetector::autodetectPort(const uInt8* image, size_t s } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::searchForBytes(const uInt8* image, size_t imagesize, +bool ControllerDetector::searchForBytes(const ByteBuffer& image, size_t imagesize, const uInt8* signature, uInt32 sigsize) { if (imagesize >= sigsize) @@ -109,7 +115,7 @@ bool ControllerDetector::searchForBytes(const uInt8* image, size_t imagesize, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesJoystickButton(const uInt8* image, size_t size, +bool ControllerDetector::usesJoystickButton(const ByteBuffer& image, size_t size, Controller::Jack port) { if(port == Controller::Jack::Left) @@ -239,7 +245,7 @@ bool ControllerDetector::usesJoystickButton(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size, +bool ControllerDetector::usesKeyboard(const ByteBuffer& image, size_t size, Controller::Jack port) { if(port == Controller::Jack::Left) @@ -311,13 +317,14 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size, else if(port == Controller::Jack::Right) { // check for INPT2 *AND* INPT3 access - const int NUM_SIGS_0_0 = 5; + const int NUM_SIGS_0_0 = 6; const int SIG_SIZE_0_0 = 3; uInt8 signature_0_0[NUM_SIGS_0_0][SIG_SIZE_0_0] = { { 0x24, 0x3a, 0x30 }, // bit INPT2|$30; bmi { 0xa5, 0x3a, 0x10 }, // lda INPT2|$30; bpl { 0xa4, 0x3a, 0x30 }, // ldy INPT2|$30; bmi { 0x24, 0x0a, 0x30 }, // bit INPT2; bmi + { 0x24, 0x0a, 0x10 }, // bit INPT2; bpl { 0xa6, 0x0a, 0x30 } // ldx INPT2; bmi }; const int NUM_SIGS_0_2 = 1; @@ -326,13 +333,14 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size, { 0xb5, 0x38, 0x29, 0x80, 0xd0 } // lda INPT2,x; and #80; bne }; - const int NUM_SIGS_1_0 = 5; + const int NUM_SIGS_1_0 = 6; const int SIG_SIZE_1_0 = 3; uInt8 signature_1_0[NUM_SIGS_1_0][SIG_SIZE_1_0] = { { 0x24, 0x3b, 0x30 }, // bit INPT3|$30; bmi { 0xa5, 0x3b, 0x10 }, // lda INPT3|$30; bpl { 0xa4, 0x3b, 0x30 }, // ldy INPT3|$30; bmi { 0x24, 0x0b, 0x30 }, // bit INPT3; bmi + { 0x24, 0x0b, 0x10 }, // bit INPT3; bpl { 0xa6, 0x0b, 0x30 } // ldx INPT3; bmi }; const int NUM_SIGS_1_2 = 1; @@ -378,7 +386,7 @@ bool ControllerDetector::usesKeyboard(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesGenesisButton(const uInt8* image, size_t size, +bool ControllerDetector::usesGenesisButton(const ByteBuffer& image, size_t size, Controller::Jack port) { if(port == Controller::Jack::Left) @@ -435,7 +443,7 @@ bool ControllerDetector::usesGenesisButton(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::usesPaddle(const uInt8* image, size_t size, +bool ControllerDetector::usesPaddle(const ByteBuffer& image, size_t size, Controller::Jack port, const Settings& settings) { if(port == Controller::Jack::Left) @@ -544,7 +552,7 @@ bool ControllerDetector::usesPaddle(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyTrakBall(const uInt8* image, size_t size) +bool ControllerDetector::isProbablyTrakBall(const ByteBuffer& image, size_t size) { // check for TrakBall tables const int NUM_SIGS = 3; @@ -563,7 +571,7 @@ bool ControllerDetector::isProbablyTrakBall(const uInt8* image, size_t size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyAtariMouse(const uInt8* image, size_t size) +bool ControllerDetector::isProbablyAtariMouse(const ByteBuffer& image, size_t size) { // check for Atari Mouse tables const int NUM_SIGS = 3; @@ -582,7 +590,7 @@ bool ControllerDetector::isProbablyAtariMouse(const uInt8* image, size_t size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, size_t size) +bool ControllerDetector::isProbablyAmigaMouse(const ByteBuffer& image, size_t size) { // check for Amiga Mouse tables const int NUM_SIGS = 4; @@ -602,7 +610,7 @@ bool ControllerDetector::isProbablyAmigaMouse(const uInt8* image, size_t size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablySaveKey(const uInt8* image, size_t size, +bool ControllerDetector::isProbablySaveKey(const ByteBuffer& image, size_t size, Controller::Jack port) { // check for known SaveKey code, only supports right port @@ -647,7 +655,7 @@ bool ControllerDetector::isProbablySaveKey(const uInt8* image, size_t size, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ControllerDetector::isProbablyLightGun(const uInt8* image, size_t size, +bool ControllerDetector::isProbablyLightGun(const ByteBuffer& image, size_t size, Controller::Jack port) { if (port == Controller::Jack::Left) diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx index 737ea36f2..be24ae09d 100644 --- a/src/emucore/ControllerDetector.hxx +++ b/src/emucore/ControllerDetector.hxx @@ -18,6 +18,8 @@ #ifndef CONTROLLER_DETECTOR_HXX #define CONTROLLER_DETECTOR_HXX +class Settings; + #include "Control.hxx" /** @@ -32,14 +34,14 @@ class ControllerDetector /** Detects the controller type at the given port if no controller is provided. - @param image A pointer to the ROM image + @param image A reference to the ROM image @param size The size of the ROM image @param controller The provided controller type of the ROM image @param port The port to be checked @param settings A reference to the various settings (read-only) @return The detected controller type */ - static Controller::Type detectType(const uInt8* image, size_t size, + static Controller::Type detectType(const ByteBuffer& image, size_t size, const Controller::Type controller, const Controller::Jack port, const Settings& settings); @@ -47,7 +49,7 @@ class ControllerDetector Detects the controller type at the given port if no controller is provided and returns its name. - @param image A pointer to the ROM image + @param image A reference to the ROM image @param size The size of the ROM image @param type The provided controller type of the ROM image @param port The port to be checked @@ -55,7 +57,7 @@ class ControllerDetector @return The (detected) controller name */ - static string detectName(const uInt8* image, size_t size, + static string detectName(const ByteBuffer& image, size_t size, const Controller::Type type, const Controller::Jack port, const Settings& settings); @@ -63,14 +65,14 @@ class ControllerDetector /** Detects the controller type at the given port. - @param image A pointer to the ROM image + @param image A reference to the ROM image @param size The size of the ROM image @param port The port to be checked @param settings A reference to the various settings (read-only) @return The detected controller type */ - static Controller::Type autodetectPort(const uInt8* image, size_t size, + static Controller::Type autodetectPort(const ByteBuffer& image, size_t size, Controller::Jack port, const Settings& settings); /** @@ -83,36 +85,41 @@ class ControllerDetector @return True if the signature was found, else false */ - static bool searchForBytes(const uInt8* image, size_t imagesize, + static bool searchForBytes(const ByteBuffer& image, size_t imagesize, const uInt8* signature, uInt32 sigsize); // Returns true if the port's joystick button access code is found. - static bool usesJoystickButton(const uInt8* image, size_t size, Controller::Jack port); + static bool usesJoystickButton(const ByteBuffer& image, size_t size, + Controller::Jack port); // Returns true if the port's keyboard access code is found. - static bool usesKeyboard(const uInt8* image, size_t size, Controller::Jack port); + static bool usesKeyboard(const ByteBuffer& image, size_t size, + Controller::Jack port); // Returns true if the port's 2nd Genesis button access code is found. - static bool usesGenesisButton(const uInt8* image, size_t size, Controller::Jack port); + static bool usesGenesisButton(const ByteBuffer& image, size_t size, + Controller::Jack port); // Returns true if the port's paddle button access code is found. - static bool usesPaddle(const uInt8* image, size_t size, Controller::Jack port, - const Settings& settings); + static bool usesPaddle(const ByteBuffer& image, size_t size, + Controller::Jack port, const Settings& settings); // Returns true if a Trak-Ball table is found. - static bool isProbablyTrakBall(const uInt8* image, size_t size); + static bool isProbablyTrakBall(const ByteBuffer& image, size_t size); // Returns true if an Atari Mouse table is found. - static bool isProbablyAtariMouse(const uInt8* image, size_t size); + static bool isProbablyAtariMouse(const ByteBuffer& image, size_t size); // Returns true if an Amiga Mouse table is found. - static bool isProbablyAmigaMouse(const uInt8* image, size_t size); + static bool isProbablyAmigaMouse(const ByteBuffer& image, size_t size); // Returns true if a SaveKey code pattern is found. - static bool isProbablySaveKey(const uInt8* image, size_t size, Controller::Jack port); + static bool isProbablySaveKey(const ByteBuffer& image, size_t size, + Controller::Jack port); // Returns true if a Lightgun code pattern is found - static bool isProbablyLightGun(const uInt8* image, size_t size, Controller::Jack port); + static bool isProbablyLightGun(const ByteBuffer& image, size_t size, + Controller::Jack port); private: @@ -125,4 +132,3 @@ class ControllerDetector }; #endif - diff --git a/src/emucore/DefProps.hxx b/src/emucore/DefProps.hxx index 6e5cf0c4a..1b58c81d1 100644 --- a/src/emucore/DefProps.hxx +++ b/src/emucore/DefProps.hxx @@ -25,3516 +25,3527 @@ regenerated and the application recompiled. */ -static constexpr uInt32 DEF_PROPS_SIZE = 3507; +static constexpr uInt32 DEF_PROPS_SIZE = 3518; -static const BSPF::array2D DefProps = {{ - { "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0060a89b4c956b9c703a59b181cb3018", "CommaVid, Irwin Gaines - Ariola", "CM-008 - 712 008-720", "Cakewalk (1983) (CommaVid) (PAL)", "AKA Alarm in der Backstube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "007d18dedc1f0565f09c42aa61a6f585", "CCE", "C-843", "Worm War I (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "008543ae43497af015e9428a5e3e874e", "Retroactive", "", "Qb (V2.09) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "00b7b4cbec81570642283e7fc1ef17af", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "006-01", "Congo Bongo (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00ce0bdd43aed84a983bef38fe7f5ee3", "20th Century Fox, Bill Aspromonte", "11012", "Bank Heist (1983) (20th Century Fox)", "AKA Bonnie and Clyde, Cops 'n' Robbers, Holdup, Rooring 20's", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00ce76ad69cdc2fa36ada01ae092d5a6", "Bit Corporation", "PGP214", "Cosmic Avenger (4 Game in One) (1983) (BitCorp) (PAL)", "AKA StarMaster", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00dc28b881989c39a6cf87a892bd3c6b", "CCE", "", "Krull (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00e19ebf9d0817ccfb057e262be1e5af", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL) [no grid markers]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00e55b27fe2e96354cd21b8b698d1e31", "", "", "Phoenix (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00eaee22034aff602f899b684c107d77", "Rainbow Vision - Suntek - Sunteck Corp", "SS-001", "Time Race (1983) (Rainbow Vision) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "00f7985c20b8bdf3c557fac4d3f26775", "Aaron Curtis", "", "AStar (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "012020625a3227815e47b37fd025e480", "Rob Kudla", "", "Better Space Invaders (1999) (Rob Kudla) (Hack) [a]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01293bd90a4579abb7aed2f7d440681f", "Century", "", "Snoopy (1983) (Century) (PAL)", "AKA Snoopy and the Red Baron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01297d9b450455dd716db9658efb2fae", "TechnoVision - Video Technology", "TVS1002", "Save Our Ship (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "012b8e6ef3b5fd5aabc94075c527709d", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (1983) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, - { "0164f26f6b38a34208cd4a2d0212afc3", "Coleco, Ed English", "2656", "Mr. Do! (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0173675d40a8d975763ee493377ca87d", "CBS Electronics, Ed English", "4L1751", "Roc 'n Rope (1984) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01abcc1d2d3cba87a3aa0eb97a9d7b9c", "Jone Yuan Telephonic Enterprise Co", "", "Topy (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01b09872dcd9556427761f0ed64aa42a", "Galaga Games", "", "River Raid (1984) (Galaga Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01cb3e8dfab7203a9c62ba3b94b4e59f", "Atari, Mimi Nyden, Scott Smith, Robert Vieira", "CX26127", "Gremlins (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01e5c81258860dd82f77339d58bc5f5c", "CCE", "", "Corrida da Matematica (CCE)", "AKA Math Gran Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01e60a109a6a67c70d3c0528381d0187", "ITT Family Games, Perry Rhodan-Serie", "554-33 383", "Fire Birds (1983) (ITT Family Games) (PAL)", "AKA Sky Alien", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "01f584bf67b0e464014a8c8b5ea470e3", "Arcadia Corporation, Dennis Caswell", "5 AR-4200", "Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02066b17f29082412c6754c1a2d6302e", "", "", "Demo Image Series #3 - Baboon (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "024365007a87f213cbe8ef5f2e8e1333", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "025668e36a788e8af8ac4f1be7e72043", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (06-14-82) (Atari) (Prototype)", "Console ports are swapped", "Prototype", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "026180bf641ff17d8577c33facf0edea", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0277c449fae63f6f1c8f94dedfcf0058", "", "", "Laser Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "027a59a575b78860aed780b2ae7d001d", "CCE", "", "Pressure Cooker (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "028024fb8e5e5f18ea586652f9799c96", "Coleco - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "2468", "Carnival (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02811151906e477d47c135db5b1699c6", "", "", "FlickerSort Demo (Updated) (20-04-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02a5fc90a0d183f870e8eebac1f16591", "HES", "771-422", "2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02ab2c47bc21e7feafa015f90d7df776", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02ced7ea2b7cb509748db6bfa227ebec", "Parker Brothers, Ed English, David Lamkins", "931502", "Frogger (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02cee0b140d2f1a1efcfb1d482a5c392", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02dcba28c614fec7ca25955327128abb", "Andrew Wallace", "", "Laseresal 2002 (PAL) (PD) [a]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "02e3f4ba156fb578bef7d7a0bf3400c1", "", "", "Booster (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "033e21521e0bf4e54e8816873943406d", "20th Century Fox Video Games - Sirius Software, Dan Thompson", "11020", "Earth Dies Screaming, The (1983) (20th Century Fox)", "The Day the Earth Stood Still", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "034c1434280b0f2c9f229777d790d1e1", "Telegames", "5665 A016", "Baseball (1988) (Telegames) (PAL)", "AKA Super Challenge Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0375f589f7da06d2d2be532e0d4d4b94", "", "", "Push (V0.04) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0383dc02cb82302da3d155fd108bfe3a", "AtariAge, Chris Spry", "CX26200", "Princess Rescue (2013) (Sprybug) (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "038e1e79c3d4410defde4bfe0b99cc32", "Atari, Tod Frye, Gary Shannon", "", "Aquaventure (08-12-1983) (Atari) (Prototype)", "AKA Sea Sentinel", "Unbelievably Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "039cf18b459d33b8a8fca31d06c4c244", "", "", "Demo Image Series #0 (12-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "03b1051c9374678363c899914412cfc5", "", "", "Incoming (30-10-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "03c3f7ba4585e349dd12bfa7b34b7729", "SEGA, Jeff Lorenz", "004-01", "Star Trek - Strategic Operations Simulator (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "03fbcee0bc80e31f27254aea3d920510", "Bit Corporation", "R320", "Trick Shot (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "03ff9e8a7af437f16447fe88cea3226c", "Bomb - Onbase", "CA285", "Wall-Defender (1983) (Bomb)", "AKA Wall Break", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04014d563b094e79ac8974366f616308", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "041b5e56bbc650db574bd8db3fae2696", "Thomas Jentzsch", "", "Thrust (V1.0) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "043f165f384fbea3ea89393597951512", "Spectravision - Spectravideo", "SA-202", "Planet Patrol (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0443cfa9872cdb49069186413275fa21", "M Network - INTV, Patricia Lewis Du Long, Ron Surratt", "MT4518", "BurgerTime (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "045035f995272eb2deb8820111745a07", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia)", "AKA Jungle Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "047ac3b9faea64522b7a23c4465a7aa8", "", "", "Defender (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04856e3006a4f5f7b4638da71dad3d88", "Atari, Douglas Neubauer", "CX26176", "Radar Lock (1989) (Atari) (PAL)", "AKA Dog Fight", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "049626cbfb1a5f7a5dc885a0c4bb758e", "", "", "MegaMania (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04b488d4eef622d022a0021375e7e339", "Home Vision - Gem International Corp. - VDI", "VCS83107", "Tennis (1983) (Home Vision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04cf9e6898007024622ed6a0b295961f", "Bit Corporation", "R320", "Tennis (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04dfb4acac1d0909e4c360fd2ac04480", "Thomas Jentzsch", "", "Jammed (2001) (XYPE) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04e737c9d53cd84bfd5ee679954e4706", "Jone Yuan Telephonic Enterprise Co", "", "Checkers (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "04fccc7735155a6c1373d453b110c640", "HES - Imagineering, David Lubar", "535", "My Golf (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0519f395d5f7d76be813b834aa51c0be", "Atari, Ian Shepard", "CX2604", "Space War (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0546f4e6b946f38956799dd00caab3b1", "Thomas Jentzsch", "", "My Golf (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "056f5d886a4e7e6fdd83650554997d0d", "Parker Brothers, Ed Temple", "931504", "Amidar (1982) (Parker Bros) (PAL)", "", "Uncommon", "", "", "", "A", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "056ff67dd9715fafa91fb8b0ddcc4a46", "", "", "Frisco (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05824fcbe615dbca836d061a140a50e0", "Jeffry Johnston", "", "Radial Pong - Version 9 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05aedf04803c43eb5e09dfd098d3fd01", "", "", "Keystone Kapers (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05aff8f626ef870432ae3b3d9d5aa301", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05b45ba09c05befa75ac70476829eda0", "Parker Brothers, Rex Bradford", "931507", "Star Wars - Jedi Arena (1983) (Parker Bros) (PAL)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "10 50", "", "", "", "", "", "", "", "" }, - { "05c60458ec69e7fe8b1be973852d84f1", "", "", "Test (1996) (J.V. Matthews) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05c765a63e61882abd1c2d627b652225", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (NTSC) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05ccf96247af12eef59698f1a060a54f", "Otto Versand", "600273", "King Arthur (1983) (Otto Versand) (PAL)", "AKA Dragonfire (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "05d61b925d3d2474bab83f0a79bb5df1", "Eckhard Stolberg", "", "Cosmic Ark Stars (1997) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05eb4347f0ec8f4783983ca35ffd8d1b", "", "", "Qb (2.06) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "05ebd183ea854c0a1b56c218246fbbae", "Atari, Dan Hitchens", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "05f11fb2e45c4e47424d3cb25414d278", "", "", "Boring (NTSC) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "060c865c782debb047e6fd101c8923fc", "Atari", "CX26163P", "Freeway Rabbit (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0614ed51acd027d531e7c85c4f435292", "", "", "Narnia (Glenn Saunders) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0619e1c3286bbfbace040b8c3ec5add2", "Omegamatrix", "", "Millipede (Atari Trak-Ball) v6.5 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "0651216c4a4a9c9ac5ada3013a317c72", "Jone Yuan Telephonic Enterprise Co", "", "Fishing Derby (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "06742cf522f23797157f215a1dc8a1a9", "", "", "Healthbars (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0685bd0bcb975ceef7041749a5454a48", "Piero Cavina", "", "11 Sprite Demo (Piero Cavina) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "069c17beb1e8e0557adb8539fdcf6cba", "", "", "Phantom II & Pirate (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "06b0194ce992584c365278e0d7323279", "Activision", "", "Unknown Activision Game #2 (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "06b6c5031b8353f3a424a5b86b8fe409", "Activision, Mike Lorenzen - Ariola", "EAX-023 - 711 023-720", "Oink! (1983) (Activision) (PAL)", "AKA Das Schweinchen und der Wolf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "06cfd57f0559f38b9293adae9128ff88", "Telegames", "4317 A009", "Adventures on GX-12 (1988) (Telegames) (PAL)", "AKA Adventures of Tron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "06d2f7674cea977607f74c464ce600a2", "CBS Electronics, Alex Nevelson", "4L 2737 0000", "Omega Race (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "" }, - { "06db908011065e5ebb37f4e253c2a0b0", "", "", "Gopher (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "06e5dc181a8eda1c31cc7c581c68b6ef", "", "", "Tac-Scan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "071f84d10b343c7c05ce3e32af631687", "Rainbow Vision - Suntek", "SS-019", "Curtiss (1983) (Rainbow Vision) (PAL)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "072a6ea2181ca0df88ac0dedc67b239d", "", "", "Multiple Missiles Demo (19-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "073cb76b006af034fd150be3f5e0e7e6", "", "", "Mobile 48 Sprite Kernel (Bug Fixed) (10-01-2003) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "073d7aff37b7601431e4f742c36c0dc1", "", "", "Bermuda (Unknown) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "074ec425ec20579e64a7ded592155d48", "Atari - Sculptured Software, Steve Aguirre", "CX26162", "Fatal Run (Ultimate Driving) (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "075069ad80cde15eca69e3c98bd66714", "CCE", "C-803", "Bobby Is Going Home (1983) (CCE)", "AKA Bobby Vai Para Casa", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0751f342ee4cf28f2c9a6e8467c901be", "Atari, Mimi Nyden, Joseph Tung", "CX26152", "Super Baseball (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07973be3ecfd55235bf59aa56bdef28c", "Suntek", "SS-036", "Criminal Pursuit (1983) (Suntek) (PAL)", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "079fe9103515d15bc108577e234a484d", "", "", "Multi-Color Demo 0 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07a3af1e18b63765b6807876366f5e8a", "Joe Grand", "", "SCSIcide Pre-release 2 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07c76f2d88552d20ad2c0ed7aef406c6", "Cody Pittman", "", "Blob (Cody Pittman) (Hack)", "Hack of Halloween", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07f42847a79e4f5ae55cc03304b18c25", "Zellers", "", "Sea Hawk (Zellers)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07f84db31e97ef8d08dc9fa8a5250755", "Supergame", "", "Enduro (1984) (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "07f91e33e76f53bb9d2731fd5d8a35a5", "Atari", "CX2632", "Space Invaders (1978) (Atari) [t1]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0805366f1b165a64b6d4df20d2c39d25", "Atari, Dan Hitchens", "CX2650", "Berzerk (1982) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08188785e2b8300983529946dbeff4d2", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari) (4K)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "081e2c114c9c20b61acf25fc95c71bf4", "Parker Brothers, Ed English, David Lamkins", "PB5300", "Frogger (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "082fdc8bd47fef01482ce5883c4ffdb8", "Charles Morgan", "", "Tanks DX (Charles Morgan) (Hack)", "Hack of Tanks But No Tanks", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0832fb2ee654bf9382bc57d2b16d2ffc", "Apollo - Games by Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "083e7cae41a874b2f9b61736c37d2ffe", "Imagic, Rob Fulop, Bob Smith", "720106-2A, IA3600P, EIX-009-04I", "Riddle of the Sphinx (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "085322bae40d904f53bdcc56df0593fc", "Parker Brothers, Dave Engman, Dawn Stockbridge", "PB5340", "Tutankham (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0856f202b18cd46e44fd1dc3b42e9bfb", "", "", "Frame Counter 1 (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0866e22f6f56f92ea1a14c8d8d01d29c", "Androbot - Western Technologies, Michael Case, Lenny Carlson", "", "AndroMan on the Moon (1984) (Western Tech) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0891252ee4e307689febccf3cfd8a8ab", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "0894aa7be77521f9df562be8d9555fe6", "CBS Electronics, Dan Kitchen, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1982) (CBS Electronics) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08989fa4ff537f5dbd611aff4019521a", "Atari, Gary Palmer", "CX26163P", "Fun with Numbers (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08bd4c1dcc843f6a0b563d9fd80b3b11", "Quelle", "343.273 9", "Phantompanzer II (1983) (Quelle) (PAL)", "AKA Thunderground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08bf437d012db07b05ff57a0c745c49e", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Meteoroids (1982) (Arcadia) (Prototype)", "Suicide Mission Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "08d1b6d75206edb999252caf542a2c7f", "Larry Petit", "", "Super Home Run (2003) (Larry Petit) (Hack)", "Hack of Home Run", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08d60a58a691c7f690162850302dc0e1", "", "", "Poker Squares (V0.27) (PAL) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08e5960bb52d9a3e2c9954677b5e4472", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (10-20-1982) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "08ea2fdaa22e5802c839ee7dfb0483dc", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "08f4dc6f118f7c98e2406c180c08e78e", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Tug of War (2 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "02", "", "", "", "", "", "", "", "" }, - { "08f853e8e01e711919e734d85349220d", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0906c6e0e4bda9c10cfa4c5fc64d2f4b", "Retroactive", "", "Qb (V0.12) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "090f0a7ef8a3f885048d213faa59b2f8", "Carrere Video - Western Technologies, John Hall - Teldec - Prism", "USC1012", "M.A.D. (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "09274c3fc1c43bf1e362fda436651fd8", "Thomas Jentzsch", "", "Acid Drop (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "09388bf390cd9a86dc0849697b96c7dc", "Absolute Entertainment, Alex DeMeo", "AG-045-04, AK-045-04", "Pete Rose Baseball (1988) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0945081a6bd00345ff3d58eb7a07330a", "", "", "Stampede (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0956285e24a18efa10c68a33846ca84d", "Dismac", "", "Viagem Espacial (Dismac)", "AKA Star Voyager", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0963aa9f7f6cf5a36ff700001583624e", "Franklin Cruz", "", "Space Invaders 2 (Hack) [o1]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "096649575e451508006b17e0353259a5", "Justin J. Scott", "", "Yar Vs. Yar (2002) (Justin J. Scott) (Hack)", "Hack of Yars' Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "097074f24cde141fe6a0f26a10333265", "", "", "Marble Craze (V0.90) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "097936b07e0e0117b9026ae6835eb168", "Imagic, Dennis Koble", "720100-2B, IA3000P", "Trick Shot (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "09abfe9a312ce7c9f661582fdf12eab6", "Atari, Douglas Neubauer", "CX26154", "Super Football (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "09e1ecf9bd2a3030d5670dba7a65e78d", "Atari, James Andreasen", "CX2654", "Haunted House (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "09e9ba0762fd0c3cf3c2e072cff79cac", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "09f89bbfa2ab00f1964d200e12d7ced0", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0a1b98937911d621b004b1617446d124", "", "", "Hangman Pac-Man Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0a981c03204ac2b278ba392674682560", "Atari, Bob Whitehead - Sears", "CX2651 - 99805, 49-75602", "Blackjack (1977) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "0aa208060d7c140f20571e3341f5a3f8", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Tom Sloper", "VC1009", "Towering Inferno (1982) (U.S. Games)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0abf64ca504a116adca80f77f85e00fb", "", "", "Cube Conquest (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0ac0d491763153fac75f5337ce32a9d6", "", "", "SPAM Image Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0acaf71e60b89f6b6eab63db6ab84510", "", "", "This Planet Sucks (Greg Troutman) [a2]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0aceb7c3bd13fe048b77a1928ed4267d", "Imagic, Bob Smith", "720102-2B, IA3201P, EIX-011-04I", "Star Voyager (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0ad9a358e361256b94f3fb4f2fa5a3b1", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner - Sears", "CX2608 - 49-75165", "Super Breakout (1982 - 1981) (Atari) [a]", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "0adb21206de92e8aec5ef295805ebb90", "", "", "Solaris (Genesis)", "Genesis controller (C switches to map mode)", "Hack of Solaris", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0ae3497e731ca0bf6a77b23441d9d9f9", "", "", "Analog Clock (V0.0) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0af51ceb4aecc7a8fc89781ac44a1973", "Barry Laws Jr.", "", "Face Invaders Deluxe (Barry Laws Jr.) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0afe6ae18966795b89314c3797dd2b1e", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692, CX2692P", "Moon Patrol (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b01909ba84512fdaf224d3c3fd0cf8d", "", "", "Revenge of the Apes (Hack)", "Hack of Planet of the Apes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b1056f1091cfdc5eb0e2301f47ac6c3", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001 - 3.60001 VE", "King Kong (1982) (Tigervision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b17ed42984000da8b727ca46143f87a", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (05-17-1983) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b24658714f8dff110a693a2052cc207", "CCE", "C-815", "Seaquest (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b33252b680b65001e91a411e56e72e9", "CCE", "C-832", "Atlantis (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b4e793c9425175498f5a65a3e960086", "CCE", "", "Kung Fu Master (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b55399cf640a2a00ba72dd155a0c140", "Imagic, Wilfredo Aguilar, Michael Becker, Rob Fulop", "720111-1A, 03205", "Fathom (1983) (Imagic)", "AKA Scuba", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0b577e63b0c64f9779f315dca8967587", "Videospielkassette - Ariola", "PGP236", "Raketen-Angriff (Ariola) (PAL)", "AKA Missile Control", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0b8d3002d8f744a753ba434a4d39249a", "Sears Tele-Games, Robert Zdybel", "CX2619 - 49-75159", "Stellar Track (1981) (Sears)", "AKA Stella Trak", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0bf19e40d5cd8aa5afb33b16569313e6", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0bf1e354304f46c0caf8fc0f6f5e9525", "Arcadia Corporation, Stephen Harland Landrum", "AR-4105", "Official Frogger (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0bfabf1e98bdb180643f35f2165995d0", "Atari, Bob Whitehead - Sears", "CX2623 - 6-99819, 49-75108, 49-75125", "Home Run (1978) (Atari)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c0392db94a20e4d006d885abbe60d8e", "", "", "Dodge Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c336f83b0e6e3bc86c77f368448e77b", "Bit Corporation", "R320", "Circus Atari (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c35806ff0019a270a7acae68de89d28", "Froggo", "FG1003", "Task Force (1987) (Froggo)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c48e820301251fbb6bcdc89bd3555d9", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Stargate (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c54811cf3b1f1573c9164d5f19eca65", "Activision, David Crane - Ariola", "EAG-001, PAG-001, EAG-001-04B, EAG-001-04I - 711 001-715", "Dragster (1980) (Activision) (PAL)", "AKA Dragster Rennen, Drag Strip", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c72cc3a6658c1abd4b735ef55fa72e4", "Dion Olsthoorn", "v1.3", "Amoeba Jump (2018) (Dionoid) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "0c7926d660f903a2d6910c254660c32c", "Atari, Larry Kaplan", "CX2602, CX2602P", "Air-Sea Battle (1977) (Atari) (PAL)", "AKA Anti-Aircraft", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0c7bd935d9a7f2522155e48315f44fa0", "Carrere Video - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Tom Sloper - Teldec - Prism", "USC1009", "Infernal Tower (1983) (Carrere Video) (PAL)", "AKA Towering Inferno", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0c80751f6f7a3b370cc9e9f39ad533a7", "Atari, Carla Meninsky", "CX2610", "Warlords (1981) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "0cb7af80fd0ddef84844481d85e5d29b", "", "", "Mr. Pac-Man (El Destructo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0cc8224ff1edfe458e8629e9e5fe3f5b", "Thomas Jentzsch", "", "Trick 12 (2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0cdd9cc692e8b04ba8eb31fc31d72e5e", "Thomas Jentzsch", "", "Wing War (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0cebb0bb45a856b23f56d21ce7d1bc34", "20th Century Fox Video Games, Bill Aspromonte", "11131", "Crash Dive (1983) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0cec9e46a25d338bf595a29aa2606516", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (PAL60) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "0cfdd2f3b243cac21f38a0f09f54bead", "", "", "Overhead Adventure Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d07d2c1be1a5eaaea235a533bcda781", "", "", "Scrolling Playfield 1 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d08558f34a47e4eaa39d01c8efb81f0", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (NTSC) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d09cff0d28033c02c3290edfc3a5cea", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d1b3abf681a2fc9a6aa31a9b0e8b445", "Atari", "CX26163P", "Laser Blast (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d27c7f5db349b592f70f68daf5e8f3b", "", "", "Space Instigators (21-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d35618b6d76ddd46d2626e9e3e40db5", "", "", "X-Doom V.26 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d5af65ad3f19558e6f8e29bf2a9d0f8", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dark Chambers (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0d6b974fe58a1bdd453600401c407856", "Atari", "", "128-in-1 Junior Console (Chip 3 or 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d786a41695e5fc8cffd05a6dbb3f659", "", "", "Scrolling Playfield With Score (10-02-2003) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d7e630a14856f4d52c9666040961d4d", "", "", "Wavy Line Test (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0d90a0ee73d55539b7def24c88caa651", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0db4f4150fecf77e4ce72ca4d04c052f", "Atari, Carol Shaw - Sears", "CX2618 - 49-75123", "3-D Tic-Tac-Toe (1980) (Atari)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0dd4c69b5f9a7ae96a7a08329496779a", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001 - 3.60001 VE", "King Kong (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0de53160a8b54c3aa5aed8d68c970b62", "Quelle", "806.174 9", "Fuchs & Schweinchen Schlau (1983) (Quelle) (PAL)", "AKA Oink!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0dfbdadf8f1bc718e7e1bb3ccd5fef3d", "", "", "Mr. Pac-Man (New start tune) (El Destructo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0e0808227ef41f6825c06f25082c2e56", "", "", "Candi (Hack) [a]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0e08cd2c5bcf11c6a7e5a009a7715b6a", "", "", "Boing! (PD) [a1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0e224ea74310da4e7e2103400eb1b4bf", "Atari, Peter C. Niday, Gary Shannon, Howard Scott Warshaw", "", "Mind Maze (10-10-1984) (Atari) (Prototype)", "Uses the MindLink controller", "Prototype", "", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "" }, - { "0e23d0ed4c33b2011ab4cc93a7619683", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "0e4b2b6e014a93ef8be896823da0d4ec", "", "", "Skiing (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0e713d4e272ea7322c5b27d645f56dd0", "Home Vision - Gem International Corp. - VDI", "VCS83105", "Panda Chase (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0e7e73421606873b544e858c59dc283e", "Digivision", "", "Super Soccer (Digivision)", "AKA RealSports Soccer", "", "", "", "F8", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0e86470791b26292abe1c64545c47985", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Down on the Line (3 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "01 70", "", "", "", "", "", "", "", "" }, - { "0ec93f519bb769e0d9f80e61f6cc8023", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (02-25-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0ecdb07bf9b36ef18f3780ef48e6c709", "Bit Corporation", "PG209", "Mr. Postman (1983) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0eebfb60d437796d536039701ec43845", "Fabrizio Zavagli", "", "Cakewalk (Fabrizio Zavagli)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0eecb5f58f55de9db4eedb3a0f6b74a8", "Xonox - Beck-Tech", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0ef64cdbecccb7049752a3de0b7ade14", "Atari, Joe Decuir, Larry Caplan, Steve Mayer, Larry Wagner", "CX26163P", "Combat (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0efc91e45f61023cda9d086a7d3c402f", "B.J. Best (aka bjbest60)", "", "Space Cactus Canyon (2017)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0effef4a341f8eebab65621c60c48787", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f14c03050b35d6b1d8850b07578722d", "Jeffry Johnston", "", "Radial Pong - Version 10 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f24ca5668b4ab5dfaf217933c505926", "", "", "Fantastic Voyage (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f2e09c71cc216f79d22a804152ba24b", "Bob Colbert", "", "Scroller Demo (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0f341d1f4e144e3163d9a5fc5a662b79", "", "", "RUN Platform Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "0f39fc03d579d0d93a6b729a3746843e", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (05-27-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f604cd4c9d2795cf5746e8af7948064", "Champ Games", "CG-02-N", "Conquest Of Mars (2010) (NTSC)", "Rev 2 release", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f643c34e40e3f1daafd9c524d3ffe64", "Atari, Robert C. Polaro, Alan J. Murphy - Sears", "CX2609 - 49-75186", "Defender (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f6676b05621f80c670966e2995b227a", "", "", "Globe Trotter Demo 1 (24-03-2003) (Weston)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f738dc44437557624eb277ed7ad91c9", "", "", "Grand Prix (Unknown) (PAL)", "AKA Grand Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f8043715d66a4bbed394ef801d99862", "Quelle", "684.733 9", "Robin Hood (1983) (Quelle) (PAL)", "AKA Save Our Ship", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0f95264089c99fc2a839a19872552004", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0fba7d8c3520bdb681f75494e498ec36", "", "", "Gunfight 2600 - Final Run (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0fbf618be43d4396856d4244126fe7dc", "Quelle", "805.784 6", "Labyrinth (1983) (Quelle) (PAL)", "AKA Maze Craze", "", "", "", "", "", "", "", "", "", "", "", "", "PAL", "", "", "", "", "", "", "" }, - { "0fc161704c46e16f7483f92b06c1558d", "CCE", "C-853", "Spider Fighter (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0fcff6fe3b0769ad5d0cf82814d2a6d9", "Suntek", "SS-027", "Zoo Fun (1983) (Suntek) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0fd72a13b3b6103fc825a692c71963b4", "Imagic, Rob Fulop", "720104-2A, IA3204P, EIX-008-04I", "Cosmic Ark (1982) (Imagic) (PAL) [selectable starfield]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "0fee596b974c9d3e70b367a3671599b6", "Bit Corporation", "R320", "Name This Game (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "101ab60f4000a5d13792ef0abad5f74b", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "102672bbd7e25cd79f4384dd7214c32b", "Atari, Alan Miller - Sears", "CX2642 - 6-99814", "Hunt & Score - Memory Match (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "103e9d616328969f5d7b4e0a381b25d5", "", "", "Playfield Illustration and Logo Demo (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "103f1756d9dc0dd2b16b53ad0f0f1859", "Home Vision, Gem International Corp.", "", "Go Go Home Monster (1983) (Home Vision) (PAL)", "AKA Go Go Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "104468e44898b8e9fa4a1500fde8d4cb", "AtariAge, Chris Spry", "CX26200", "Princess Rescue (2013) (Sprybug)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "106326c262dfd3e8eaeabd961d2a0519", "", "", "PAL-NTSC Detector (15-11-2002) (CT)[a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "106855474c69d08c8ffa308d47337269", "Atari - Sculptured Software, Adam Clayton", "CX26151", "Dark Chambers (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "107cc025334211e6d29da0b6be46aec7", "Atari, Bob Smith - Sears", "CX2648 - 49-75161", "Video Pinball (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1086ff69f82b68d6776634f336fb4857", "Activision, David Crane", "AG-009", "Bloody Human Freeway (1981) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10958cd0a1a81d599005f1797ab0e51d", "", "", "Centipede 2k (2000) (PD) (Hack)", "Hack of Centipede", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10a3cd14e5dcfdde6ff216a14ce7b7dd", "Atari", "CX262, CX2627P", "Human Cannonball (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10af8728f975aa35a99d0965de8f714c", "Dinatronic", "", "Seaquest (Dinatronic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10c47acca2ecd212b900ad3cf6942dbb", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a4]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10c8cfd8c37522f11d47540ff024e5f9", "Canal 3 - Intellivision", "C 3016", "Demon Attack (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10eae73a07b3da044b72473d8d366267", "Funvision - Fund. Int'l Co.", "", "Karate (1982) (Funvision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "10f0ecaf962aef1fc28abed870b01b65", "Atari, Paul Donaldson", "", "Bionic Breakthrough (06-22-1984) (Atari) (Prototype)", "Uses the Mindlink Controller", "Prototype", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "", "" }, - { "10f62443f1ae087dc588a77f9e8f43e9", "Atari, Carla Meninsky", "CX2637, CX2637P", "Dodge 'Em (1980) (Atari) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "110ac8ecaf1b69f41bc94c59dfcb8b2d", "", "", "Demon Attack (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "111029770226b319524134193886a10e", "Hozer Video Games", "", "Gunfight 2600 - One Limit Reached! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "11330eaa5dd2629052fac37cfe1a0b7d", "128-in-1 Junior Console", "", "Human Cannonball (128-in-1 Junior Console) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "113cd09c9771ac278544b7e90efe7df2", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari) [no grid markers]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "114c599454d32f74c728a6e1f71012ba", "Activision, Bob Whitehead - Ariola", "EAX-015, EAX-015-04I - 711 015-725", "Chopper Command (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "11bcf5c752088b5aaf86d6c7a6a11e8d", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "11e7e0d9437ec98fa085284cf16d0eb4", "", "", "Bowling (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "11f9532557e4c9569f4b242164006161", "Chris Walton, Justin Hairgrove, Tony Morse", "", "Hunchy II (2005) (PAL)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1201c18cf00d2c236f42e4d7d8c86aa1", "", "", "Nick Bensema Demo (Nick Bensema)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "12080205f669b8e7783b976f8cf3d8bb", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "12123b534bdee79ed7563b9ad74f1cbd", "Absolute Entertainment, Alex DeMeo", "AG-041-04", "Title Match Pro Wrestling (1987) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1228c01cd3c4b9c477540c5adb306d2a", "Atari, Alan Miller", "CX26163P", "Basketball (32 in 1) (1988) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1266b3fd632c981f3ef9bdbf9f86ce9a", "Activision, Bob Whitehead", "EAZ-034-04, EAZ-034-04I", "Private Eye (1984) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1267e3c6ca951ff1df6f222c8f813d97", "", "", "Dragonfire (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "126f7f64b7b00e25dcf5e3710b4cf8b8", "Atari - GCC", "CX2676", "Centipede (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1278f74ca1dfaa9122df3eca3c5bcaad", "Rainbow Vision - Suntek", "SS-013", "Bi! Bi! (Rainbow Vision) (PAL)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1287535256bf5dff404839ac9e25c3e7", "PacManPlus", "Rev 2", "Alien Pac-Man (PacManPlus) (Hack)", "Hack of Alien", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "12937db3d4a80da5c4452b752891252d", "Digitel", "", "Megamania (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "12bca8305d5ab8ea51fe1cfd95d7ab0e", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00250", "Summer Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "12d7e0d6b187889f8d150bf7034d1db2", "", "", "Poker Squares (V0.0e) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "130c5742cd6cbe4877704d733d5b08ca", "Home Vision - Gem International Corp. - VDI", "VCS83109", "World End (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1323c45d660f5a5b6d5ea45c6c4cbe4a", "Canal 3 - Intellivision", "", "Enduro (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "133456269a03e3fdae6cddd65754c50d", "Tigervision - Software Electronics Corporation - Teldec", "7-006 - 3.60008 VG", "Springer (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "133a4234512e8c4e9e8c5651469d4a09", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "133b56de011d562cbab665968bde352b", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1343de49c2a50d99176255f99f0d0234", "Gray Games & AtariAge", "", "E.T. Book Cart (PAL)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "55", "", "", "", "" }, - { "13448eb5ba575e8d7b8d5b280ea6788f", "Digivision", "", "Crackpots (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1345e972dbe08ea3e70850902e20e1a5", "Greg Troutman", "", "Dark Mage (rough beta) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1351c67b42770c1bd758c3e42f553fea", "Digivision", "", "Keystone Kapers (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "135708b9a7dd20576c1b66ab2a41860d", "", "", "Hangman Man Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13584411da0a8d431991035423fdc0dc", "Jone Yuan Telephonic Enterprise Co", "", "Skiing (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1367e41858be525710eb04d0dab53505", "Kyle Pittman", "", "Zelda (2003) (Kyle Pittman) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "136f75c4dd02c29283752b7e5799f978", "Atari, Dan Hitchens - Sears", "CX2650 - 49-75168", "Berzerk (1982) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13895ef15610af0d0f89d588f376b3fe", "Tigervision, Rorke Weigandt", "7-005", "Marauder (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13a37cf8170a3a34ce311b89bde82032", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13a991bc9c2ff03753aeb322d3e3e2e5", "Funvision - Fund. International Co.", "", "Galactic (Funvision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13aa1f9ac4249947e4af61319d9a08f2", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13abc32f803165c458bb086fa57195fb", "Christian Samuel", "", "E.T. The Extra-Testical (Christian Samuel) (Hack)", "Hack of E.T. The Extra-Terrestrial", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13ccc692f111d52fec75d83df16192e2", "Canal 3 - Intellivision", "", "Fishing Derby (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13d8326bf5648db4dafce45d25e62ddd", "", "", "Atari Logo Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "13dfb095e519a555a5b60b7d9d7169f9", "", "", "Red Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "140909d204abd6841c64cdad4d7765b4", "", "", "Moving Blue Ladder Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "14163eb2a3ddd35576bd8527eae3b45e", "", "", "Multi-Color Demo 6 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1423f560062c4f3c669d55891a2bcbe7", "CCE", "C-859", "MASH (1983) (CCE) [a]", "AKA M.A.S.H", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1428029e762797069ad795ce7c6a1a93", "", "", "Thunderground (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "143918368f4f4dfff90999188c0197c9", "", "", "Unknown Title (bin00016 (200110)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1442d1b35a6478fba22ae7dd1fcb5634", "Thomas Jentzsch", "", "Thrust (V0.2) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "148471144ccebd7f6aa9aa9215896533", "Parker Brothers - JWDA, Todd Marshall", "PB5550", "Q-bert's Qubes (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "149b543c917c180a1b02d33c12415206", "CCE", "C-857", "Superman (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "14a56b493a8d9d10e94a3e100362e3a2", "Hozer Video Games", "", "Gunfight 2600 - Early Play-kernel (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "14b1e30982962c72f426e2e763eb4274", "Atari, Carol Shaw - Ralph Lauren", "", "Polo (1978) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "14c2548712099c220964d7f044c59fd9", "First Star Software, Alex Leavens, Shirley Ann Russell", "", "Boing! (1983) (First Star Software)", "AKA Bubbles, Soap Suds, The Emphysema Game", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "14d365bbfaac3d20c6119591f57acca4", "", "", "Video Life (Unknown) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "14dbb3686dd31964332dc2ef0c55cad0", "", "", "Demo Image Series #15 - Three Marios (PAL) (Non-Interleave) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "151c33a71b99e6bcffb34b43c6f0ec23", "Parker Brothers, Laura Nikolich", "", "Care Bears (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "151fa3218d8d7600114eb5bcd79c85cb", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (05-02-1983) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "" }, - { "152c253478b009c275e18cd731b48561", "", "", "Quest (11-10-2002) (Chris Larkin)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "153f40e335e5cb90f5ce02e54934ab62", "Absolute Entertainment, Alex DeMeo", "EAZ-041-04I", "Title Match Pro Wrestling (1987) (Absolute) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1542662f665d2ffaa77b4b897dd2e2af", "", "", "Starfield (V1.0) (2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "155fa7f479dcba3b10b1494e236d6010", "Skyworks", "", "Tomcat (2002) (Skyworks) (PAL)", "AKA The F-14 Flight Simulator", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "157356f80c709ab675961d8b8b207e20", "", "", "Multi-Sprite Game V2.5 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "157bddb7192754a45372be196797f284", "Atari, Warren Robinett - Sears", "CX2613, 49-75154", "Adventure (1980) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "159e5cd6ccb968015f49aed5adbc91eb", "Justin J. Scott", "", "Yar's Defeat (2002) (Justin J. Scott) (Hack)", "Hack of Yars' Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "15a0d59304dece2c7d0580f3ea3527f0", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (04-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15b498199ed0ed28057bf0dbdce9b8d8", "Thomas Jentzsch", "", "Jammed (V0.2) (Demo) (2001) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15b9f5e2439bfaa08874b5184261c777", "Bit Corporation", "R320", "Space Invaders (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15bcd74f2f1f2a63e1aa93e90d2c0555", "", "", "Incoming (22-08-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15bf2ef7583bfcbbba630847a1dc5539", "Erik Eid", "", "Euchre (Jul 15) (2002) (Eric Eid) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15c11ab6e4502b2010b18366133fc322", "Atari - Axlon, Tod Frye - Heuristica, Augustin Ortiz", "CX26169", "Shooting Arcade (09-19-1989) (Atari) (Prototype)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15dd21c2608e0d7d9f54c0d3f08cca1f", "Data Age, J. Ray Dettling", "112-008", "Frankenstein's Monster (1983) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "15fe28d0c8893be9223e8cb2d032e557", "", "", "Towering Inferno (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1619bc27632f9148d8480cd813aa74c3", "Thomas Jentzsch", "", "Steeple Chase (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "161ded4a85d3c78e44fffd40426f537f", "Thomas Jentzsch", "", "JtzBall (Alpha) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "163e7e757e2dc44469123ff0e5daec5e", "", "", "Many Blue Bars and Text Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "169d4c7bd3a4d09e184a3b993823d048", "", "", "Superman (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "16cb43492987d2f32b423817cdaaf7c4", "Atari, Larry Kaplan - Sears", "CX2602 - 99802, 6-99802, 49-75102", "Air-Sea Battle (1977) (Atari)", "AKA Target Fun (Anti-Aircraft)", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "16cc6d1b4ddce51c767a1ba8e5ff196c", "", "", "Big - Move This Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "16d69f71bf5846639be5ff16483f0498", "Bit Corporation", "R320", "Golf (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "16e04823887c547dc24bc70dff693df4", "Atari", "CX26163P", "Tennis (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "16ee443c990215f61f7dd1e55a0d2256", "Spectravideo, David Lubar", "SA-218, SA-218C", "Bumper Bash (1983) (Spectravideo) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "PADDLES", "", "", "", "", "", "", "", "", "", "", "" }, - { "16f494f20af5dc803bc35939ef924020", "Mark De Smet", "", "Video Simon (Mark De Smet)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "170e7589a48739cfb9cc782cbb0fe25a", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5666", "Astroblast (1982) (M Network) [fixed]", "Can also use left joystick", "Uncommon", "", "", "", "", "", "", "", "PADDLES", "", "YES", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "171cd6b55267573e6a9c2921fb720794", "Kurt Howe", "", "Adventure 34 (Kurt Howe) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "171ebf135b13ba907f462c10d88a2c25", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (PAL60) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "1733772165d7b886a94e2b4ed0f74ccd", "", "", "Boring Journey Escape (Hack)", "Hack of Journey - Escape", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1738b2e3f25ab3eef3cecb95e1d0d957", "", "", "Hangman Monkey Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17512d0c38f448712f49f36f9d185c4e", "Retroactive", "", "Qb (Release Candidate #1) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "17515a4d0b7ea5029ffff7dfa8456671", "Piero Cavina", "", "Multi-Sprite Demo V1.1 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "176d3fba7d687f2b23158098e103c34a", "Zach Matley", "", "Combat AI (16-02-2003) (Zach Matley)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "177504abd4260c4265e1338955e9fa47", "HCC Software", "", "Pitfall! (Steroids Hack)", "Hack of Pitfall! (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1782929e1c214b70fb6884f77c207a55", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17ba72433dd41383065d4aa6dedb3d91", "", "", "SCSIcide (09-06-2001) (Joe Grand)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17badbb3f54d1fc01ee68726882f26a6", "M Network - INTV - APh Technological Consulting, Hal Finney, Bruce Pedersen", "MT5659", "Space Attack (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17bbe288c3855c235950fea91c9504e9", "Dismac", "", "Pega Ladrao (Dismac)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17c0a63f9a680e7a61beba81692d9297", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, David Johnson, Tom Sloper", "VC2004", "Picnic (1983) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "17d000a2882f9fdaa8b4a391ad367f00", "Atari - GCC", "CX2676", "Centipede (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "17ee158d15e4a34f57a837bc1ce2b0ce", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691, CX2691P", "Joust (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "17ee23e5da931be82f733917adcb6386", "Salu, Dennis M. Kiss", "460758", "Acid Drop (1992) (Salu) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1802cc46b879b229272501998c5de04f", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (1983) (Atari)", "Uses Kids/Keypad Controllers", "Rare", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "183020a80848e06a1238a1ab74079d52", "Thomas Jentzsch", "", "Missile Command (Amiga Mouse) (2002) (TJ) (PAL)", "Uses Amiga Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1862fca4f98e66f363308b859b5863af", "Atari", "", "128-in-1 Junior Console (Chip 1 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18a970bea7ac4d29707c8d5cd559d03a", "", "", "Bridge (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18b28b386abdadb3a700ac8fb68e639a", "Manuel Polik", "", "Gunfight 2600 (MP) (PAL)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18b476a34ce5e6db2c032029873ac39b", "Bit Corporation", "R320", "Atlantis (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18be8981b8201638f3ed8ae92bb4c215", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (PAL60) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "18bebbbd41c234f82b1717b1905e6027", "", "", "Space Instigators (Public Release) (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18d26111cef66dff0c8af8cf0e117843", "", "", "Tunnel Demo (Cycling Colours 2) (29-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18dc28bc22402f21e1c9b81344b3b8c5", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "18ed63e3ce5bc3dd2d8bd188b807f1a2", "", "", "Stell-A-Sketch (Bob Colbert) (PD) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "18f299edb5ba709a64c80c8c9cec24f2", "Home Vision - Gem International Corp. - VDI", "VCS83111", "Asteroid Fire (1983) (Home Vision) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19098c46da0640f2b5763167dea6c716", "Andrew Wallace", "", "Laseresal 2002 (NTSC) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "191449e40b0c56411c70772706f79224", "", "", "Multi-Color Demo 2 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19162393786098d50587827588198a86", "Jone Yuan Telephonic Enterprise Co", "", "Flag Capture (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "191ac4eec767358ee3ec3756c120423a", "", "", "Checkers (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "192aa2e8c795c9e10a7913e5d41feb81", "Atari - GCC, Jaques Hugon, Seth Lipkin", "CX26125", "Los Angeles 1984 Games (1984) (Atari) (Prototype) (PAL)", "AKA Track and Field (Uses Track & Field Controller)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "193f060553ba0a2a2676f91d9ec0c555", "Atari, Carol Shaw", "CX2636, CX2636P", "Video Checkers (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1942bdb7abc75e412068330a9082b0ff", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (PAL) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "1986f864e32e3e8d198b5becf3022257", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "199985cae1c0123ab1aef921daace8be", "", "", "Euchre (Release Candidate 2) (PAL) (01-10-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "199eb0b8dce1408f3f7d46411b715ca9", "Parker Brothers, David Lamkins, Laura Nikolich", "PB5900", "Spider-Man (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19a9d3f9fa1b1358fb53009444247aaf", "", "", "Blackjack (Unknown) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "19abaf2144b6a7b281c4112cff154904", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "19b3b807507653516985ba95da92499d", "Joe Gaucher", "", "VCS Draw Demo (Joe Gaucher)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19d6956ff17a959c48fcd8f4706a848d", "PlayAround - J.H.M.", "202", "Burning Desire (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "19d9b5f8428947eae6f8e97c7f33bf44", "", "", "Fortress (Dual Version) (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19e739c2764a5ab9ed08f9095aa2af0b", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "19e761e53e5ec8e9f2fceea62715ca06", "Panda", "104", "Scuba Diver (1983) (Panda)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1a23540d91f87584a04f184304a00648", "", "", "Race Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1a613ce60fc834d4970e1e674b9196b3", "Home Vision - Gem International Corp. - VDI", "VCS83135", "Tanks War (1983) (Home Vision) (PAL)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1a624e236526c4c8f31175e9c89b2a22", "Rainbow Vision - Suntek", "SS-007", "Space Raid (1983) (Rainbow Vision) (PAL) [a]", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1a8204a2bcd793f539168773d9ad6230", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari) [no initials]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1aa7344b563c597eecfbfcf8e7093c27", "David Marli", "", "Slot Invaders (David Marli) (Hack)", "Hack of Slot Machine", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1b0f3d7af668eeea38ddd6182d8f48fb", "Jone Yuan Telephonic Enterprise Co", "", "Cosmic Swarm (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1b1daaa9aa5cded3d633bfcbeb06479c", "", "", "Ship Demo (V 1502) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1b22a3d79ddd79335b69c94dd9b3e44e", "Tron", "", "Moon Patrol (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1b4b06c2a14ed3ee73b7d0fd61b6aaf5", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1b8c3c0bfb815b2a1010bba95998b66e", "Telegames", "", "Frogs and Flies (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1b8d35d93697450ea26ebf7ff17bd4d1", "Quelle - Otto Versand", "176.764 9 - 781644", "Marineflieger (1983) (Quelle) (PAL)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1bb91bae919ddbd655fa25c54ea6f532", "Suntek", "SS-026", "Treasure Island (1983) (Suntek) (PAL)", "AKA Treasure Discovery", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1bc2427ac9b032a52fe527c7b26ce22c", "Intellivision Productions - M Network - APh Technological Consulting, Bruce Pedersen, Larry Zwick", "MT5860", "Sea Battle (1983) (M Network)", "High Seas", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1bef389e3dd2d4ca4f2f60d42c932509", "Dimax - Sinmax", "SM8001", "Space Robot (1983) (Dimax - Sinmax) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1bf503c724001b09be79c515ecfcbd03", "", "", "Bumper Bash (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1bfae770e089fa81412d04eb299f4c3f", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (NTSC) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1c3f3133a3e5b023c77ecba94fd65995", "CCE", "C-830", "Planet Patrol (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1c5796d277d9e4df3f6648f7012884c4", "Rainbow Vision - Suntek", "SS-012", "Hey! Stop! (1983) (Rainbow Vision) (PAL)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1c666ba5aac19b81671357e76062989b", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) (PAL60) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "1c6eb740d3c485766cade566abab8208", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1c85c0fc480bbd69dc301591b6ecb422", "CCE", "", "Super Box (CCE)", "AKA RealSports Boxing", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1c8c42d1aee5010b30e7f1992d69216e", "PlayAround - J.H.M.", "205", "Gigolo (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1cad3b56cc0e6e858554e46d08952861", "Jone Yuan Telephonic Enterprise Co", "", "Chopper Command (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1cafa9f3f9a2fce4af6e4b85a2bbd254", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (1982) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1cca2197d95c5a41f2add49a13738055", "Atari, Larry Kaplan - Sears", "CX2664 - 6-99818", "Brain Games (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "1cf59fc7b11cdbcefe931e41641772f6", "SEGA", "005-01", "Buck Rogers - Planet of Zoom (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1d1d2603ec139867c1d1f5ddf83093f1", "Atari, Larry Kaplan - Sears", "CX2602 - 99802, 6-99802, 49-75102", "Air-Sea Battle (1977) (Atari) (4K)", "AKA Target Fun (Anti-Aircraft)", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d284d6a3f850bafb25635a12b316f3d", "CCE", "", "H.E.R.O. (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d2a28eb8c95da0d6d6b18294211839f", "", "", "Fishing Derby (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d4e0a034ad1275bc4d75165ae236105", "20th Century Fox Video Games, Mark Klein", "11034", "Pick Up (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d5eac85e67b8cff1377c8dba1136929", "", "", "Chronocolor Donkey Kong Sideways (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d6ed6fe9dfbde32708e8353548cbb80", "Jone Yuan Telephonic Enterprise Co", "", "Super Challenge Baseball (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1d72cc6ee466a4af1b27587b900ed430", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1da2da7974d2ca73a823523f82f517b3", "Spectravision - Spectravideo - Sirius Software, David Lubar", "SA-206", "Challenge of.... Nexar, The (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1db3bc4601f22cf43be7ce015d74f59a", "", "", "Ship Demo (V 10) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e060a8025512ad2127e3da11e212ccc", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (3 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e0ef01e330e5b91387f75f700ccaf8f", "Quelle - Otto Versand", "686.561 2 - 781627", "Mein Weg (1983) (Quelle) (PAL)", "AKA Challenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1e1290ea102e12d7ac52820961457e2b", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-15-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1e272d09c0e55f5ef14fcb76a735f6d7", "Atari, David Crane", "CX26163P", "Slot Machine (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e31b3a48865ba98d4d1aa5205115983", "Atari - Roklan, Bob Curtiss", "", "Firefox (1983) (Atari) (Prototype)", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e587ca91518a47753a28217cd4fd586", "Telesys, Jim Rupp, Jack Woodman", "1001", "Coco Nuts (1982) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e750000af77cc76232f4d040f4ab060", "Jone Yuan Telephonic Enterprise Co", "", "Raft Rider (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e85f8bccb4b866d4daa9fcf89306474", "Atari, Lou Harp", "CX26122", "Sinistar (02-13-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1e89f722494608d6ea15a00d99f81337", "", "", "River Raid (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC50", "", "", "", "", "", "", "" }, - { "1ea1abcd2d3d3d628f59a99a9d41b13b", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ea980574416bfd504f62575ba524005", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ec57bbd27bdbd08b60c391c4895c1cf", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (09-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ec5bef77b91e59313cba205f15b06d7", "", "", "Overhead Adventure Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ede4f365ce1386d58f121b15a775e24", "Parker Brothers, Dave Hampton, Tom Sloper", "931517", "Q-bert (1983) (Parker Bros) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ee2cfc7d0333b96bd11f7f3ec8ce8bc", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (4 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ee9c1ba95cef2cf987d63f176c54ac3", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675, CX2675P", "Ms. Pac-Man (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1ef04e7e508296a8d9eb61cc7dae2e5d", "SOLID Corp. (D. Scott Williamson)", "CX2655-069", "Star Castle 2600 (SolidCorp) [069]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "1f21666b8f78b65051b7a609f1d48608", "K-Tel Vision", "", "Vulture Attack (1982) (K-Tel Vision)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f2ae0c70a04c980c838c2cdc412cf45", "Atari - GCC", "CX2698", "Rubik's Cube (1984) (Atari)", "AKA Atari Video Cube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f349dd41c3f93c4214e5e308dccb056", "", "", "Virtual Pet Demo 2 (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f40eefc7447336ae6cd8ffa5eb325be", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f562b89d081e36d58e6fc943512ec05", "", "", "Hangman Man Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f5a2927a0b2faf87540b01d9d7d7fd1", "Pet Boat", "", "Tennis (Pet Boat) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1f60e48ad98b659a05ce0c1a8e999ad9", "", "", "Mondo Pong V2 (Piero Cavina) (PD)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "01", "", "", "", "", "", "", "", "" }, - { "1f773a94d919b2a3c647172bbb97f6b4", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (07-11-1983) (Atari) (Prototype) (PAL)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1fa58679d4a39052bd9db059e8cda4ad", "Imagic, Dan Oliver", "720118-1A, 03208", "Laser Gates (1983) (Imagic)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1fa7a42c2c7d6b7a0c6a05d38c7508f4", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-04-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "1fa86282403fa35d103ab88a9d603c31", "SpiceWare - Darrell Spice Jr.", "", "Stay Frosty (SpiceWare) (PAL60)", "Part of Stella's Stocking 2007 Xmas compilation", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "1fab68fd67fe5a86b2c0a9227a59bb95", "20th Century Fox Video Games - Videa, Lee Actor", "", "Lasercade (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "200309c8fba0f248c13751ed4fc69bab", "Jeffry Johnston", "", "Radial Pong - Version 1 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2008c76deba5953201ef75a09b2ff7dc", "", "", "Fortress (21-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "200a9d2a7cb4441ce4f002df6aa47e38", "", "", "Doomzerk (PD) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2016726db38ad6a68b4c48ba6fe51557", "Piero Cavina, Erik Mooney", "", "INV 2 (Piero Cavina, Erik Mooney)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "203049f4d8290bb4521cc4402415e737", "Tigervision, Robert H. O'Neil - Teldec", "7-007 - 3.60005 VG", "Polaris (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "203abb713c00b0884206dcc656caa48f", "Imagic, Bob Smith", "720114-1A, 03207, IZ-001-04", "Moonsweeper (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "203b1efc6101d4b9d83bb6cc1c71f67f", "Quelle", "685.996 1", "Teller-Jonglieren! (1983) (Quelle) (PAL)", "AKA Dancing Plate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "205070b6a0d454961dd9196a8e81d877", "", "", "Hangman Monkey Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2058cf3fefad4d2bc03ed817cedddcd4", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "2091af29b4e7b86914d79d9aaa4cbd20", "CBS Electronics - Woodside Design Associates, Harley H. Puthuff Jr.", "4L1802", "Donkey Kong Junior (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "20ae62fb69c6cc6e8098cca8cd080487", "Zirok", "", "Tennis (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "20d4457ba22517253fcb62967af11b37", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "20dca534b997bf607d658e77fbb3c0ee", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1002", "Fire Fly (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "20edcc3aa6c189259fa7e2f044a99c49", "Spectravision - Spectravideo", "SA-201", "Gangster Alley (1982) (Spectravision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "211774f4c5739042618be8ff67351177", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "211f76dff0b7dad3f6fcac9d938ee61a", "JSK", "", "Custer's Viagra (JSK) (Hack) [a]", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "211fbbdbbca1102dc5b43dc8157c09b3", "Apollo", "AP-2009", "Final Approach (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2124cf92978c46684b6c39ccc2e33713", "", "", "Sea Monster (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "21299c8c3ac1d54f8289d88702a738fd", "K-Tel Vision", "", "Spider Maze (1982) (K-Tel Vision)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "212d0b200ed8b45d8795ad899734d7d7", "Atari, Richard Maurer, Christopher H. Omarzu - Coca Cola", "", "Pepsi Invaders (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "213e5e82ecb42af237cfed8612c128ac", "Sancho - Tang's Electronic Co.", "TEC006", "Forest (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2162266b906c939b35c84ff9a0f50ad1", "Atari, Larry Kaplan", "CX2664, CX2664P", "Brain Games (1978) (Atari) (PAL) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "2179dfd7edee76efafe698c1bc763735", "", "", "Yellow Submarine (Cody Pittman) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "217b1452881264ac75126bf77b8d0db8", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "218b76f5a4142dc2ea9051a768583d70", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "218c0fe53dfaaa37f3c823f66eafd3fc", "Atari, Alan Miller", "CX2624, CX2624P", "Basketball (1978) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "21a96301bb0df27fde2e7eefa49e0397", "Data Age", "DA1003", "Sssnake (1982) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "21b09c40295c2d7074a83ae040f22edf", "", "", "Marble Craze (V0.90) (Easy Version) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "21d2c435bcccde7792d82844b3cf60f4", "Atari - GCC, Doug Macrae", "CX2677, CX2677P", "Dig Dug (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "21d7334e406c2407e69dbddd7cec3583", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2228c67d25e507603d4873d3934f0757", "", "", "Fu Kung! (V0.10) (28-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "22319be7a640af5314ec3c482cceb676", "", "", "Joustpong (05-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2240655247d6de1c585564004a853ab7", "", "", "Fu Kung! (V0.17) (07-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "225522777dc7155627808bde0c1d0ef0", "", "", "This Planet Sucks Demo 1 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "22675cacd9b71dea21800cbf8597f000", "Atari, David Crane", "CX2605, CX2605P", "Outlaw (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "227532d82505c3c185a878273c285d5f", "", "", "Hangman Man Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "22abbdcb094d014388d529352abe9b4b", "Apollo", "AP-2012", "Squoosh (1983) (Apollo) (Prototype) [a]", "AKA Vat's Incredible!, The Grape Escape", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "22b22c4ce240303012e8a9596ae8d189", "", "", "Skeleton+ (03-05-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "22f6b40fc82110d68e50a1208ae0bb97", "", "", "Purple Bar Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2319922df4d0c820b3e5f15faa870cc3", "Atari - GCC, Mike Feinstein", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2327456f86d7e0deda94758c518d05b3", "Digitel", "", "Mr. Postman (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2351d26d0bfdee3095bec9c05cbcf7b0", "", "", "Warring Worms (19-01-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2353725ec98e0f0073462109e886efd7", "Champ Games", "CG-03-P", "Scramble (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "235436ab0832370e73677c9c6f0c8b06", "", "", "Beast Invaders (Double Shot) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2365e1534d67f94d8670394ab99150ce", "Thomas Jentzsch", "", "Missile Command (Atari Mouse) (2002) (TJ)", "Uses Atari ST Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "ATARIMOUSE", "ATARIMOUSE", "", "", "", "", "YES", "", "", "", "", "" }, - { "23d445ea19a18fb78d5035878d9fb649", "CBS Electronics - JWDA, Sylvia Day, Todd Marshall, Henry Will IV", "4L1818, 4L1819, 4L1820, 4L1821", "Mouse Trap (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "23e4ca038aba11982e1694559f3be10f", "", "", "Big Dig (V3) (20-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "23fad5a125bcd4463701c8ad8a0043a9", "CCE", "C-840", "Stone Age (1983) (CCE)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "A", "A", "", "YES", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "240bfbac5163af4df5ae713985386f92", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2432f33fd278dea5fe6ae94073627fcc", "CBS Electronics, Tom DiDomenico", "4L2477, 4L2482, 4L2485, 4L4171", "Blueprint (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2434102f30eeb47792cf0825e368229b", "Sparrow - Enter-Tech, Paul Walters, Rick Harris, George Hefner, Barbara Ultis", "", "Arkyology (1983) (Sparrow) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24385ba7f5109fbe76aadc0a375de573", "CCE", "", "Xevious (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2447e17a4e18e6b609de498fe4ab52ba", "CCE", "", "Super Futebol (CCE)", "AKA RealSports Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "244c6de27faff527886fc7699a41c3be", "", "", "Matt Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2450dfa1df70d12b60683185775efed8", "Jeffry Johnston", "", "Radial Pong - Version 7 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24544ee5d76f579992d9522e9b238955", "Carrere Video - Western Technologies, Jeff Corsiglia, David Johnson, Tom Sloper - Teldec - Prism", "USC2004", "Picnic (1983) (Carrere Video) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "245f07c8603077a0caf5f83ee6cf8b43", "Home Vision - Thomas Jentzsch", "", "Parachute (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24759be31e8fe55d2829fd86bdf3181f", "Hozer Video Games", "", "Gunfight 2600 - Worst Nightmare... (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "247fa1a29ad90e64069ee13d96fea6d6", "CCE", "C-867", "Radar (1983) (CCE)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "248668b364514de590382a7eda2c9834", "CBS Electronics, Richard K. Balaska Jr., Bob Curtiss, Alex Leavens, Alex Nevelson", "", "Kick-Man (01-08-82) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2496d404bfc561a40a80bea6a69695c3", "CCE", "C-1007", "Jungle Hunt (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24ad538291eb5f5cac4b9998f3b851c3", "", "", "Gunfight 2600 - This time it's your decission! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24aff972d58990f9b88a6d787c796f1e", "CBS Electronics", "4L1767, 4L1768, 4L1769, 4L1770", "Smurf (1982) (CBS Electronics) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24b5f4bbdb853eca38ea0cae2dfe73a1", "", "", "Home Run (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24b9adac1b4f85b0bac9bf9b9e180906", "Angelino", "", "Space 2002 (Angelino) (Hack)", "Hack of Space Jockey", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24d018c4a6de7e5bd19a36f2b879b335", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "24d9a55d8f0633e886a1b33ee1e0e797", "Thomas Jentzsch", "", "Dragon Defender (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "24df052902aa9de21c2b2525eb84a255", "Imagic, Dennis Koble", "720000-100, 720100-1B, IA3000, IA3000C", "Trick Shot (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "24fbf8250a71611e40ef18552e61b009", "", "", "Movable Grid Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2516f4f4b811ede4ecf6fbeb5d54a299", "Quelle", "701.134 9", "Schiessbude (1983) (Quelle) (PAL)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2517827950fee41a3b9de60275c8aa6a", "Atari", "CX26163P", "Fishing (32 in 1) (1988) (Atari) (PAL)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25265d0e7f88b3026003809f25ee025e", "Atari - GCC, Ava-Robin Cohen", "CX26123", "Jr. Pac-Man (1984) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25472dfdeef6a42581a231d631d6b04d", "", "", "Gunfight 2600 - Design thoughts (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25710bde8fa181b0c5cf0846b983bec1", "", "", "Demo Image Series #15 - Three Marios (NTSC) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "257bc3b72a6b5db3fd0d47619125b387", "CBS Electronics", "4L 2737 0000", "Omega Race (1983) (CBS Electronics) [a]", "Set right difficulty to 'A' for BoosterGrip in both ports", "", "", "", "", "", "", "", "", "BOOSTERGRIP", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "" }, - { "25a21c47afe925a3ca0806876a2b4f3f", "Quelle", "685.640 5", "Der kleine Baer (1983) (Quelle) (PAL)", "AKA Frostbite", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25b52bf8dd215bcbd59c9abdb55c44f8", "Atari - GCC, Betty Ryan Tylko, Doug Macrae", "CX2694, CX2694P", "Pole Position (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25b6dc012cdba63704ea9535c6987beb", "Avalon Hill, Jean Baer, Bill Hood", "5004002", "Shuttle Orbiter (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25bb080457351be724aac8a02021aa92", "CBS Electronics", "4L1784, 4L1786, 4L1787, 4L2277", "Zaxxon (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25d4be3309b89583c6b39d9f93bf654f", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25e73efb9a6edf119114718bd2f646ba", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (1983) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25f2e760cd7f56b88aac88d63757d41b", "Activision, Bob Whitehead - Ariola", "EAG-002, EAG-002-04I, PAG-002 - 711 002-715", "Boxing (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "25f879ff678130fea615ac418e7943f1", "Activision, Garry Kitchen", "EAX-025", "Keystone Kapers (1983) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "SECAM", "", "", "", "", "", "", "" }, - { "25f9cf703575c5d63048c222f5463758", "", "", "Multi-Sprite Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "260c787e8925bf3649c8aeae5b97dcc0", "Thomas Jentzsch", "", "Hell Driver (Thomas Jentzsch)", "NTSC Conversion, joystick ports swapped", "Homebrew", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "262ccb882ff617d9b4b51f24aee02cbe", "Atari, Douglas Neubauer", "CX26154, CX26154P", "Super Football (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "265a85f66544eaf95fda06c3d9e48abf", "", "", "Tunnel Demo (Cycling Colours) (29-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "265c74a956500bd31efd24adc6d5ccf6", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2683d29a282dd059535ac3bb250f540d", "", "", "Space Treat (12-01-2003) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "268f46038e29301568fa9e443e16e960", "Atarius Maximum", "", "Pitfall Unlimited (Atarius Maximus) (Hack)", "Hack of Pitfall", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "26bc2bdf447a17376aea7ef187ff6e44", "", "", "Amanda Invaders (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "26f4f8b098609164effef7809e0121e1", "", "", "Oystron (V2.7) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "270229c6d5578446e6a588492e4e5910", "", "", "Space Invaders 2 (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2712e91f6f1dc55e90e2b14b27c042ac", "Omegamatrix", "", "SpaceMaster X-7 (Amiga Mouse) (PAL60) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "271bfd5dc2673d382019f1fb6cab9332", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (Preview) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "273ce50db5a0d6da7ea827a54f44dee9", "", "", "Island Flyer Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "274d17ccd825ef9c728d68394b4569d2", "Playaround - J.H.M.", "202", "Bachelorette Party (1982) (Playaround)", "AKA Bachelor Party, Uses the paddle controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "277c7281ac945b8331e2e6fcad560c11", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (2 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "277cca62014fceebb46c549bac25a2e3", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "277fa4b9a6bb7a8dcea2c5f38a4c25f0", "Atari, Alan J. Murphy, Robert Zdybel", "CX2668", "RealSports Football (1982) (Atari) (Prototype)", "AKA Football II", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "278155fc9956e9b6ef2359eb238f7c7f", "", "", "Donkey Kong Junior (Unknown) (Hack)", "Hack of Donkey Kong Junior", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2783006ee6519f15cbc96adae031c9a9", "Telegames", "", "Night Stalker (1989) (Telegames) (PAL) [a]", "AKA Dark Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "278531cc31915747018d22145823d2c9", "", "", "Defender MegaDrive (PAL) (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "278f14887d601b5e5b620f1870bc09f6", "Thomas Jentzsch", "", "SWOOPS! (v0.96) (TJ)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "27a5d2d0c74c8e4b2c05b94c9f098eea", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (PAL60) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "AUTO 60", "PAL60", "", "", "", "", "", "", "" }, - { "27baecd618e7e53dc11f2a9c559f529d", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "27c4c2af4b46394bb98638af8e0f6e9d", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "27c6a2ca16ad7d814626ceea62fa8fb4", "Parker Brothers, Mark Lesser", "PB5590", "Frogger II (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "27f9e2e1b92af9dc17c6155605c38e49", "CCE", "", "Nightmare (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2808dc745ff4321dc5c8122abef6711f", "Retroactive", "", "Qb (2.11) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "28148a52b1955ce12c7a74d3a3e620a4", "CCE", "", "Freeway (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "281ff9bd0470643853de5cbd6d9e17f5", "Eckhard Stolberg", "", "Cubis (EM) (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2823364702595feea24a3fbee138a243", "Bit Corporation", "PG206", "Bobby Is Going Home (1983) (BitCorp) (PAL)", "AKA Bobby geht Heim", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2825f4d068feba6973e61c84649489fe", "", "", "Boom Bang (Unknown) (PAL)", "AKA Crackpots", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "282a77841cb3d33af5b56151acba770e", "Otto Versand", "311388", "Black Hole (1983) (Otto Versand) (PAL)", "AKA Cosmic Ark (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "283cb03ee031c842beabdad1aa4e7dbc", "Bit Corporation", "R320", "Demon Attack (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "283dee88f295834c4c077d788f151125", "Retroactive", "", "Qb (2.11) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "284ca61b2407bdba3938048b0a559015", "Atari, Tod Frye", "CX2695", "Xevious (05-25-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2854e5dfb84173fafc5bf485c3e69d5a", "Canal 3 - Intellivision", "C 3004", "Moon Patrol (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2880c6b59bd54b153174676e465167c7", "Tron", "", "Donkey Kong Jr. (Tron)", "AKA Donkey Kong Junior", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "28a2bea8f84936cb2e063f857414cda0", "Thiago Paiva", "", "Mega Mania Raid (1999) (Thiago Paiva) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "28a4cd87fb9de4ee91693a38611cb53c", "", "", "Skeleton (V1.1) (NTSC) (24-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "28d5df3ed036ed63d33a31d0d8b85c47", "Bit Corporation", "PG204", "Open, Sesame! (1983) (BitCorp) (PAL)", "AKA Sesam, Offne Dich", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2903896d88a341511586d69fcfc20f7d", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "291bcdb05f2b37cdf9452d2bf08e0321", "Atari", "CX26163P", "32 in 1 Game Cartridge (1988) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "32IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "291cc37604bc899e8e065c30153fc4b9", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "291dd47588b9158beebe4accc3a093a6", "Atari", "", "32 in 1 Console ROM (02-10-1989) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "32IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "292a0bb975b2587f9ac784c960e1b453", "", "", "Qb (05-02-2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "292f2446a0325b7b423e88a2ebfeb5a0", "", "", "Cube Conquest (Non Interlaced) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "29396db58406084e416032c372734a3e", "", "", "Gunfight 2600 - Fixed Beta Release! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2942680c47beb9bf713a910706ffabfe", "", "", "Blue Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "294762000e853b4319f9991c1ced5dfc", "", "", "T.F. Space Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "295f3679bdf91ca5e37da3f787b29997", "", "", "Exorcise (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "29630a20d356fb58685b150bfa8f00c3", "M Network, Kevin Miller", "MT5687", "International Soccer (1982) (Mattel) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "297236cb9156be35679f83c4e38ee169", "Exus Corporation", "", "Video Reflex (1983) (Exus) [no roman numbers]", "AKA Foot Craz (no roman numbers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "297c405afd01f3ac48cdb67b00d273fe", "Atari - GCC, Ava-Robin Cohen", "CX26123, CX26123P", "Jr. Pac-Man (1986) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2982e655dffc89d218a0a3072cfc6811", "", "", "Mini Golf 812631 (Hack)", "Hack of Miniature Golf", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "298387b0637173d2002770a649b4fbca", "", "", "S.I.PLIX 2 (Hack) [a]", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "29843f43b81f3736bf35c00b1bb88fb2", "Gray Games & AtariAge", "", "E.T. Book Cart (NTSC)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "55", "", "", "", "" }, - { "29949f893ef6cb9e8ecb368b9e99eee4", "Erik Eid", "", "Euchre (Alpha) (NTSC) (31-08-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "29dfa26b7988af9984d617708e4fc6e2", "", "", "Boulderdash Demo (05-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2a0ba55e56e7a596146fa729acf0e109", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2a10053fd08664c7cfbbb104386ed77f", "", "", "Alpha Demo - The Beta Demo (2000) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2a1b454a5c3832b0240111e7fd73de8a", "Tigervision, Bill Hogue", "7-011", "Miner 2049er Volume II (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2a2f46b3f4000495239cbdad70f17c59", "CommaVid, John Bronstein - Ariola", "CM-003 - 712 003-720", "Cosmic Swarm (1982) (CommaVid) (PAL)", "AKA Angriff der Termiten", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2a33e21447bf9e13dcfed85077ff6b40", "", "", "Backwards Cannonball v2 (Hack)", "Hack of Human Cannonball", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2a360bc85bf22de438651cf92ffda1de", "Bit Corporation", "PGP213", "Spy Vs. Spy (4 Game in One) (1983) (BitCorp) (PAL)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2a9f9001540c55a302befd8e9d54b47b", "Atari, Dan Hitchens", "CX2697, CX2697P", "Mario Bros. (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2aa5e56d36c2e58b6f2856109f2099a9", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2aba6a1b01a5859e96d6a66d2286772f", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2abc3d46b3f2140160759e2e10bc86d9", "", "", "Gunfight 2600 - Beta Release! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2ac3a08cfbf1942ba169c3e9e6c47e09", "Activision, Dan Kitchen", "EAK-046-04B", "Fighter Pilot (1988) (Activision) (PAL)", "AKA Tomcat - The F-14 Fighter Simulator", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2ae700c9dba843a68dfdca40d7d86bd6", "TechnoVision - Thomas Jentzsch", "", "Pharaoh's Curse (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2aeedcc6eb1602efb77161b0cef832ab", "SOLID Corp. (D. Scott Williamson)", "CX2655-025", "Star Castle 2600 (SolidCorp) [025]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2b1589c7e1f394ae6a1c046944f06688", "Carrere Video - JWDA, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV - Teldec - Prism", "USC2003", "Eggomania (1983) (Carrere Video) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "2b27eb194e13f3b38d23c879cc1e3abf", "Quelle", "402.272 9", "Super-Ferrari (1983) (Quelle) (PAL)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2b42da79a682ed6e2d735facbf70107e", "", "", "DKjr Improved (Hack)", "Hack of Donkey Kong Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2b430c00dc79e495762ac59b2f9b4fcd", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2b71a59a53be5883399917bf582b7772", "Greg Troutman", "", "Dark Mage (final beta) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2ba02f509a4991aa176ba8d9e540df3d", "Atari, Mark R. Hahn", "CX2678", "Dukes of Hazzard (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bb0a1f1dee5226de648eb5f1c97f067", "Robby", "", "Enduro (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bb9f4686f7e08c5fcc69ec1a1c66fe7", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bc26619e31710a9884c110d8430c1da", "Atari, Bob Whitehead", "CX2652, CX2652P", "Casino (1979) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bc6c53b19e0097a242f22375a6a60ff", "", "", "Droid Demo 2 (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bee7f226d506c217163bad4ab1768c0", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2bf34b6ad7d2317a2d0808b3fb93571b", "", "", "Easy Playfield Graphics (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c0dc885d5ede94aa664bf3081add34e", "", "", "Earth Dies Screaming, The (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c29182edf0965a7f56fe0897d2f84ba", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (08-18-1990) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c2aea31b01c6126c1a43e10cacbfd58", "Paul Slocum", "", "Synthcart (2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2c3b2843295c9d6b16996971180a3fe9", "HES - Activision", "", "Sports Action Pak - Enduro, Ice Hockey, Fishing Derby, Dragster (1988) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c3b9c171e214e9e46bbaa12bdf8977e", "Bit Corporation", "R320", "Othello (32 in 1) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c45c3eb819a797237820a1816c532eb", "Atari", "CX26163P", "Boxing (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c8835aed7f52a0da9ade5226ee5aa75", "Arcadia Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2c8c11295d8613f875b7bcf5253ab9bb", "Fabrizio Zavagli", "", "Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) (PAL60)", "PAL60 Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "2c9fadd510509cc7f28f1ccba931855f", "", "", "Hangman Invader Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2ca6445204ffb7686ddee3e33ba64d5b", "Alex Herbert", "", "AtariVox Test ROM", "Uses the AtariVox controller", "", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "" }, - { "2cb42cf62b2f25f59f909b5447821b14", "Atari, Christopher H. Omarzu - Children's Computer Workshop", "CX26104", "Big Bird's Egg Catch (1983) (Atari) (PAL) [a]", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "2cc3049b7feb8e92f1870f1972629757", "Video Soft", "", "Atom Smasher (1984) (Video Soft) (Prototype) [stack pointer fix]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2cccc079c15e9af94246f867ffc7e9bf", "PlayAround - J.H.M.", "203", "Jungle Fever (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2cefa695df2ed020899a7df7bb1e3a95", "Manuel Polik, Fabrizio Zavagli", "", "A-Team (2002) (Manuel Polik) (Hack)", "Hack of A-Team", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2cf20f82abcae2decff88db99331e071", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2cfb188c1091cc7ec2a7e60064d2a758", "", "", "Space Invaders Hack Demo (2003) (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d15b092e8350912ec4b2e5e750fa1c6", "Wizard Video Games, Bob Davis, Robert H. O'Neil", "", "Texas Chainsaw Massacre, The (1982) (Wizard Video Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d16a8b59a225ea551667be45f554652", "Quelle", "802.744 3", "Der Geheimkurier (1983) (Quelle) (PAL)", "AKA Mr. Postman", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d1cf85fbc732856bf76470cd4060f4a", "", "", "Daredevil (V1) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d2c5f0761e609e3c5228766f446f7f8", "Atari - Axlon, Steve DeFrisco", "CX26170, CX26170P", "Secret Quest (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d33a44e82f88d05f6c50577218c0cae", "AtariAge - Michael Haas", "RC2", "Flappy (2014) (AtariAge)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d38a96f92952b301eefdf25a5e6976b", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) (Y_Inverted) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d405da70af82b20a6b3ecc3d1d2c4ec", "Genus", "", "Pitfall (Genus)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d6388a8389f1d59108fd169c3356d79", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d63b452f897818c52b3fceeb080a4d0", "HES - Absolute Entertainment", "", "Pete Rose Baseball (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d6741cda3000230f6bbdd5e31941c01", "CBS Electronics - VSS", "80110", "Targ (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d69a5f23784f1c2230143292a073b53", "", "", "Qb (Fixed background animation) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2d6da0eb85eabc93270e5bb8a466ca51", "", "", "Sprite Demo 7 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d76c5d1aad506442b9e9fb67765e051", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo", "AP-2004", "Lost Luggage (1982) (Apollo) [no opening scene]", "AKA Airport Mayhem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d9e5d8d083b6367eda880e80dfdfaeb", "QDI, Mike Montana, Rich Montana - Selchow & Righter", "87", "Glib (1983) (QDI)", "AKA Video Word Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2d9e65959808a6098c16c82a59c9d9dc", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2dbc92688f9ba92a7e086d62be9df79d", "", "", "How to Draw a Playfield (1997) (Jim Crawford) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2dbdca3058035d2b40c734dcf06a86d9", "Thomas Jentzsch", "", "Asteroids DC+ (Thomas Jentzsch) (Hack)", "Uses the Joystick (left) or Steering (right) Controller", "Hack", "", "", "", "", "", "", "", "", "DRIVING", "", "58", "", "", "YES", "", "", "", "", "" }, - { "2dcf9ce486393cd36ca0928cd53b96cb", "Atari - GCC, Mike Feinstein, John Allred", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2de41a11c6767e54a5ee9ebaffec72af", "Gray Games & AtariAge", "", "E.T. Book Cart (PAL60)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "55", "", "", "", "" }, - { "2dfec1615c49501fefc02165c81955e6", "", "", "Song (05-11-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2e0aed5bb619edcefa3fafb4fbe7c551", "", "", "Qb (2.06) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2e2acef8513edcca991e7e5149412e11", "Parker Brothers, Larry Gelberg, Gary Goltz", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (16K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e3728f3086dc3e71047ffd6b2d9f015", "Atari, David Crane", "CX26163P", "Outlaw (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e5b184da8a27c4d362b5a81f0b4a68f", "Atari", "", "Rabbit Transit (08-29-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e663eaa0d6b723b645e643750b942fd", "Atari, Tom Rudadahl - Sears", "CX2634 - 49-75121", "Golf (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e7e9c6dcfcceaffc6fa73f0d08a402a", "CCE", "C-818", "Star Voyager (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e82a1628ef6c735c0ab8fa92927e9b0", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2e842c2ee22e9dad9df16eed091315c4", "HES", "701-157", "2 Pak Special - Moto-cross, Boom Bang (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2eaf8fa9e9fdf1fcfc896926a4bdbf85", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur Version 39 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2ec6b045cfd7bc52d9cdfd1b1447d1e5", "Activision, David Crane - Ariola", "EAG-009, PAG-009 - 711 009-720", "Freeway (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2eda6a49a49fcb2b674ea9e160b6a617", "Kyle Pittman", "", "Rambo in Afghanistan (Kyle Pittman) (Hack)", "Hack of Riddle of the Sphinx", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2ef36341d1bf42e02c7ea2f71e024982", "", "", "Space Invaders (Explosion Hack)", "Hack of Space Invaders (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f0546c4d238551c7d64d884b618100c", "SEGA, Jeff Lorenz", "", "Ixion (1984) (SEGA) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f0a8bb4e18839f9b1dcaa2f5d02fd1d", "CCE", "", "Super Futebol (CCE) [a]", "AKA RealSports Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2f11ba54609777e2c6a5da9b302c98e8", "Atari - GCC", "CX2676", "Centipede (1982) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f16663b01591539624d0ef52934a17d", "M Network", "", "Rocky and Bullwinkle", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f2f9061398a74c80420b99ddecf6448", "Rentacom - Brazil", "", "Bobby Is Going Home (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f66ebf037321ed0442ac4b89ce22633", "Baroque Gaming (Brian Eno)", "", "Warring Worms (Beta 2) (2002) (Baroque Gaming)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f7772879a1ed04f660aa9d77a86a4bd", "", "", "Yars' Revenge (Genesis)", "Genesis controller (C is zorlon cannon)", "Hack of Yars' Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "2f77f015fc880b05f28e84156f989a0c", "", "", "Plane Demo (Gonzalo) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2f7949f71076db42480d3f5036b4a332", "", "", "Name This Game (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "2facd460a6828e0e476d3ac4b8c5f4f7", "Sancho - Tang's Electronic Co.", "", "Words-Attack (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3025bdc30b5aec9fb40668787f67d24c", "", "", "Demo Image Series #14 - Two Marios (4K Interleaved Chronocolour Vertical Movement) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "303242c239474f2d7763b843de58c1c3", "CCE", "", "Laser Blast (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "304512528a5530a9361e8a231ed9a6de", "Thomas Jentzsch", "", "River Raid Plus (Thomas Jentzsch) (Hack)", "Hack of River Raid", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "30512e0e83903fc05541d2f6a6a62654", "Atari, Jim Huether - Sears", "CX2644 - 6-99824", "Flag Capture (1978) (Atari)", "AKA Capture the Flag", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "30516cfbaa1bc3b5335ee53ad811f17a", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3051b6071cb26377cd428af155e1bfc4", "Atari, David Crane - Sears", "CX2607 - 6-99828, 49-75115", "Canyon Bomber (1979) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "10", "", "", "", "", "", "", "", "" }, - { "30685b9b6ebd9ba71536dd7632a1e3b6", "Dactari - Milmar", "", "Tennis (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3091af0ef1a61e801f4867783c21d45c", "CCE", "C-862", "Crackpots (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "30997031b668e37168d4d0e299ccc46f", "", "", "John K Harvey's Equalizer (PAL) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "30c92c685224dc7a72b9bbe5eb62d004", "", "", "Hangman Monkey Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "30e012e8d50330c8972f126b8e913bc4", "", "", "Indy 500 (Hack) [a2]", "Hack of Indy 500", "Hack", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "", "", "", "", "", "", "" }, - { "30e0ab8be713208ae9a978b34e9e8e8c", "Atari, Mike Lorenzen", "CX2630, CX2630P", "Circus Atari (1980) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, - { "30f0b49661cfcfd4ec63395fab837dc3", "SEGA, Jeff Lorenz - Teldec", "004-01", "Star Trek - Strategic Operations Simulator (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3105967f7222cc36a5ac6e5f6e89a0b4", "SEGA, Jeff Lorenz", "011-01, 011-02", "Spy Hunter (1984) (SEGA)", "Uses Joystick Coupler (Dual Control Module)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "310ba30e25ea8957e58180b663503c0c", "Ed Federmeyer", "", "Sound X6 (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31235a27b065c2863048fa84db330dc6", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (PAL) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "313243fc41e49ef6bd3aa9ebc0d372dd", "", "", "Fast Food (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31512cdfadfd82bfb6f196e3b0fd83cd", "Tigervision", "7-004", "River Patrol (1984) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3177cc5c04c1a4080a927dfa4099482b", "Atari - Imagineering, Alex DeMeo", "CX26135", "RealSports Boxing (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "317a4cdbab090dcc996833d07cb40165", "Goliath - Hot Shot", "83-312", "Missile War (1983) (Goliath) (PAL)", "AKA Astrowar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "318046ae3711c05fd16e479b298e5fcc", "Retroactive", "", "Qb (V2.08) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "318a9d6dda791268df92d72679914ac3", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "319a142aab6260842ab616382848c204", "", "", "Marble Craze (05-02-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31bb9b8ceed46cb3e506777a9e65f3ce", "Bit Corporation", "", "4 Game in One Light Green (1983) (BitCorp) (PAL)", "Phantom UFO, Ice Hockey, Cosmic Avenger, Spy Vs. Spy", "", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31c5fd55a39db5ff30a0da065f86c140", "Dactari - Milmar", "", "Enduro (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31d08cb465965f80d3541a57ec82c625", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31df1c50c4351e144c9a378adb8c10ba", "Quelle", "687.463 0", "Die Ratte und die Karotten (1983) (Quelle) (PAL)", "AKA Gopher", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31e518debba46df6226b535fa8bd2543", "Atari, Douglas 'Solaris' Neubauer, Mimi Nyden", "CX26134", "Last Starfighter (1984) (Atari) (Prototype)", "Solaris Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31f4692ee2ca07a7ce1f7a6a1dab4ac9", "Atari, Alan Miller", "CX2642", "Game of Concentration (1980) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "31fcbce1cfa6ec9f5b6de318e1f57647", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (1983) (Atari) (Prototype) (PAL)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32199271dc980eb31a2cc96e10a9e244", "", "", "Radial Pong - Version 12 (Jeffry Johnston) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "321c3451129357af42a375d12afd4450", "Atari - Imagineering, Dan Kitchen", "CX26177", "Ikari Warriors (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32244e55ce6ec6bfbd763f33384bdc2e", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3225676f5c0c577aeccfaa7e6bedd765", "CCE", "C-1002", "Pole Position (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "322b29e84455aa41e7cc9af463bffa89", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (06-25-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "324cb4a749bcac4f3db9da842b85d2f7", "Dennis Debro", "", "Climber 5 (01-05-2003) (Dennis Debro)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "327468d6c19697e65ab702f06502c7ed", "Charles Morgan", "", "Aster-Hawk (2002) (Charles Morgan) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3276c777cbe97cdd2b4a63ffc16b7151", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3278158e5c1f7eb5c5d28ccfd7285250", "Dactari - Milmar", "", "Megamania (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "327fe8cf94f3a45c35a840a453df1235", "", "", "Spice Girls Rule Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "328949872e454181223a80389d03c122", "", "", "Home Run (Unknown) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32ae78abbb5e677e2aabae5cc86cec29", "Atari, Christopher H. Omarzu, Courtney Granner", "CX26112", "Good Luck, Charlie Brown (04-18-1984) (Atari) (Prototype)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32d1260ea682e1bb10850fa94c04ec5f", "Atari, Alan Miller", "CX26163P", "Basketball (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32dcd1b535f564ee38143a70a8146efe", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox)", "AKA Thundarr the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32e65d1e4dfcbcd9b57fee72cafe074c", "", "", "Eckhard Stolberg's Scrolling Text Demo 3 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32ecb5a652eb73d287e883eea751d99c", "Dactar - Milmar", "", "Bowling (Dactar - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "32f4e47a71601ab06cfb59e1c6a0b846", "Ed Federmeyer", "", "Sound X (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3316ee2f887e9cb9b54dd23c5b98c3e2", "", "", "Texas Golf (miniature Gold Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "331938989f0f33ca39c10af4c09ff640", "Zach Matley", "", "Combat - Tank AI (19-04-2003) (Zach Matley)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "332f01fd18e99c6584f61aa45ee7791e", "", "", "X'Mission (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3347a6dd59049b15a38394aa2dafa585", "Parker Brothers - JWDA, Henry Will IV", "PB5760", "Montezuma's Revenge (1984) (Parker Bros)", "Featuring Panama Joe", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "335793736cbf6fc99c9359ed2a32a49d", "", "", "Analog Clock (V0.0) (20-01-2003) (AD) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "335a7c5cfa6fee0f35f5824d1fa09aed", "SEGA - Beck-Tech, Steve Beck, Phat Ho - Teldec", "006-01 - 3.60105 VG", "Congo Bongo (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3367eeba3269aa04720abe6169767502", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "336ea20d38f98926919d4b4651d1a03f", "Omegamatrix", "", "Omega Race (Genesis) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3391f7c4c656793f92299f4187e139f7", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a4]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "33cac5e767a534c95d292b04f439dc37", "Jone Yuan Telephonic Enterprise Co", "", "Tapeworm (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "33d68c3cd74e5bc4cf0df3716c5848bc", "CBS Electronics, Tom DiDomenico", "4L 2486 5000", "Blueprint (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "33ed6dfac4b9ea2f81f778ceddbb4a75", "Activision", "", "River Raid (1982) (SpkSoft) [t1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "340f546d59e72fb358c49ac2ca8482bb", "Sancho - Tang's Electronic Co.", "TEC003", "Skindiver (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34340c8eecd1e557314789cc6477e650", "Joe Grand", "", "SCSIcide Pre-release 4 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "345488d3b014b684a181108f0ef823cb", "CBS Electronics, Tom DiDomenico", "4L 2486 5000", "Blueprint (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "345758747b893e4c9bdde8877de47788", "CBS Electronics, Joseph Biel", "4L1802, 4L1803, 4L1804, 4L2278", "Venture (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "345769d085113d57937198262af52298", "Rainbow Vision - Suntek", "SS-007", "Space Raid (1983) (Rainbow Vision) (PAL)", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "346555779a2d51b48833463b5433472f", "Thomas Jentzsch", "", "Thrust (V0.1) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "348615ffa30fab3cec1441b5a76e9460", "Activision, Alan Miller - Ariola", "EAX-016, PAX-016 - 711 016-725", "StarMaster (1982) (Activision) (PAL) [fixed]", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34b269387fa1aa5a396636f5ecdd63dd", "", "", "Marble Craze (mc7_23) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34c808ad6577dbfa46169b73171585a3", "Apollo", "AP-2012", "Squoosh (1983) (Apollo) (Prototype)", "AKA Vat's Incredible!, The Grape Escape", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34ca2fcbc8ba4a0b544acd94991cfb50", "Atari, Robert C. Polaro", "", "Dukes of Hazzard (1980) (Atari) (Prototype) (4K)", "AKA Stunt Cycle", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34e37eaffc0d34e05e40ed883f848b40", "Retroactive", "", "Qb (2.15) (Retroactive) (Stella)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "34f4b1d809aa705ace6e46b13253fd3b", "Aaron Bergstrom", "", "Nothern Alliance (Aaron Bergstrom) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "34fd4fcb40ff5babce67f8b806d5969c", "", "", "Boxing (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "350e0f7b562ec5e457b3f5af013648db", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (06-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "35156407e54f67eb1f625450d5c093e1", "", "", "Mouse Trap (Genesis)", "Genesis controller (C changes to dog)", "Hack of Mouse Trap", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "35163b56f4a692a232ae96ad3e23310f", "Retroactive", "", "Qb (2.12) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3545eb3b8b1e7dc19f87d231ab0b1d4c", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "M8774, M8794", "Wizard of Wor (1982) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3556e125681aea864e17b09f3f3b2a75", "", "", "Incoming (2 Player Demo) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3576037c9281656655fa114a835be553", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3577e19714921912685bb0e32ddf943c", "TechnoVision - Video Technology", "TVS1003", "Pharaoh's Curse (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "35ae903dff7389755ad4a07f2fb7400c", "", "", "Colored Wall Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "35b10a248a7e67493ec43aeb9743538c", "Dor-x", "", "Defender (Dor-x) (Hack)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "35b43b54e83403bb3d71f519739a9549", "Parker Brothers, Dave Engman, Isabel Garret", "", "McDonald's (06-06-1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "35be55426c1fec32dfb503b4f0651572", "Men-A-Vision", "", "Air Raid (Men-A-Vision) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "35fa32256982774a4f134c3347882dff", "Retroactive", "", "Qb (V0.05) (Macintosh) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "360ba640f6810ec902b01a09cc8ab556", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (06-15-1983) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "360c0dcb11506e73bd0b77207c81bc62", "Digitel", "", "Enduro (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3619786f6a32efc1e4a262d5aca8a070", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3624e5568368929fabb55d7f9df1022e", "Activision - Imagineering, Donald Hahn, Dan Kitchen", "EAK-050-04", "Double Dragon (1989) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36306070f0c90a72461551a7a4f3a209", "U.S. Games Corporation - JWDA, Roger Booth, Sylvia Day, Ron Dubren, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV", "VC1007", "Name This Game (1983) (U.S. Games)", "AKA Octopussy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36547bc6faa5132b87504e18d088e1d7", "", "", "Cosmic Swarm (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "367411b78119299234772c08df10e134", "Atari", "CX26163P", "Skiing (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3685060707df27d4091ba0ea2dc4b059", "", "", "PezZerk - PezMan in Ghost Manor (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "368d88a6c071caba60b4f778615aae94", "Atari, Matthew L. Hubbard", "CX26159", "Double Dunk (1989) (Atari)", "AKA Super Basketball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36a701c60a9f9768d057bc2a83526a80", "", "", "Cube Conquest (Interlaced) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "36b20c427975760cb9cf4a47e41369e4", "Coleco - Woodside Design Associates - Imaginative Systems Software, Garry Kitchen", "2451", "Donkey Kong (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36c29ceee2c151b23a1ad7aa04bd529d", "Atari - GCC, Ava-Robin Cohen", "CX26123", "Jr. Pac-Man (1986) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36c31bb5daeb103f488c66de67ac5075", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, - { "36c993dc328933e4dd6374a8ffe224f4", "Gameworld, J. Ray Dettling", "133-007", "Bermuda Triangle (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36e47ed74968c365121eab60f48c6517", "Quelle", "343.373 7", "Master Builder (1983) (Quelle) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36edef446ab4c2395666efc672b92ed0", "Atari - Axlon, John Vifian", "CX26168", "Off the Wall (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "36f9a953ebdd9a8be97ccf27a2041903", "", "", "Chinese Character Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37252757a79dc5b174e3c03d6ea0bdcb", "", "", "Sky Diver (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "372bddf113d088bc572f94e98d8249f5", "Bomb - Onbase", "CA285", "Wall-Defender (1983) (Bomb) (PAL)", "AKA Wall Break", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "373b8a081acd98a895db0cb02df35673", "", "", "Demo Image Series #5 - Boofly (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3750f2375252b6a20e4628692e94e8b1", "Dismac", "", "Ases do Ar (Dismac)", "AKA Sky Jinks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37527966823ee9243d34c7da8302774f", "", "", "Word Zapper (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "376944889dcfa96c73d3079f308e3d32", "Retroactive", "", "Qb (0.11) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3783f12821b88b08814da8adb1a9f220", "", "", "Mission Survive (PAL) (Genesis)", "Genesis controller (C is vertical fire)", "Hack of Mission Survive)", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "378a62af6e9c12a760795ff4fc939656", "Atari - Axlon, Steve DeFrisco", "CX26171", "MotoRodeo (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "378c118b3bda502c73e76190ca089eef", "Atari, Alan Miller", "CX2662P", "Hangman (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37ab3affc7987995784b59fcd3fcbd31", "", "", "Sprite Test (29-11-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37b98344c8e0746c486caf5aaeec892a", "K-Tel Vision", "6", "Spider Maze (1982) (K-Tel Vision) (PAL)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37e828675d556775ae8285c0caf7d11c", "AtariAge - Fred Quimby", "", "Gingerbread Man (Fred Quimby) (Genesis)", "Genesis controller (C throws cookie)", "New Release", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "37f42ab50018497114f6b0f4f01aa9a1", "", "", "Droid Demo 2-M (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "37fd7fa52d358f66984948999f1213c5", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL) [a2]", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "PAL", "", "", "", "", "", "", "" }, - { "384db97670817103dd8c0bbdef132445", "Atari - Sears", "CX2626 - 6-99829, 49-75116", "Miniature Golf (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "384f5fbf57b5e92ed708935ebf8a8610", "20th Century Fox Video Games, John W.S. Marvin", "11009", "Crypts of Chaos (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3856b9425cc0185ed770376a62af0282", "Kyle Pittman", "", "Yellow Submarine (Kyle Pittman) (Hack)", "Hack of Bermuda Triangle", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "386ff28ac5e254ba1b1bac6916bcc93a", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "3882224adbd0ca7c748b2a1c9b87263e", "Atari, Tod Frye", "CX2657", "SwordQuest - FireWorld (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3889351c6c2100b9f3aef817a7e17a7a", "CCE", "", "Dolphin (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3897744dd3c756ea4b1542e5e181e02a", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (05-05-1983) (Atari) (Prototype)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "38bd172da8b2a3a176e517c213fcd5a6", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "38c362dcd5cad5a62e73ae52631bd9d8", "Jake Patterson", "", "Baubles (14-11-2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "38cf93eacfb2fa9a2c5e39059ff35a74", "Greg Zumwalt", "", "WacMan (2003) (Greg Zumwalt) (Hack)", "Hack of Ms. Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "38de7b68379770b9bd3f7bf000136eb0", "Imagic, Mark Klein", "EIZ-003-04I", "Subterranea (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "391764720140c432aec454a468f77a40", "Video Game Program", "", "Miss Pack Man (Video Game Program) (PAL)", "AKA Ms. Pac-Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "392d34c0498075dd58df0ce7cd491ea2", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "392f00fd1a074a3c15bc96b0a57d52a1", "Atari, Rob Fulop - Sears", "CX2633 - 49-75119", "Night Driver (1980) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "393948436d1f4cc3192410bb918f9724", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "393e41ca8bdd35b52bf6256a968a9b89", "U.S. Games Corporation - Western Technologies, John Hall", "VC1012", "M.A.D. (1983) (U.S. Games)", "AKA Missile Intercept, Mutually Assured Destruction", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3947eb7305b0c904256cdbc5c5956c0f", "Jone Yuan Telephonic Enterprise Co", "", "Lilly Adventure (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "396f7bc90ab4fa4975f8c74abe4e81f0", "Atari, Larry Kaplan - Sears", "CX2612 - 99804, 49-75103", "Street Racer (1977) (Atari)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "3974e2d1f614fbd3a092533ecae2e84d", "Alessandro Ciceri", "", "MagiCard+ (alex_79) WIP_20150118", "MagiCard hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39790a2e9030751d7db414e13f1b6960", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39a6a5a2e1f6297cceaa48bb03af02e9", "", "", "Pitfall 2 Plus (Hack)", "Hack of Pitfall 2", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39b94d41bd3b01c12b4054c1a8733783", "SOLID Corp. (D. Scott Williamson)", "CX2655-016", "Star Castle 2600 (SolidCorp) [016]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "39c78d682516d79130b379fa9deb8d1c", "Apollo - Games by Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39d36366ae7e6dfd53393fb9ebab02a0", "CCE", "C-811", "River Raid (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39da69ff9833f8c143f03b6e0e7a996b", "Charles Morgan", "", "Ventrra Invaders 2002 (Charles Morgan) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "39fe316952134b1277b6a81af8e05776", "Robby", "18", "River Raid (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a10562937a766cbbb77203d029b00e1", "Carrere Video - JWDA, Garry Kitchen, Paul Willson - Teldec - Prism", "USC1002", "Sneak 'n Peek (1983) (Carrere Video) (PAL)", "AKA Der Unsichtbare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a2e2d0c6892aa14544083dfb7762782", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3a35d7f1dc2a33565c8dca52baa86bc4", "", "", "Rubik's Cube Demo 2 (23-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a51a6860848e36e6d06ffe01b71fb13", "Retroactive", "", "Qb (2.07) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3a521b7e29123b2d38e34e3ff8dc255c", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a526e6a1f9fe918af0f2ce997dfea73", "CBS Electronics, Dan Kitchen, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1982) (CBS Electronics) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a53963f053b22599db6ac9686f7722f", "", "", "Word Zapper (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3a771876e4b61d42e3a3892ad885d889", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Defender II (1987) (Atari)", "AKA Stargate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3aad0ef62885736a5b8c6ccac0dbe00c", "Dynacom", "", "Atlantis (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ab5d138e26d88c8190e7cc629a89493", "", "", "Phased Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3ac6c50a8e62d4ce71595134cbd8035e", "Absolute Entertainment, Dan Kitchen", "AK-046-04", "Tomcat (1988) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ad3dc799211ccd424d7c6d454401436", "Probe 2000 - NAP", "", "Power Lords (1983) (Probe) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ad58b53a1e972396890bd86c735e78d", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur Version 36 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b040ed7d1ef8acb4efdeebebdaa2052", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b097a7ed5bd2a84dc3d3ed361e9c31c", "", "", "Interleaved ChronoColour Demo (PAL) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b10106836565e5db28c7823c0898fbb", "Xonox - Beck-Tech", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b2c32fcd331664d037952bcaa62df94", "Xonox", "6230, 6250", "Super Kung-Fu (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b5751a8d20f7de41eb069f76fecd5d7", "", "", "Eckhard Stolberg's Scrolling Text Demo 4 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b64a00ce147c3c29f7f8f8e531d08d8", "", "", "This Planet Sucks (16K) (Greg Troutman)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b69f8929373598e1752f43f8da61aa4", "Apollo - Games by Apollo - RCA Video Jeux", "AP-2006", "Infiltrate (1921) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3b6dba1a24bb2893bd3bd0593f92016b", "CBS Electronics / Thomas Jentzsch", "", "Omega Race JS (TJ)", "Hack of Omega Race (CBS Electronics)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b76242691730b2dd22ec0ceab351bc6", "M Network - INTV, Connie Goldman, Joe King, Patricia Lewis Du Long, Gerald Moore, Mike Sanders, Jossef Wagner", "MT4319", "Masters of the Universe (1983) (M Network)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3b80b8f52a0939e16b5059f93a3fc19a", "V007", "", "Virtual Pet (V007) (after Demo 2) (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b86a27132fb74d9b35d4783605a1bcb", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b8aacf5f5638492b926b5124de19f18", "Atari, Tod Frye - Sears", "CX2646 - 49-75185", "Pac-Man (1981) (Atari) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b91c347d8e6427edbe942a7a405290d", "Parker Brothers", "PB5350", "Sky Skipper (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b9480bb6fb1e358c9c0a64e86945aee", "", "", "Title Match Pro Wrestling (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3b966bf3c2ca34ac6ca1de4cf6383582", "", "", "Double-Height 6-Digit Score Display (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3bb9793c60c92911895cf44530846136", "Jone Yuan Telephonic Enterprise Co", "", "Dragster (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c21a89bc38d8cd0b010a2916bcff5c2", "", "", "Colony 7 - CX-22 Hack v0.4 (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, - { "3c3a2bb776dec245c7d6678b5a56ac10", "", "", "Unknown Title (bin00003) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c4223316c835ceaad619651e25df0f9", "", "", "Defender (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c4a6f613ca8ba27ce9e43c6c92a3128", "", "", "Qb (V0.04) (Non-Lax Version) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3c57748c8286cf9e821ecd064f21aaa9", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c72ddaf41158fdd66e4f1cb90d4fd29", "Dismac", "", "Comando Suicida (Dismac)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c7a7b3a0a7e6319b2fa0f923ef6c9af", "Atari - Roklan, Joe Gaucher", "", "Racer (1982) (Atari) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c7a96978f52b2b15426cdd50f2c4048", "", "", "Overhead Adventure Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c82e808fe0e6a006dc0c4e714d36209", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3c853d864a1d5534ed0d4b325347f131", "Telesys, Don 'Donyo' Ruffcorn", "1002", "Cosmic Creeps (1982) (Telesys)", "AKA Space Maze, Spaze Maze", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3c8e57a246742fa5d59e517134c0b4e6", "Parker Brothers, Rex Bradford, Sam Kjellman", "PB5050", "Star Wars - The Empire Strikes Back (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ca51b5c08f5a0ecfb17d0c1ec6d0942", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (09-28-81) (Atari) (Prototype)", "AKA Mystery Mansion, Graves' Manor, Nightmare Manor", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3caa902ac0ce4509308990645876426a", "Atari - GCC, Dave Payne", "CX2669, CX2669P", "Vanguard (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3cbdf71bb9fd261fbc433717f547d738", "CCE", "C-803", "Bobby Is Going Home (1983) (CCE) (PAL)", "AKA Bobby Vai Para Casa", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3cdd91e1c28d28e856c0063d602da166", "", "", "Stell-A-Sketch (03-11-1997) (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3d1e83afdb4265fa2fb84819c9cfd39c", "Coleco - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "2465", "Smurf - Rescue in Gargamel's Castle (1983) (Coleco)", "AKA Smurf, Smurf Action", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d2367b2b09c28f1659c082bb46a7334", "Imagic, Dennis Koble", "720103-2A, IA3203P, EIX-010-04I", "Atlantis (1982) (Imagic) (PAL)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d2652cbea462a886a41791dd7c8d073", "", "", "Ritorno dei frattelli di Mario (Mario Bros Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d48b8b586a09bdbf49f1a016bf4d29a", "Video Game Cartridge - Ariola", "TP-606", "Hole Hunter (Video Game Cartridge)", "AKA Topy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d6fc7a19be76d808aa233415cb583fc", "CCE", "C-833", "Target Practice (1983) (CCE)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d7749fb9c2f91a276dfe494495234c5", "Jone Yuan Telephonic Enterprise Co", "", "Checkers (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d7aad37c55692814211c8b590a0334c", "Atari, Dan Oliver", "", "Telepathy (1983) (Atari) (Prototype)", "Uses both left joystick and right Mindlink controllers (press Fire on respective controller to begin)", "Prototype", "", "", "", "", "", "", "", "", "MINDLINK", "", "78", "", "", "", "", "", "", "", "" }, - { "3d8a2d6493123a53ade45e3e2c5cafa0", "Atari, Jim Huether - Sears", "CX2629 - 6-99843, 49-75118", "Sky Diver (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d934bb980e2e63e1ead3e7756928ccd", "Activision, Steve Cartwright - Ariola", "EAX-017, EAX-017-04I - 711 017-720", "MegaMania (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3d9c2fccf8b11630762ff00811c19277", "", "", "Challenge of.... Nexar, The (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3da7cc7049d73d34920bb73817bd05a9", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3dfb7c1803f937fadc652a3e95ff7dc6", "Dimax - Sinmax", "SM8001", "Space Robot (Dimax - Sinmax)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3e03086da53ecc29d855d8edf10962cb", "CBS Electronics - Roklan, Joe Gaucher, Alex Leavens", "4L1751, 4L1752, 4L1753, 4L2275", "Gorf (1982) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3e1682ddaec486d8b6b90b527aaa0fc4", "Thomas Jentzsch", "", "Robot City (V0.12) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e22c7eaf6459b67388602e4bebbb3a8", "CommaVid, John Bronstein - Ariola", "CM-003 - 712 003-720", "Cosmic Swarm (1982) (CommaVid) (PAL) (4K)", "AKA Angriff der Termiten", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e33ac10dcf2dff014bc1decf8a9aea4", "Spectravideo - Video Games Industries Corporation, Michael Schwartz - Ralston Purina", "", "Chase the Chuckwagon (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3e49da621193d2611a4ea152d5d5ca3a", "", "", "Atari Logo Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e4b1137433cc1e617b5508619e13063", "", "", "Asteroids (Genesis)", "Genesis controller (C is hyperspace)", "Hack of Asteroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3e5ca1afaa27c5da3c54c9942fec528b", "", "", "2600 Digital Clock (Demo 2) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e6dab92009d6034618cb6b7844c5216", "", "", "Ed Invaders (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e7d10d0a911afc4b492d06c99863e65", "VGS", "", "Super Tenis (VGS)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e88cca5b860d0bd8947479e74c44284", "Atari, Lou Harp", "CX26122", "Sinistar (01-23-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3e899eba0ca8cd2972da1ae5479b4f0d", "Coleco, Joseph Biel", "2457", "Venture (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3e90cf23106f2e08b2781e41299de556", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3eae062a9b722bda1255d474a87eca5c", "Atari, David Crane", "CX2605, CX2605P", "Outlaw (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3eb1e34a4f0eec36f12e7336badcecf2", "Jake Patterson", "", "Baubles (V0.001) (2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3eb21313ea5d5764c5ed9160a5a55a83", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ec12372ca3e870b11ca70edc7ec26a4", "CommaVid, John Bronstein", "CM-002", "Video Life (1981) (CommaVid) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3eccf9f363f5c5de0c8b174a535dc83b", "", "", "Plaque Attack (Unknown) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ef9573536730dcd6d9c20b6822dbdc4", "Atari, Larry Wagner, Bob Whitehead", "CX2645, CX2645P", "Video Chess (1979) (Atari) (PAL)", "AKA Computer Chess", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f01bd6d059396f495a4cde7de0ab180", "", "", "Qb (Special Edition) (NTSC) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "3f039981255691d3859d04ef813a1264", "Xonox, John Perkins", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) [a]", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f251c50aa7237e61a38ab42315ebed4", "Thomas Jentzsch", "", "Ikari Warriors (1990) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f3ad2765c874ca13c015ca6a44a40a1", "CCE", "C-862", "Crackpots (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f540a30fdee0b20aed7288e4a5ea528", "Atari - GCC", "CX2670", "Atari Video Cube (1983) (Atari)", "AKA Atari Cube, Video Cube", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f58f972276d1e4e0e09582521ed7a5b", "Telegames", "6082 A145", "Kung Fu Superkicks (1988) (Telegames)", "AKA Chuck Norris Superkicks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f5a43602f960ede330cd2f43a25139e", "Activision, Alan Miller", "AG-003", "Checkers (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f6938aa6ce66e6f42e582c1eb19b18c", "Jone Yuan Telephonic Enterprise Co", "", "Laser Blast (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f6dbf448f25e2bd06dea44248eb122d", "", "5687 A279", "Soccer (1988) (Telegames)", "AKA International Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f75a5da3e40d486b21dfc1c8517adc0", "Atari, Jim Huether", "CX26163P", "Sky Diver (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f9431cc8c5e2f220b2ac14bbc8231f4", "", "", "Colors Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f96eb711928a6fac667c04ecd41f59f", "Bit Corporation", "PGP218", "Rodeo Champ (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3f9cb1aba8ec20e2c243ae642f9942bf", "", "", "New Questions (1998) (John K. Harvey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3fd1f9d66a418c9f787fc5799174ddb7", "Aaron Curtis", "", "AStar (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3fd53bfeee39064c945a769f17815a7f", "CCE", "", "Sea Hawk (CCE)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3fe43915e5655cf69485364e9f464097", "CCE", "C-863", "Fisher Price (1983) (CCE)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "3ff5165378213dab531ffa4f1a41ae45", "Otto Versand", "311377", "Pygmy (1983) (Otto Versand) (PAL)", "AKA Lock 'n' Chase (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4026ad38ba5ce486e88383dc27d7a46f", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "402b1ca3c230a60fb279d4a2a10fa677", "", "", "3-D Tic-Tac-Toe (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "402d876ec4a73f9e3133f8f7f7992a1e", "Alex Herbert", "", "Man Goes Down (2006) (A. Herbert) (Prototype)", "Uses AtariVox controller", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "" }, - { "405f8591b6941cff56c9b392c2d5e4e5", "Telegames", "", "Star Strike (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4066309eb3fa3e7a725585b9814bc375", "", "", "Multi Ball Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4066d7d88ec4a2c656127a67fa52dcf1", "", "", "Overhead Adventure Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "407a0c6cc0ff777f67b669440d68a242", "Erik Eid", "", "Euchre (Alpha) (PAL) (31-08-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4093382187f8387e6d011883e8ea519b", "", "", "Go Go Home (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40aa851e8d0f1c555176a5e209a5fabb", "", "", "Euchre (More for less) (NTSC) (22-08-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40b1832177c63ebf81e6c5b61aaffd3a", "Atari, Peter C. Niday", "", "Rubik's Cube 3-D (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40b59249e05135bca33861e383735e9e", "Atari", "CX26163P", "Skiing (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40d8ed6a5106245aa79f05642a961485", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40d9f5709877ecf3dd1184f9791dd35e", "Dactari - Milmar", "", "Skiing (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40e12c008037a323a1290c8fa4d2fe7f", "", "", "Skeleton (NTSC) (06-09-2002) (Eric Ball)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "40eb4e263581b3dfec6dd8920b68e00f", "Sears Tele-Games, Marilyn Churchill, Matthew L. Hubbard", "CX2647 - 49-75142", "Seawolf 3 (03-23-1981) (Sears) (Prototype) (PAL)", "Submarine Commander Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "413c925c5fdcea62842a63a4c671a5f2", "Activision, Larry Kaplan", "AX-006", "Bridge (1980) (Activision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4153dd2beed648e9dc082140ebe8e836", "Thomas Jentzsch", "", "Coke Zero (v1.0) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "415c11fcac66bbd2ace2096687774b5a", "", "", "Fu Kung! (V0.00) (07-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4181087389a79c7f59611fb51c263137", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (06-24-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "41810dd94bd0de1110bedc5092bef5b0", "Funvision - Fund. International Co.", "", "Dragon Treasure (Funvision)", "AKA Dragonfire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "41818738ab1745e879024a17784d71f5", "CCE", "C-832", "Atlantis (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4189adfc1b30c121248876e3a1a3ac7e", "Eric Ball", "", "Skeleton (Complete) (06-09-2002) (Eric Ball)", "", "New Release", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4191b671bcd8237fc8e297b4947f2990", "Exus Corporation", "", "Video Jogger (1983) (Exus)", "AKA Foot Craz", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "41b554c6970b18670acc7b6baef8ed2e", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "41c4e3d45a06df9d21b7aae6ae7e9912", "CCE", "C-826", "Grand Prix (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "41f252a66c6301f1e8ab3612c19bc5d4", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (1983) (Atari)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4209e9dcdf05614e290167a1c033cfd2", "CommaVid, John Bronstein", "CM-002", "Video Life (1984) (CommaVid) [higher sounds]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "42249ec8043a9a0203dde0b5bb46d8c4", "CCE", "", "Resgate Espacial (CCE)", "AKA Moonsweeper", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4233eb824c2b4811abef9b6d00355ae9", "Retroactive", "", "Qb (V0.10) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4251b4557ea6953e88afb22a3a868724", "Thomas Jentzsch", "", "Robot City (V1.1) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "425ee444a41d218598893d6b6e03431a", "Thomas Jentzsch", "", "Invaders Demo (2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4279485e922b34f127a88904b31ce9fa", "", "", "Enduro (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "428b2d36f5d716765460701f7016ac91", "Andrew Wallace", "", "Brooni (2001) (Andrew Wallace) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42ae81ae8ac51e5c238639f9f77d91ae", "", "", "Multi-Sprite Demo 2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42b2c3b4545f1499a083cfbc4a3b7640", "U.S. Games Corporation - JWDA, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV", "VC2003", "Eggomania (1982) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "42b3ab3cf661929bdc77b621a8c37574", "Robby", "", "Volleyball (Robby)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42b5e3a35b032f033809afb0ea28802d", "Atari, Mimi Nyden, Scott Smith, Robert Vieira", "CX26127", "Gremlins (03-12-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42cdd6a9e42a3639e190722b8ea3fc51", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42dcc02777b0bcfacd85aeb61d33558a", "", "", "Human Cannonball (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "42e0ec5ab8f5deba53e4169ff2a5efbe", "", "", "Atari Logo Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4311a4115fb7bc68477c96cf44cebacf", "", "", "Challenge (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4326edb70ff20d0ee5ba58fa5cb09d60", "Atari - GCC, Kevin Osborn", "CX2689", "Kangaroo (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "435fd469f088468c4d66be6b5204d887", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "438968a26b7cfe14a499f5bbbbf844db", "", "", "Raft Rider (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "43adf60ebdd6b5a0fae21594ecf17154", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "43c6cfffeddab6b3787357fed9d44529", "20th Century Fox Video Games, Frank Cohen, Douglas 'Dallas North' Neubauer", "11111", "M.A.S.H (1983) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "43f33c6dfdeaf5138ce6e6968ad7c5ce", "Jeffry Johnston", "", "Radial Pong - Version 11 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "43f8459d39fb4eddf9186d62722ff795", "", "", "Skeleton+ (17-04-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "442602713cb45b9321ee93c6ea28a5d0", "", "", "Demon Attack (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4427f06085bb4c22ff047027f7acecc2", "Parker Brothers, Rex Bradford", "PB5000", "Star Wars - Jedi Arena (1983) (Parker Bros) (Prototype)", "Uses the Paddle Controllers (swapped)", "Prototype", "", "", "", "", "", "", "", "", "", "YES", "10 50", "", "", "", "", "", "", "", "" }, - { "442b7863683e5f084716fda050474feb", "Eckhard Stolberg", "", "Frame Timed Sound Effects-EM (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4431428a7500c96fc0e2798a5dbd36d6", "", "", "Kangaroo (Genesis)", "Genesis controller (B is punch, C is jump)", "Hack of Kangaroo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4474b3ad3bf6aabe719a2d7f1d1fb4cc", "Activision - Imagineering, Dan Kitchen, Garry Kitchen", "EAX-039-04B, EAX-039-04I", "Kung-Fu Master (1987) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4476c39736090dabac09f6caf835fc49", "", "", "Text Screen (25-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "448c2a175afc8df174d6ff4cce12c794", "Activision, David Crane", "AB-035-04", "Pitfall II (1983) (Activision) [a2]", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "44e9c4a047c348dbeb7ace60f45484b4", "", "", "Moon Patrol Arcade (Genesis)", "Genesis controller (C is jump)", "Hack of Moon Patrol", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "44f71e70b89dcc7cf39dfd622cfb9a27", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45027dde2be5bdd0cab522b80632717d", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00250", "Summer Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45040679d72b101189c298a864a5b5ba", "20th Century Fox Video Games - Sirius Software, David Lubar", "11022", "SpaceMaster X-7 (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4543b7691914dfd69c3755a5287a95e1", "CommaVid, Irwin Gaines", "CM-005", "Mines of Minos (1982) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "456453a54ca65191781aef316343ae00", "", "", "Full Screen Bitmap (3-D Green) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4565c1a7abce773e53c75b35414adefd", "Arcadia Corporation", "", "Supercharger BIOS (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "457b03cd48ff6d895795ef043c6b0f1e", "AtariAge, Chris Spry", "CX26201", "Zippy the Porcupine (2014) (Sprybug)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "457e7d4fcd56ebc47f5925dbea3ee427", "Carrere Video - JWDA, Garry Kitchen - Teldec - Prism", "USC1001", "Space Jockey (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "457f4ad2cda5f4803f122508bfbde3f5", "", "", "Canyon Bomber (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "458883f1d952cd772cf0057abca57497", "", "", "Fishing Derby (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45a095645696a217e416e4bd2baea723", "Digivision", "", "Snoopy (Digivision)", "AKA Snoopy and the Red Baron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45a4f55bb9a5083d470ad479afd8bca2", "CommaVid, Joseph Biel", "", "Frog Demo (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45beef9da1a7e45f37f3f445f769a0b3", "Atari, Suki Lee", "CX2658", "Math Gran Prix (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45c4413dd703b9cfea49a13709d560eb", "Jone Yuan Telephonic Enterprise Co", "", "Challenge of.... Nexar, The (Jone Yuan) (Hack)", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "45cb0f41774b78def53331e4c3bf3362", "Carrere Video - JWDA, Roger Booth, Sylvia Day, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV - Teldec - Prism", "USC1007", "Octopus (1983) (Carrere Video) (PAL)", "AKA Name This Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4605a00f5b44a9cbd5803a7a55de150e", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (07-03-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "461029ab23800833e9645be3e472d470", "", "", "Combat TC (v0.1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "46258bd92b1f66f4cb47864d7654f542", "Zellers", "", "Turmoil (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "463dd4770506e6c0ef993a40c52c47be", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (Preview) (1982) (Arcadia)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "463e66ad98806a49106cffa49c08e2ed", "", "", "Interlace Game Demo (01-09-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "467340a18158649aa5e02a4372dcfccd", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4689081b7363721858756fe781cc7713", "", "", "Oystron (V2.6) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "468f2dec984f3d4114ea84f05edf82b6", "Tigervision - Teldec", "7-011 - 3.60015 VG", "Miner 2049er Volume II (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4690fdb70c86604bb35da26696818667", "", "", "Euchre (Release Candidate) (NTSC) (28-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "469473ff6fed8cc8d65f3c334f963aab", "Atari, Bruce Poehlman, Gary Stark", "", "Dune (07-10-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "46c021a3e9e2fd00919ca3dd1a6b76d8", "Atari, Jim Huether - Sears", "CX2629 - 6-99843, 49-75118", "Sky Diver (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "46c43fdcbce8fde3a91ebeafc05b7cbd", "", "", "Invaders Demo (PAL) (2001) (Eckhard Stolberg)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "46dc526773808c8b9bb2111f24e5704c", "Omegamatrix", "", "SpaceMaster X-7 (Atari Mouse) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "46e9428848c9ea71a4d8f91ff81ac9cc", "Telegames", "", "Astroblast (1988) (Telegames) (PAL)", "Can also use left joystick", "", "", "", "", "", "", "", "", "PADDLES", "", "YES", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "4702d8d9b48a332724af198aeac9e469", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "470878b9917ea0348d64b5750af149aa", "Atari, Suki Lee - Sears", "CX2658 - 49-75128", "Math Gran Prix (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "471f7bdc933e8db0e44aa3dde2dd92af", "Omegamatrix", "", "Millipede (Atari Mouse) v6.5 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47464694e9cce07fdbfd096605bf39d4", "Activision, Dan Kitchen", "EAK-050-04", "Double Dragon (1989) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47585c047802dd9af888b998fb921f32", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) v4 (PAL60) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "4767356fa0ed3ebe21437b4473d4ee28", "Atari, Dan Hitchens, Mimi Nyden", "CX2685", "Gravitar (04-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47711c44723da5d67047990157dcb5dd", "CCE", "", "Ice Hockey (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47911752bf113a2496dbb66c70c9e70c", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (1984) (Atari) (PAL)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "4799a40b6e889370b7ee55c17ba65141", "Konami", "RC 100-X 02", "Pooyan (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47aad247cce2534fd70c412cb483c7e0", "Rainbow Vision - Suntek", "SS-010", "Mafia (1983) (Rainbow Vision) (PAL)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47abfb993ff14f502f88cf988092e055", "Zellers", "", "Inca Gold (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "47aef18509051bab493589cb2619170b", "", "", "Stell-A-Sketch (Bob Colbert) (PD)", "Uses Driving, Joystick, or Amiga/Atari ST mouse Controllers", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "47b82d47e491ac7fdb5053a88fccc832", "Atari Freak 1, Franklin Cruz", "", "Asteroid 2 (Atari Freak 1) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "47cd61f83457a0890de381e478f5cf5f", "Imagic, Wilfredo Aguilar, Michael Becker, Rob Fulop", "720111-2A, 13205", "Fathom (1983) (Imagic) (PAL)", "AKA Scuba", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "481d20ec22e7a63e818d5ef9679d548b", "Atari", "CX26163P", "Freeway Rabbit (32 in 1) (1988) (Atari) (PAL)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "481f9a742052801cc5f3defb41cb638e", "Jeffry Johnston", "", "Radial Pong - Version 4 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "48287a9323a0ae6ab15e671ac2a87598", "Zellers", "", "Laser Volley (Zellers)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4834b7b28ea862227ac7e40053fb52a5", "Nukey Shay", "", "Montezuma's Revenge (Genesis) (F6_Conversion)", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "48411c9ef7e2cef1d6b2bee0e6055c27", "Telesys, Don Ruffcorn, Jack Woodman", "1003", "Fast Food (1982) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "484b0076816a104875e00467d431c2d2", "Atari", "CX26150", "Q-bert (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4857f8bb88bb63c640d3ea5aac7f5d6d", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (08-12-81) (Atari) (Prototype)", "AKA Mystery Mansion, Graves' Manor, Nightmare Manor", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4868a81e1b6031ed66ecd60547e6ec85", "Eric Mooney", "", "Invaders by Erik Mooney (V2.1) (1-3-98) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "487193a7b7fe57a1bbc2f431f628bd5f", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4884b1297500bd1243659e43c7e7579e", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (10-24-1991) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4892b85c248131d6a42c66a4163a40d0", "Canal 3 - Intellivision", "", "Tac-Scan (Canal 3)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "48bcf2c5a8c80f18b24c55db96845472", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "48e5c4ae4f2d3b62b35a87bca18dc9f5", "Quelle", "476.774 5", "Bobby geht nach Hause (1983) (Quelle) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "48f18d69799a5f5451a5f0d17876acef", "ZiMAG - Emag - Vidco", "GN-070", "Mysterious Thief, A (1983) (ZiMAG) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4901c05068512828367fde3fb22199fe", "Imagic, Rob Fulop", "720101-2B, IA3200P, EIX-006-04I", "Demon Attack (1982) (Imagic) (PAL)", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4904a2550759b9b4570e886374f9d092", "Parker Brothers, Charlie Heath", "931506", "Reactor (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "490e3cc59d82f85fae817cdf767ea7a0", "", "", "Berzerk (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "490eed07d4691b27f473953fbea6541a", "Activision, Steve Cartwright, David Crane", "AB-035-04", "Pitfall II (1983) (Activision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "493daaf9fb1ba450eba6b8ed53ffb37d", "", "", "3-D Corridor Demo (27-03-2003) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "493de059b32f84ab29cde6213964aeee", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Stargate (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "493e90602a4434b117c91c95e73828d1", "Telegames", "", "Lock 'n' Chase (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4947c9de2e28b2f5f3b0c40ce7e56d93", "", "", "3-D Corridor Demo 2 (29-03-2003) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "494cda91cc640551b4898c82be058dd9", "Andreas Dietrich", "", "Donkey Kong VCS (2017) (1.0) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "49571b26f46620a85f93448359324c28", "", "", "Save Our Ship (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "497c811026367c08fd838c9c59e5041d", "Omegamatrix", "", "SpaceMaster X-7 (Atari Trak-Ball) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "497f3d2970c43e5224be99f75e97cbbb", "CommaVid, John Bronstein", "CM-002", "Video Life (1984) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4981cefe5493ea512284e7f9f27d1e54", "Home Vision - Gem International Corp. - VDI", "VCS83136", "Cosmic War (1983) (Home Vision) (PAL)", "AKA Space Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4999b45be0ab5a85bac1b7c0e551542b", "CCE", "", "Double Dragon (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "499b612f6544ae71d4915aa63e403e10", "Atari, Carol Shaw", "CX26163P", "Checkers (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "49f2cef5269fd06218be9f9474c74f8d", "Rentacom", "", "Time Pilot (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a196713a21ef07a3f74cf51784c6b12", "Jone Yuan Telephonic Enterprise Co", "", "Frogs and Flies (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a2fe6f0f6317f006fd6d4b34515448b", "", "", "Warring Worms (Midwest Classic Edition) (08-06-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a45c6d75b1ba131f94a9c13194d8e46", "", "", "How to Draw a Playfield II (Joystick Hack) (1997) (Eric Bacher) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a5fddf89801336637ac8e57a7c9a881", "Amiga", "1125", "Power Play Arcade Video Game Album IV (1984) (Amiga) (Prototype)", "Atlantis, Cosmic Ark, Dragonfire", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a6be79310f86f0bebc7dfcba4d74161", "", "", "Demolition Herby (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4a7eee19c2dfb6aeb4d9d0a01d37e127", "Hozer Video Games", "", "Crazy Valet (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a8c743396b8ad69d97e6fd3dd3e3132", "Arcadia Corporation", "", "Supercharger BIOS (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4a9009620038f7f30aaeb2a00ae58fde", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (3 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ab2ebd95a8f861ea451abebdad914a5", "Nukey Shay, Thomas Jentzsch", "PAL conversion (F6)", "Montezuma's Revenge (PAL) (Genesis)", "Genesis controller (B jumps left, C jumps right)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ab4af3adcdae8cdacc3d06084fc8d6a", "Nick Bensema", "", "Sucky Zepplin (Nick Bensema) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4abb4c87a4c5f5d0c14ead2bb36251be", "Atari - Imagineering, Alex DeMeo", "CX26135, CX26135P", "RealSports Boxing (1987) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ac9f40ddfcf194bd8732a75b3f2f214", "Atari - CCW, Stephan R. Keith, Laura Scholl, Preston Stuart", "CX26106", "Grover's Music Maker (12-29-1982) (Atari) (Prototype)", "Uses Keypad Controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ae8c76cd6f24a2e181ae874d4d2aa3d", "", "", "Flash Gordon (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4af4103759d603c82b1c9c5acd2d8faf", "Imagic, Bob Smith", "720114-2A, 13207, EIZ-001-04I", "Moonsweeper (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4afa7f377eae1cafb4265c68f73f2718", "Ed Fries", "", "Halo 2600 (2010) (Ed Fries)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4afe528a082f0d008e7319ebd481248d", "", "", "Multi-Color Demo 1 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b143d7dcf6c96796c37090cba045f4f", "Atari, Jim Huether - Sears", "CX2644 - 6-99824", "Flag Capture (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b205ef73a5779acc5759bde3f6d33ed", "", "", "Berzerk (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b27f5397c442d25f0c418ccdacf1926", "Atari, Warren Robinett", "CX2613, 49-75154", "Adventure (1980) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b379b885e2694f992c6cc932f18327f", "Omegamatrix", "", "SpaceMaster X-7 (Atari Mouse) (PAL60) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "4b71197153d651480830638cb6a03249", "Atari, Larry Kaplan", "CX26163P", "Bowling (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b753a97aee91e4b3e4e02f5e9758c72", "Glenn Saunders, Roger Williams", "", "Asymmetric Reflected Playfield (Glenn Saunders)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4b94fd272785d7ec6c95fb7279d0f522", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (12-03-1982) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "4b9581c3100a1ef05eac1535d25385aa", "", "", "IQ 180 (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4baada22435320d185c95b7dd2bcdb24", "Atari, Jerome Domurat, Dave Staugas", "CX2682", "Krull (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4bcc7f6ba501a26ee785b7efbfb0fdc8", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4bdae9246d6ee258c26665512c1c8de3", "Atari", "CX26163P", "Human Cannonball (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4bdf54a454470ba015a217a8f5e61320", "Omegamatrix", "", "Millipede (Amiga Mouse) v6.5 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "4c030667d07d1438f0e5c458a90978d8", "Retroactive", "", "Qb (V2.03) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4c0fb2544ae0f8b5f7ae8bce7bd7f134", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (Preview) (1983) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c205f166157154df2f1ef60d87e552f", "", "", "Single-Scanline Positioning Demo 2 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c39a2c97917d3d71739b3e21f60bba5", "", "", "Whale (Sub Scan Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c462b2b6fb0a19a1437eb2c3dc20783", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c4ce802cbfd160f7b3ec0f13f2a29df", "", "", "Beta Demo (V1.1) (26-09-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c606235f4ec5d2a4b89139093a69437", "Andrew Davies", "", "Andrew Davies early notBoulderDash demo (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4c6afb8a44adf8e28f49164c84144bfe", "CCE", "C-806", "Mission 3,000 A.D. (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c8832ed387bbafc055320c05205bc08", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c8970f6c294a0a54c9c45e5e8445f93", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4c9307de724c36fd487af6c99ca078f2", "Imagic, Brad Stewart", "720106-1A, IA3409", "Sky Patrol (1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ca0959f846d2beada18ecf29efe137e", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666, CX2666P", "RealSports Volleyball (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ca73eb959299471788f0b685c3ba0b5", "Activision, Steve Cartwright", "AX-031", "Frostbite (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4ca90ba45eced6f5ad560ea8938641b2", "", "", "Hangman Man Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4cabc895ea546022c2ecaa5129036634", "Funvision - Fund. International Co.", "", "Ocean City (Funvision)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4cd796b5911ed3f1062e805a3df33d98", "Tigervision - Software Electronics Corporation - Teldec", "7-006", "Springer (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d06f72cc3d8934579c11ff8f375c260", "Bit Corporation", "R320", "Bowling (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d0a28443f7df5f883cf669894164cfa", "", "", "Beast Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d2cef8f19cafeec72d142e34a1bbc03", "HES", "771-422", "2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d38e1105c3a5f0b3119a805f261fcb5", "Bit Corporation", "PGP212", "Phantom UFO (4 Game in One Light Green) (1983) (BitCorp) (PAL)", "AKA Spider Fighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d502d6fb5b992ee0591569144128f99", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (11-21-1989) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d5f6db55f7f44fd0253258e810bde21", "Fabrizio Zavagli", "", "Betterblast (Fabrizio Zavagli) (Hack)", "Hack of Astroblast", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d7517ae69f95cfbc053be01312b7dba", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d77f291dca1518d7d8e47838695f54b", "Data Age", "DA1004", "Airlock (1982) (Data Age)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4d8396deeabb40b5e8578276eb5a8b6d", "Otto Versand", "781698", "Volleyball (1983) (Otto Versand) (PAL)", "AKA RealSports Volleyball (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4dbd7e8b30e715efc8d71d215aec7fe7", "Bit Corporation", "R320", "Air Raiders (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4dbf47c7f5ac767a3b07843a530d29a5", "Ric Pryor", "", "Breaking News (2002) (Ric Pryor) (Hack)", "Hack of Bump 'n' Jump", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4dcc7e7c2ec0738e26c817b9383091af", "", "", "Unknown Title (bin00026 (200110)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4dd6c7ab9ef77f2b4950d8fc7cd42ee1", "Retroactive", "", "Qb (V2.04) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4df6124093ccb4f0b6c26a719f4b7706", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) [a]", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, - { "4df9d7352a56a458abb7961bf10aba4e", "", "", "Racing Car (Unknown)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e01d9072c500331e65bb87c24020d3f", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (06-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e02880beeb8dbd4da724a3f33f0971f", "Imagic, Michael Greene", "EIZ-002-04I", "Wing War (1983) (Imagic) (PAL)", "AKA Flap!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e15ddfd48bca4f0bf999240c47b49f5", "Avalon Hill, Jean Baer, Jim Jacob", "5001002", "Death Trap (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4e2c884d04b57b43f23a5a2f4e9d9750", "", "", "Baby Center Animation (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4e37992a37ea36489283f7eb90913bbc", "Kris", "", "Hangman Ghost Halloween (Kris) (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e4895c3381aa4220f8c2795d6338237", "", "", "Backwards Cannonball v1 (Hack)", "Hack of Human Cannonball", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e66c8e7c670532569c70d205f615dad", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e86866d9cde738d1630e2e35d7288ce", "Supergame", "", "River Raid III (Supergame)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4e99ebd65a967cabf350db54405d577c", "Coleco", "2663", "Time Pilot (1983) (Coleco) [b1]", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4eb4fd544805babafc375dcdb8c2a597", "Inspirational Video Concepts, Steve Shustack", "321430", "Red Sea Crossing (1983) (Inspirational Video Concepts)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4edb251f5f287c22efc64b3a2d095504", "Atari", "", "Atari VCS Point-of-Purchase ROM (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f0071946e80ca68edfdccbac86dcce0", "", "", "Virtual Pet Demo 1 (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f2d47792a06da224ba996c489a87939", "HES - Activision", "223", "Super Action Pak - Pitfall, Barnstorming, Grand Prix, Laser Blast (1988) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f32b24869d8c1310fecf039c6424db6", "U.S. Games Corporation - JWDA, Todd Marshall", "", "3-D Zapper (12-15-82) (U.S. Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4f618c2429138e0280969193ed6c107e", "Activision, Alan Miller", "AZ-028, AG-028-04", "Robot Tank (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f634893d54e9cabe106e0ec0b7bdcdf", "Retroactive", "", "Qb (2.14) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4f64d6d0694d9b7a1ed7b0cb0b83e759", "20th Century Fox Video Games, John Russell", "11016", "Revenge of the Beefsteak Tomatoes (1983) (20th Century Fox)", "AKA Revenge of the Cherry Tomatoes", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f6702c3ba6e0ee2e2868d054b00c064", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen - Ariola", "EAZ-033 - 711 033-725", "Space Shuttle (1983) (Activision) (PAL)", "A Journey Into Space, Eine Reise ins All", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f781f0476493c50dc578336f1132a67", "", "", "Indy 500 (Unknown) (PAL) (4K)", "Uses Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "4f7b07ec2bef5ccffe06403a142f80db", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4f82d8d78099dd71e8e169646e799d05", "", "", "Miniature Golf (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4f89b897444e7c3b36aed469b8836839", "Atari", "CX26190", "BMX Air Master (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4fae08027365d31c558e400b687adf21", "", "", "Qb (V2.17) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "4faeb04b1b7fb0fa25db05753182a898", "", "", "2600 Digital Clock (V x.xx) (PD) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4fbe0f10a6327a76f83f83958c3cbeff", "CCE", "C-816", "Keystone Kappers (1983) (CCE)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "4fc1b85b8074b4b9436d097900e34f29", "John K. Harvey", "", "John K. Harvey's Equalizer (John K. Harvey)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "50200f697aeef38a3ce31c4f49739551", "Mystique - American Multiple Industries, Joel H. Martin", "", "Custer's Revenge (1982) (Mystique) (PAL60)", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "502044b1ac111b394e6fbb0d821fca41", "", "", "Hangman Invader 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "502168660bfd9c1d2649d415dc89c69d", "Activision, Bob Whitehead - Ariola", "EAG-019, EAG-019-04I - 711 019-715", "Sky Jinks (1982) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "504688d49a41bf03d8a955512609f3f2", "Thomas Jentzsch", "", "SWOOPS! (v0.94) (TJ)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "50568c80ac61cab789d9923c9b05b68e", "Ebivision", "", "Merlin's Walls - Standard Edition (1999) (Ebivision)", "Image rotated 90 degrees CW", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5069fecbe4706371f17737b0357cfa68", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Shark Attack (1982) (Apollo) (PAL)", "AKA Lochjaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5079bfbc7b8f5770f84215ed2e3bdd1b", "Omegamatrix (2012)", "", "Genesis Button Tester", "", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "GENESIS", "", "", "", "", "", "", "", "", "", "" }, - { "50a410a5ded0fc9aa6576be45a04f215", "Activision, Bob Whitehead - Ariola", "EAG-019, EAG-019-04I - 711 019-715", "Sky Jinks (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "50c7edc9f9dc0369abcdab3b4efeb5e9", "U.S. Games Corporation - JWDA, Todd Marshall", "", "3-D Zapper (U.S. Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "50ef88f9a5e0e1e6b86e175362a27fdb", "", "", "Multi-Sprite Game V2.4 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "512e874a240731d7378586a05f28aec6", "Tigervision, Rorke Weigandt - Teldec", "7-005", "Marauder (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5131ab3797fe8c127e3e135b18b4d2c8", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "514f911ecff2be5eeff2f39c49a9725c", "Parker Brothers", "931510", "Sky Skipper (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "515046e3061b7b18aa3a551c3ae12673", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "516ffd008057a1d78d007c851e6eff37", "Parker Brothers, Dawn Stockbridge", "PB5910", "Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "517592e6e0c71731019c0cebc2ce044f", "Parker Brothers - JWDA, Todd Marshall", "PB5550", "Q-bert's Qubes (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "517923e655755086a3b72c0b17b430e6", "Tron", "", "Super Tennis (Tron)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5188fee071d3c5ef0d66fb45c123e4a5", "Gameworld", "133-001", "Encounter at L-5 (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, - { "519f007c0e14fb90208dbb5199dfb604", "Amiga - Video Soft", "", "Depth Charge (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "51c1ddc9d6d597f71fb7efb56012abec", "Bit Corporation", "R320", "Lock 'n' Chase (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "51de328e79d919d7234cf19c1cd77fbc", "Atari, Mark R. Hahn", "CX2678", "Dukes of Hazzard (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "51e390424f20e468d2b480030ce95d7b", "Video Game Program", "", "Fire Bird (Video Game Program) (PAL)", "AKA Phoenix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "51f15b39d9f502c2361b6ba6a73464d4", "", "", "Amanda Invaders (PD) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "51f211c8fc879391fee26edfa7d3f11c", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "521f4dd1eb84a09b2b19959a41839aad", "Bit Corporation", "PG206", "Bobby Is Going Home (1983) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "522b27a8afeb951b5a5a667f8d1a46a1", "Omegamatrix", "", "Millipede (Amiga Mouse) v6.5 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "522c9cf684ecd72db2f85053e6f6f720", "Rainbow Vision - Suntek", "SS-008", "Year 1999, The (1983) (Rainbow Vision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52385334ac9e9b713e13ffa4cc5cb940", "CCE", "C-804", "Open, Sesame! (1983) (CCE)", "AKA Abre-te, Sesamo!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "523f5cbb992f121e2d100f0f9965e33f", "Joe Grand", "", "SCSIcide (1.30) (CGE 2001 Release) (Joe Grand)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "524693b337f7ecc9e8b9126e04a232af", "", "", "Euchre (19-08-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5256f68d1491986aae5cfdff539bfeb5", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-26-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "525ea747d746f3e80e3027720e1fa7ac", "Activision, Garry Kitchen - Ariola", "EAZ-032 - 771 032-712", "Pressure Cooker (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "525f2dfc8b21b0186cff2568e0509bfc", "Activision, David Crane", "AG-930-04, AZ-030", "Decathlon (1983) (Activision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52615ae358a68de6e76467e95eb404c7", "", "", "DJdsl-wopd (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "528400fad9a77fd5ad7fc5fdc2b7d69d", "Starpath Corporation, Stephen H. Landrum, Jon Leupp", "11 AR-4201", "Sword of Saros (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52a0003efb3b1c49fcde4dbc2c685d8f", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari) (4K) [a]", "", "", "", "", "2K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52b448757081fd9fabf859f4e2f91f6b", "", "", "Worm War I (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52bae1726d2d7a531c9ca81e25377fc3", "", "", "Space Instigators (V1.8 Fixed) (20-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "52e1954dc01454c03a336b30c390fb8d", "Retroactive", "", "Qb (2.14) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "52e9db3fe8b5d336843acac234aaea79", "", "", "Fu Kung! (V0.11) (28-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5305f69fbf772fac4760cdcf87f1ab1f", "Jone Yuan Telephonic Enterprise Co", "", "Ski Run (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5324cf5b6dc17af4c64bf8696c39c2c1", "Imagic, Dennis Koble", "IA3203, IX-010-04", "Atlantis (1982) (Imagic) (8K)", "AKA Lost City of Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "533661e9bccd8a9f80ce3765f282c92f", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) (Y Inverted) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5336f86f6b982cc925532f2e80aa1e17", "Parker Brothers - JWDA, Todd Marshall, Robin McDaniel, Ray Miller", "PB5060", "Star Wars - Death Star Battle (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "534e23210dd1993c828d944c6ac4d9fb", "M Network, Stephen Tatsumi, Jane Terjung - Kool Aid", "MT4648", "Kool-Aid Man (1983) (M Network)", "AKA Kool Aid Pitcher Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5355f80cacf0e63a49cbf4ade4e27034", "Christian Samuel", "", "Cute Dead Things House (Christian Samuel) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5360693f1eb90856176bd1c0a7b17432", "", "", "Oystron (V2.85) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "536bf56baa70acb17113884ac41f2820", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (PAL) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "537ed1e0d80e6c9f752b33ea7acbe079", "", "", "A-VCS-tec Challenge (beta 5) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5385cf2a04de1d36ab55c73174b84db0", "Paul Slocum", "", "Combat Rock (PD) (Hack)", "Hack of Combat", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "539d26b6e9df0da8e7465f0f5ad863b7", "Atari, Carol Shaw - Sears", "CX2636 - 49-75156", "Video Checkers (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "539f3c42c4e15f450ed93cb96ce93af5", "Dion Olsthoorn", "v1.3", "Amoeba Jump (2018) (Dionoid)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "53b66f11f67c3b53b2995e0e02017bd7", "CCE", "C-1005", "Super Tennis (1983) (CCE)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "53bd1c7c972ae634c912331a9276c6e3", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "53d181cde2e0219b5754caad246fcb66", "", "", "Missile Demo (1998) (Ruffin Bailey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "53e03df47e76329b701641f8bdc206f5", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "53f147b9746fdc997c62f3dd67888ee5", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "540075f657d4b244a1f74da1b9e4bf92", "Bit Corporation", "PGP230", "Festival (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5409d20c1aea0b89c56993aec5dc5740", "", "", "Carnival Shooter (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5428cdfada281c569c74c7308c7f2c26", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "542c6dd5f7280179b51917a4cba4faff", "ZiMAG - Emag - Vidco", "GN-080", "Spinning Fireball (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5438e84b90e50a5362f01cc843b358d4", "Arcadia Corporation, Scott Nelson", "3 AR-4300", "Fireball (1982) (Arcadia) (Prototype)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "543b4b8ff1d616fa250c648be428a75c", "Warren Robinett", "", "Adventure (1978) (Warren Robinett) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "545048ccb045f9efc6cf2b125cd0dfa8", "Arcadia Corporation, Stephen Harland Landrum, Jon Leupp", "AR-4201", "Sword of Saros (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "54785fa29e28aae6038929ba29d33d38", "", "", "Poker Squares (V0.19) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "54836a8f23913e9a77c7f2665baf36ac", "Bit Corporation", "PG204", "Open, Sesame! (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5494b9ee403d9757f0fd1f749e80214a", "Larry Petit", "", "Xenophobe Arcade (2003) (Larry Petit) (Hack)", "Hack of Xenophobe", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "54a1c1255ed45eb8f71414dadb1cf669", "Spectravideo", "SA-212", "Mangia' (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "54bafc299423f5a50b8bc3a797914706", "SOLID Corp. (D. Scott Williamson)", "CX2655*", "Star Castle 2600 (SolidCorp) (PAL)", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "54da3b0b3f43f5b37911c135b9432b49", "", "", "Halloween III Revision (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "54f7efa6428f14b9f610ad0ca757e26c", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Shark Attack (1982) (Apollo)", "AKA Lochjaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "551a64a945d7d6ece81e9c1047acedbc", "Matthias Jaap", "", "Coffee Cup Soccer (Matthias Jaap) (Hack)", "Hack of Pele's Soccer", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5524718a19107a04ec3265c93136a7b5", "Thomas Jentzsch", "", "RealSports Basketball (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "553dbf9358cfd2195e2fa0e08b01fb6a", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (07-05-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "554fd5775ca6d544818c96825032cf0d", "Atari - Roklan, Bob Curtiss", "", "Firefox (06-01-83) (Atari) (Prototype)", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "557e893616648c37a27aab5a47acbf10", "Atari - Axlon, Tod Frye - Heuristica, Augustin Ortiz", "CX26169", "Shooting Arcade (01-16-1990) (Atari) (Prototype) (PAL)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "559317712f989f097ea464517f1a8318", "Panda", "100", "Space Canyon (1983) (Panda)", "AKA Space Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "55949cb7884f9db0f8dfcf8707c7e5cb", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "55ace3c775f42eb46f08bb1dca9114e7", "", "", "Shadow Keep (04-03-2003) (Andrew Towers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "55ef6ab2321ca0c3d369e63d59c059c8", "", "", "Pitfall! (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "55ef7b65066428367844342ed59f956c", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "56210a3b9ea6d5dd8f417a357ed8ca92", "Probe 2000 - NAP, Roger Booth, Todd Marshall, Robin McDaniel, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype) [bad dump]", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "56300ed31fef018bd96768ccc982f7b4", "HES - Activision", "559", "Rad Action Pak - Kung-Fu Master, Freeway, Frostbite (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5641c0ff707630d2dd829b26a9f2e98f", "Joystik", "", "Motocross (Joystik)", "AKA Motocross Racer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5643ee916f7dc760148fca4db3aa7d10", "", "", "Moon Patrol (Genesis)", "Genesis controller (C is jump)", "Hack of Moon Patrol", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5678ebaa09ca3b699516dba4671643ed", "Coleco, Sylvia Day, Henry Will IV", "2459", "Mouse Trap (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "568371fbae6f5e5b936af80031cd8888", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "56f72247eb9ebfd33bfd0cca23ab7ef4", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) v4 (PAL60) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "571c6d9bc71cb97617422851f787f8fe", "Activision, David Crane - Ariola", "EAG-004, PAG-004 - 711 004-715", "Fishing Derby (1980) (Activision) (PAL)", "AKA Schneller als der Hai", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "572d0a4633d6a9407d3ba83083536e0f", "Funvision - Fund. International Co.", "", "Busy Police (Funvision)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "575c0fb61e66a31d982c95c9dea6865c", "", "", "Blackjack (Unknown) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "57939b326df86b74ca6404f64f89fce9", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "579baa6a4aa44f035d245908ea7a044d", "Jess Ragan", "", "Galaxian Enhanced Graphics (Jess Ragan) (Hack)", "Hack of Galaxian", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "57a66b6db7efc5df17b0b0f2f2c2f078", "Retroactive", "", "Qb (V2.08) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "57c5b351d4de021785cf8ed8191a195c", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari)", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "5835a78a88f97acea38c964980b7dbc6", "", "", "Cosmic Creeps (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5846b1d34c296bf7afc2fa05bbc16e98", "Atari - Sears", "CX2643 - 6-99815", "Codebreaker (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "58513bae774360b96866a07ca0e8fd8e", "Mystique - American Multiple Industries, Joel H. Martin", "1001", "Custer's Revenge (1982) (Mystique)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "585600522b1f22f617652c962e358a5d", "", "", "Multi-Sprite Game V2.2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "585f73010e205ae5b04ee5c1a67e632d", "", "", "Daredevil (V3) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5864cab0bc21a60be3853b6bcd50c59f", "", "", "Commando Raid (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "58746219d8094edff869f0f5c2aeaad5", "Jone Yuan Telephonic Enterprise Co", "", "Bowling (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5894c9c0c1e7e29f3ab86c6d3f673361", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "AZ-033, AZ-033-04", "Space Shuttle (1983) (Activision)", "A Journey Into Space", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "589c73bbcd77db798cb92a992b4c06c3", "Xonox - K-Tel Software - Action Graphics, Michael Schwartz, David Thiel", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) (PAL60)", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "58a82e1da64a692fd727c25faef2ecc9", "CCE", "C-824", "Jaw Breaker (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "58c396323ea3e85671e34c98eb54e2a4", "Brian Watson", "", "Color Tweaker (B. Watson)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "58d331c23297ed98663d11b869636f16", "", "", "Fu Kung! (V0.09) (26-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "58e313e2b5613b2439b5f12bb41e3eef", "", "", "Cube Conquest (Demo Interlace) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "590ac71fa5f71d3eb29c41023b09ade9", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (01-05-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59135f13985b84c4f13cc9e55eec869a", "", "", "Multi-Sprite Game V2.0 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "594437a35603c3e857b5af75b9718b61", "HES - Activision", "", "Robot Tank (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "594dbc80b93fa5804e0f1368c037331d", "Telesys, Alex Leavens", "", "Bouncin' Baby Bunnies (1983) (Telesys) (Prototype)", "AKA Baby Boom Boom, Bouncing Baby Monkeys", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5961d259115e99c30b64fe7058256bcf", "Universal Gamex Corporation, Miguel Castillo, H.K. Poon", "GX-001", "X-Man (1983) (Universal)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59734e1cc41822373845a09c51e6ba21", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "598a4e6e12f8238b7e7555f5a7777b46", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "599cbf919d47a05af975ad447df29497", "Jake Patterson", "", "Baubles (V0.002) (2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59b70658f9dd0e2075770b07be1a35cf", "Thomas Jentzsch", "", "Surfer's Paradise (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59d33e00c07665395209c1e55da0b139", "", "", "Imagic Selector ROM (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59e53894b3899ee164c91cfa7842da66", "Data Age", "", "Survival Run (1983) (Data Age) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "59e96de9628e8373d1c685f5e57dcf10", "PlayAround - J.H.M.", "204", "Beat 'Em & Eat 'Em (1982) (PlayAround)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "59f596285d174233c84597dee6f34f1f", "CCE", "C-811", "River Raid (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a0ff99ba10bd26d542e1d6f59f56850", "Champ Games", "CG-04-P", "Super Cobra Arcade (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "5a17e30e6e911e74ccd7b716d02b16c6", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a272012a62becabcd52920348c7c60b", "Star Game", "", "Pitfall (Star Game)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a2f2dcd775207536d9299e768bcd2df", "Otto Versand", "781698", "Flippern (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Video Pinball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a4205aeedd3b0588f973f38bbd9dfd4", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a5390f91437af9951a5f8455b61cd43", "Retroactive", "", "Qb (0.11) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5a6febb9554483d8c71c86a84a0aa74e", "CCE", "C-1003", "Donkey Kong Jr (1983) (CCE)", "AKA Donkey Kong Junior", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a734779d797ccef25dc8acfa47244c7", "", "", "Oh No! (Version 2) (18-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a80b857eb8b908ab477ec4ef902edc8", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a81ad4e184050851e63c8e16e3dac77", "Jone Yuan Telephonic Enterprise Co", "Hack", "Sky Diver (Jone Yuan) (Hack)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a8afe5422abbfb0a342fb15afd7415f", "Atari - Bobco, Robert C. Polaro", "CX26155", "Sprint Master (1988) (Atari)", "AKA Sprint 88, Sprint 2000", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a93265095146458df2baf2162014889", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a9685c4d51a6c1d6a9544946d9e8dc3", "AtariAge", "", "Grandma's Revenge (AtariAge)", "Can use driving controller in right port", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5a9d188245aff829efde816fcade0b16", "CCE", "C-808", "Phantom Tank (1983) (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5acf9865a72c0ce944979f76ff9610f0", "", "", "Dodge Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5ae73916fa1da8d38ceff674fa25a78a", "CCE", "", "Barnstorming (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5aea9974b975a6a844e6df10d2b861c4", "Atari, Dan Hitchens. Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari)", "AKA Adventure I, SwordQuest I - EarthWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5af9cd346266a1f2515e1fbc86f5186a", "SEGA", "002-01", "Sub-Scan (1983) (SEGA)", "AKA Subterfuge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b124850de9eea66781a50b2e9837000", "PlayAround - J.H.M.", "205", "Bachelor Party (1982) (PlayAround)", "Uses the paddle controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "5b574faa56836da0866ba32ae32547f2", "", "", "Tomb Raider 2600 [REV 03] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b5d04887922b430de0b7b2a21f9cd25", "", "", "Omega Race (Genesis)", "Genesis controller (B is thrust, C is fire)", "Hack of Omega Race", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b6f5bcbbde42fc77d0bdb3146693565", "", "", "Seaquest (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b7ea6aa6b35dc947c65ce665fde624b", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (2 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b85e987e2b1618769d97ba9182333d0", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (05-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b92a93b23523ff16e2789b820e2a4c5", "Activision - Imagineering, Dan Kitchen, Garry Kitchen", "AG-039-04", "Kung-Fu Master (1987) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b98e0536c3f60547dd708ae22adb04b", "Ben Hudman", "", "Donkey Kong Gingerbread Man (Ben Hudman) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5b9c2e0012fbfd29efd3306359bbfc4a", "HES", "", "2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5babe0cad3ec99d76b0aa1d36a695d2f", "Coleco - Individeo, Ed Temple", "2654", "Looping (1983) (Coleco) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5bba254e18257e578c245ed96f6b003b", "", "", "Music Effects Demo (21-01-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5bbab3f3e4b47e3e23f9820765dbb45c", "", "", "Pitfall! (says 1985) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5bbb75b49b2bccef9c91ff84bb249c80", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5bc9998b7e9a970e31d2cb60e8696cc4", "Jack Kortkamp", "", "Borgwars Asteroids (2003) (Jack Kortkamp) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5bcc83677d68f7ef74c1b4a0697ba2a8", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision) (16K)", "", "", "", "", "4K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5bd79139a0c03b63f6f2cf00a7d385d2", "Marc de Smet", "", "An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5be03a1fe7b2c114725150be04b38704", "Atari, Alan Miller", "CX2642", "Hunt & Score (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c0227ad63300670a647fcebf595ea37", "Josh", "", "Battle for Naboo (Josh) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c0520c00163915a4336e481ca4e7ef4", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL) [a1]", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c19f6da638c4c7c1f98d09e63df43e4", "Canal 3 - Intellivision", "", "Cosmic Ark (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c1b1aa78b7609d43c5144c3b3b60adf", "", "", "Demo Image Series #8 - Two Marios (Different Interlacing) (27-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c3a6d27c026f59a96b7af91e8b1bf26", "PlayAround - J.H.M.", "", "PlayAround Demo (PlayAround) (1982)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c618a50dfa23daac97ba459b9ff5206", "Steve Engelhardt", "", "Berzerk Renegade (2002) (Steve Engelhardt) (Hack)", "Hack of Room of Doom", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5c73693a89b06e5a09f1721a13176f95", "", "", "Wavy Line Test 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5c86e938e0845b9d61f458539e9a552b", "Atari, Alan Miller", "CX26163P", "Surround (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5cbd7c31443fb9c308e9f0b54d94a395", "Spectravideo, Mark Turmell", "SA-217", "Gas Hog (1983) (Spectravideo) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5ce98f22ade915108860424d8dde0d35", "", "", "Hangman Man Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5ced13931c21ef4fc77d3fe801a1cbfa", "CCE", "C-828", "Missile Command (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d0e8a25cbd23e76f843c75a86b7e15b", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-07-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d132d121aabc5235dd039dfc46aa024", "", "", "Basketball (208 in 1) (Unknown) (PAL) (Hack)", "Console ports are swapped", "Hack", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d25df9dc2cde746ceac48e834cf84a7", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "EAZ-033", "Space Shuttle (1983) (Activision) (SECAM)", "A Journey Into Space", "", "", "", "FE", "", "", "", "", "", "", "", "", "SECAM", "", "", "", "", "", "", "" }, - { "5d2cc33ca798783dee435eb29debf6d6", "Activision - Imagineering, Mike Reidel", "AK-043-04", "Commando (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d7293f1892b66c014e8d222e06f6165", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a1]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d799bfa9e1e7b6224877162accada0d", "Spectravision - Spectravideo - Sirius Software, David Lubar", "SA-206", "Challenge of.... Nexar, The (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d8f1ab95362acdf3426d572a6301bf2", "Thomas Jentzsch", "", "SWOOPS! (v0.96) (TJ) (PAL)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d8fb14860c2f198472b233874f6b0c9", "", "", "Boing! (PD) [a2]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5d9592756425192ec621d2613d0e683d", "CCE", "C-839", "Misterious Thief, A (1983) (CCE) [a]", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5da8fd0b5ed33a360bff37f8b5d0cd58", "Tron", "", "Pole Position (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5dae540347cf0a559962d62604ecf750", "Canal 3 - Intellivision", "", "Freeway (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5db9e5bf663cad6bf159bc395f6ead53", "Goliath - Hot Shot", "83-212", "Time Race (1983) (Goliath) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5dccf215fdb9bbf5d4a6d0139e5e8bcb", "Froggo", "FG1009", "Sea Hunt (1987) (Froggo)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5de8803a59c36725888346fdc6e7429d", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5df32450b9fbcaf43f9d83bd66bd5a81", "Eric Ball", "", "Atari Logo Playfield Demo (2001) (Eric Ball) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5df559a36347d8572f9a6e8075a31322", "Digivision", "", "Enduro (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e0c37f534ab5ccc4661768e2ddf0162", "Telegames - VSS, Ed Salvo", "5667 A106", "Glacier Patrol (1988) (Telegames)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e1b4629426f4992cf3b2905a696e1a7", "Activision - Bobco, Robert C. Polaro", "AK-049-04", "Rampage! (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e1b7a6078af428ef056fe85a37a95ca", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e1cd11a6d41fc15cf4792257400a31e", "Philip R. Frey", "", "Return of Mario Bros (Philip R. Frey) (Hack)", "Hack of Mario Bros.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e201d6bfc520424a28f129ee5e56835", "Universal Gamex Corporation, Miguel Castillo, H.K. Poon", "GX-001", "X-Man (1983) (Universal) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e2495d43b981010304af55efed1e798", "Jone Yuan Telephonic Enterprise Co", "", "Math Gran Prix (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5e43c0391f7412ae64fae6f3742d6ee9", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.27)", "", "New Release, supports BoosterGrip", "", "", "", "", "", "", "", "BOOSTERGRIP", "DRIVING", "", "", "", "", "", "", "", "", "", "" }, - { "5e99aa93d0acc741dcda8752c4e813ce", "", "", "2600 Digital Clock (V b2) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5ec73ac7d2ac95ac9530c6d33e713d14", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (2 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5eeb81292992e057b290a5cd196f155d", "Wizard Video Games - VSS, Ed Salvo", "008", "Texas Chainsaw Massacre, The (1983) (Wizard Video)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5ef303b9f0aa8cf20720c560e5f9baa1", "Atari, Jim Huether", "CX2629, CX2629P", "Sky Diver (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f1b7d5fa73aa071ba0a3c2819511505", "CCE", "", "Cosmic Commuter (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f2b4c155949f01c06507fb32369d42a", "Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f316973ffd107f7ab9117e93f50e4bd", "", "", "Commando Raid (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f39353f7c6925779b0169a87ff86f1e", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (1983) (Atari) [a]", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f46d1ff6d7cdeb4b09c39d04dfd50a1", "Atari, Gary Palmer", "CX2661P", "Fun with Numbers (1980) (Atari) (PAL)", "AKA Basic Math", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f4ebf8a1e5f5f7b9ff3e3c6affff3e6", "Bit Corporation", "R320", "Donkey Kong (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f560837396387455c9dcb05cdd4b053", "Canal 3 - Intellivision", "", "Eggomania (Canal 3)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "5f681403b1051a0822344f467b05a94d", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5f708ca39627697e859d1c53f8d8d7d2", "Atari, Warren Robinett - Sears", "CX2606 - 6-99825, 49-75112", "Slot Racers (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f73e7175474c1c22fb8030c3158e9b3", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f786b67e05fb9985b77d4beb35e06ee", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Defender II (1987) (Atari) (PAL)", "AKA Stargate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f7ae9a7f8d79a3b37e8fc841f65643a", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f7de62a408b9de3a1168898298fd31d", "", "", "Super Cobra (Genesis)", "Genesis controller (B is bomb, C is laser)", "Hack of Super Cobra", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5f950a2d1eb331a1276819520705df94", "20th Century Fox Video Games - Micro Computer Technologies, Jim Collas", "", "Heart Like a Wheel (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "5f9b62350b31be8bd270d9a241cbd50e", "Telegames", "5658 A088", "Football (1988) (Telegames) (PAL)", "AKA Super Challenge Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5faffe1c4c57430978dec5ced32b9f4a", "Dactari - Milmar", "", "Volleyball (Dactari - Milmar)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "5fb71cc60e293fe10a5023f11c734e55", "", "", "This Planet Sucks (Fix) (27-12-2002) (Greg Troutman)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "600d48eef5c0ec27db554b7328b3251c", "", "", "Bars and Text Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6015a9cef783e97e98a2aa2cf070ae06", "Thomas Jentzsch", "", "Battlezone TC (Thomas Jentzsch) (Hack)", "Uses two simultaneous Joystick Controllers, Hack of Battlezone", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "60358edf0c2cc76b1e549e031e50e130", "Manuel Polik", "", "Cyber Goth Galaxian (Manuel Polik) (Hack)", "Hack of Galaxian", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "603c7a0d12c935df5810f400f3971b67", "Bit Corporation", "PG209", "Mr. Postman (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6041f400b45511aa3a69fab4b8fc8f41", "Apollo, Ban Tran", "AP-2010", "Wabbit (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "604e09724555807c28108049efe34a13", "", "", "Sokoban (01-01-2003) (Adam Wozniak)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6058e40ce79d7434c7f7477b29abd4a5", "", "", "Rubik's Cube Demo (23-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "605dcb73d22f4efdb90ef9da2f290f7c", "Atari, Larry Kaplan", "CX26163P", "Air-Sea Battle (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "605fd59bfef88901c8c4794193a4cbad", "Data Age", "", "Secret Agent (1983) (Data Age) (Prototype)", "Uses the Paddle Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "606c2c1753051e03c1f1ac096c9d2832", "Jone Yuan Telephonic Enterprise Co", "", "Crackpots (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6076b187a5d8ea7a2a05111c19b5d5cd", "", "", "Fu Kung! (V0.14) (01-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "60a61da9b2f43dd7e13a5093ec41a53d", "VentureVision, Dan Oliver", "VV2001", "Rescue Terra I (1982) (VentureVision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "60bbd425cb7214ddb9f9a31948e91ecb", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "60cd61a2dfccb0e2736434f9792c1672", "Amiga - Video Soft, Frank Ellis, Jerry Lawson", "2110", "3-D Havoc (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "60d304582d33e2957b73eb300a7495bb", "", "", "Jam Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "60e0ea3cbe0913d39803477945e9e5ec", "Atari, Joe Decuir - Sears", "CX2621 - 99806, 6-99806, 49-75104", "Video Olympics (1977) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "PADDLES_IAXDR", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "613abf596c304ef6dbd8f3351920c37a", "", "", "Boring Pac-Man (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6141c095d0aee4e734bebfaac939030a", "Rainbow Vision - Suntek", "SS-017", "Mariana (1983) (Rainbow Vision) (PAL)", "AKA Seaquest", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61426cee013306e7f7367534ab124747", "", "", "One Blue Bar Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "615a3bf251a38eb6638cdc7ffbde5480", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61621a556ad3228f0234f5feb3ab135c", "", "", "Fu Kung! (V0.05 Cuttle Card Compattle Revision) (14-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61631c2f96221527e7da9802b4704f93", "Activision - Imagineering, Mike Reidel", "AK-043-04", "Commando (1988) (Activision) [different logo]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61719a8bdafbd8dab3ca9ce7b171b9e2", "", "", "Enduro (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61728c6cfb052e62a9ed088c5bf407ba", "", "", "Sprite Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "619de46281eb2e0adbb98255732483b4", "", "", "Time Warp (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61dbe94f110f30ca4ec524ae5ce2d026", "CCE", "C-820", "Space Invaders (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61e0f5e1cc207e98704d0758c68df317", "Star Game", "007", "Tennis (Star Game)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "61ef8c2fc43be9a04fe13fdb79ff2bd9", "", "", "Gas Gauge Demo - Revisited (2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6205855cc848d1f6c4551391b9bfa279", "", "", "Euchre (Release Candidate 2) (NTSC) (01-10-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6238ac888871fec301d1b9fc4fc613c9", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (PAL) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "624e0a77f9ec67d628211aaf24d8aea6", "Panda", "108", "Sea Hawk (1983) (Panda)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "626d67918f4b5e3f961e4b2af2f41f1d", "Atari", "50008", "Diagnostic Test Cartridge 2.0 (1980) (Atari) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6272f348a9a7f2d500a4006aa93e0d08", "Atari, Jerome Domurat, Michael Sierchio", "CX2667, CX2667P", "RealSports Soccer (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "62899430338e0538ee93397867d85957", "Gameworld", "133-004", "Airlock (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "62921652f6634eb1a0940ed5489c7e18", "", "", "SCSIcide (V1.09) (2001) (Joe Grand)", "", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "62992392ea651a16aa724a92e4596ed6", "Eric Mooney", "", "Invaders by Erik Mooney (Beta) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "62d1f50219edf9a429a9f004c19f31b3", "JWDA, Todd Marshall", "", "Euro Gen (02-01-83) (JWDA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "62ee2b8f59e9cd6285bbdb674a952e8b", "Probe 2000 - NAP, Roger Booth, Todd Marshall, Robin McDaniel, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype)", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "62f74a2736841191135514422b20382d", "", "", "Pharaoh's Curse (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "62ffd175cac3f781ef6e4870136a2520", "", "", "2600 Digital Clock (V x.xx) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63166867f75869a3592b7a94ea62d147", "", "", "Indy 500 (Hack) [a1]", "Hack of Indy 500", "Hack", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "", "", "", "", "", "", "" }, - { "6333ef5b5cbb77acd47f558c8b7a95d3", "Greg Troutman", "", "Dark Mage (Greg Troutman) (PD) (8K)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6337927ad909aa739d6d0044699a916d", "Jeffry Johnston", "", "Radial Pong - Version 2 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6339d28c9a7f92054e70029eb0375837", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6342afe9c9ad1b6120b8f6fb040d0926", "", "", "Move a Blue Blob Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6354f9c7588a27109c66905b0405825b", "Thomas Jentzsch", "", "Amidar DS (2003) (TJ) (Hack)", "Hack of Amidar", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6358f7f8bf0483402a080efccf250d61", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid) (Prototype)", "AKA Termite", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "635cc7a0db33773959d739d04eff96c2", "", "", "Minesweeper (V.90) (Soren Gust) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6362396c8344eec3e86731a700b13abf", "Panda", "109", "Exocet (1983) (Panda)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "637efac676ff063f2fbb0abff77c4fa5", "", "", "Noize Maker Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63811ed69bdbc35c69d8aa7806c3d6e9", "Atari", "CX26163P", "Homerun (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "638cc82ea96f67674595ba9ae05da6c6", "Rainbow Vision - Suntek", "SS-011", "Super Ferrari (1983) (Rainbow Vision) (PAL)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63a6eda1da30446569ac76211d0f861c", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63a7445b1d3046d3cdcdbd488dca38d9", "Rob Kudla", "", "Better Space Invaders (1999) (Rob Kudla) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63c5fef3208bb1424d26cf1ab984b40c", "", "", "Analog Clock (V0.1) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63c7395d412a3cd095ccdd9b5711f387", "Eric Ball", "ELB005", "Skeleton+ (PAL)", "Stereo sound", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63d6247f35902ba32aa49e7660b0ecaa", "", "", "Space War (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63e42d576800086488679490a833e097", "Telesys, Jim Rupp", "1004", "Ram It (1983) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63e783994df824caf289b69a084cbf3e", "David Marli", "", "Fat Albert (David Marli) (Hack)", "Hack of Fast Food", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "63e9e612bbee31045f8d184a4e53f8ec", "ATARITALIA", "", "Moby Blues (2002) (ATARITALIA) (Hack)", "Hack of Mario Bros", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "640a08e9ca019172d612df22a9190afb", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691, CX2691P", "Joust (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "64198bb6470c78ac24fcf13fe76ab28c", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "643e6451eb6b8ab793eb60ba9c02e000", "Salu - Avantgarde Software, Michael Buetepage", "460741", "Ghostbusters II (1992) (Salu) (PAL) [different tune]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "645bf7f9146f0e4811ff9c7898f5cd93", "Xonox - K-Tel Software - VSS, Robert Weatherby", "6230, 6250", "Super Kung-Fu (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6468d744be9984f2a39ca9285443a2b2", "Atari, Ed Logg, Carol Shaw", "CX26163P", "Reversi (32 in 1) (1988) (Atari) (PAL)", "AKA Othello", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "647162cceb550fd49820e2206d9ee7e8", "", "", "Skeleton (NTSC) (2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "64b8e19c767191ccdc97acc6904c397b", "Jeffry Johnston", "", "Radial Pong - Version 6 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "64ca518905311d2d9aeb56273f6caa04", "CCE", "", "Cubo Magico (CCE)", "AKA Cubicolor", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "64d43859258dc8ca54949e9ff4174202", "Thomas Jentzsch", "", "Lilly Adventure (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "64fab9d15df937915b1c392fc119b83b", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (05-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "650df778c6ce22d3fd1a7c33c565bcc3", "Atari - GCC, Betty Ryan Tylko, Douglas B. Macrae", "CX2694", "Pole Position (1983) (Atari)", "Genesis controller (B is high gear, C is low gear, left difficulty switch swaps gear buttons)", "Hack of Pole Position", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "651d2b6743a3a18b426bce2c881af212", "CCE", "C-812", "Pac Man (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6522717cfd75d1dba252cbde76992090", "Home Vision - Gem International Corp. - VDI", "VCS83102", "War 2000 (1983) (Home Vision) (PAL)", "AKA Astrowar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6538e454b0498ad2befe1ef0f87815c0", "Joe Grand", "", "SCSIcide (v1.2) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "65490d61922f3e3883ee1d583ce10855", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692, CX2692P", "Moon Patrol (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "65562f686b267b21b81c4dddc129d724", "", "", "Euchre (28-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "655c84e5b951258c9d20f0bf2b9d496d", "", "", "2600_2003 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "656dc247db2871766dffd978c71da80c", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (1981) (Sears)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "6588d192d9a8afce27b44271a2072325", "Bit Corporation", "R320", "Basketball (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "65917ae29a8c9785bb1f2acb0d6aafd0", "", "", "Junkosoft One Year Demo (1999) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6596b3737ae4b976e4aadb68d836c5c7", "Digivision", "", "Defender (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "659a20019de4a23c748ec2292ea5f221", "Retroactive", "", "Qb (V2.05) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "65b106eba3e45f3dab72ea907f39f8b4", "Christian Software Development - HomeComputer Software, Dan Schafer, Glenn Stohel, Jon Tedesco - Sparrow", "GCG 1001T", "Music Machine, The (1983) (Sparrow)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "65ba1a4c643d1ab44481bdddeb403827", "Quelle", "876.013 4", "Katastrophen-Einsatz (1983) (Quelle) (PAL)", "AKA M.A.S.H.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "65bd29e8ab1b847309775b0de6b2e4fe", "Coleco, Ed English", "2667", "Roc 'n Rope (1984) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "65c6406f5af934590097c8c032ebb482", "", "", "Three Hugger (Pave Demo) (20-12-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6604f72a966ca6b2df6a94ee4a68eb82", "", "", "MegaMania (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "662eca7e3d89175ba0802e8e3425dedb", "", "", "Hangman Pac-Man Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66362890eb78d6ea65301592cce65f5b", "", "", "Euchre (13-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "663ef22eb399504d5204c543b8a86bcd", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "4L1720, 4L1721, 4L1722, 4L2276", "Wizard of Wor (1982) (CBS Electronics) (PAL)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "664d9bfda6f32511f6b4aa0159fd87f5", "Atari - Roklan, Joe Gaucher", "", "Racer (1982) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6651e2791d38edc02c5a5fd7b47a1627", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (04-05-1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "665b8f8ead0eef220ed53886fbd61ec9", "Telesys, Don Ruffcorn, Jack Woodman", "1003", "Fast Food (1982) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66706459e62514d0c39c3797cbf73ff1", "Video Gems", "VG-05", "Treasure Below (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6672de8f82c4f7b8f7f1ef8b6b4f614d", "Videospielkassette - Ariola", "PGP237", "Angeln I (Ariola) (PAL)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "667a70b028f581d87648693b873bc962", "Parker Brothers - Roklan, Joe Gaucher", "PB5370", "Popeye (1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "668dc528b7ea9345140f4fcfbecf7066", "Gakken", "001", "Pooyan (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6697f177847c70505824422e76aad586", "", "", "Tennis (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "669840b0411bfbab5c05b786947d55d4", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66b89ba44e7ae0b51f9ef000ebba1eb7", "Atari - CCW, Stephan R. Keith, Laura Scholl, Preston Stuart", "CX26106", "Grover's Music Maker (01-18-1983) (Atari) (Prototype)", "Uses Keypad Controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66b92ede655b73b402ecd1f4d8cd9c50", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66bc1bef269ea59033928bac2d1d81e6", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (Preview) (1982) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "66c2380c71709efa7b166621e5bb4558", "Parker Brothers, Dave Engman, Dawn Stockbridge", "931509", "Tutankham (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66c4e0298d4120df333bc2f3e163657e", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (2 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66f49b3248791b9803fa3e2f4165d072", "Bit Corporation", "R320", "Football (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "66fcf7643d554f5e15d4d06bab59fe70", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6706a00f9635508cfeda20639156e66e", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "672012d40336b403edea4a98ce70c76d", "", "", "Spider Kong (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "675ae9c23fa1aae376cea86cad96f9a5", "", "", "Poker Squares (V0.25) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67631ea5cfe44066a1e76ddcb6bcb512", "", "", "Termool (Unknown) (PAL)", "AKA Turmoil", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67684a1d18c85ffa5d82dab48fd1cb51", "Tigervision, Warren Schwader - Teldec", "7-003", "Threshold (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "678c1d71a1616d9d022f03d8545b64bb", "", "", "Demo Image Series #11 - Donald And Mario (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67931b0d37dc99af250dd06f1c095e8d", "CommaVid, Irwin Gaines", "CM-004", "Room of Doom (1982) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "679d30c7886b283cbe1db4e7dbe5f2a6", "Colin Hughes", "", "Puzzle (Colin Hughes) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "679e910b27406c6a2072f9569ae35fc8", "Data Age", "DA1002", "Warplock (1982) (Data Age)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 40", "", "", "YES", "", "", "", "", "" }, - { "67bd3d4dc5ac6a42a99950b4245bdc81", "Retroactive", "", "Qb (2.11) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "67c05ae94bf8b83a666c3ae2c4bc14de", "Atari", "CX26163P", "NFL Football (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67cdde4176e0447fc45a71e0a1cdd288", "Telegames - VSS, Ed Salvo", "5665 A016", "Glacier Patrol (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67ce6cdf788d324935fd317d064ed842", "Retroactive", "", "Qb (V2.09) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "67cf913d1df0bf2d7ae668060d0b6694", "", "", "Hangman Monkey 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "67f90d74fd0b72fdc6d9b92436780ea9", "Omegamatrix", "", "SpaceMaster X-7 (Atari Trak-Ball) (PAL60) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "6803fa7c2c094b428b859a58dc1dd06a", "Retroactive", "", "Qb (0.11) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6805734a0b7bcc8925d9305b071bf147", "Bit Corporation", "PGP229", "Kung Fu (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Karate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "681206a6bde73e71c19743607e96c4bb", "", "", "Casino (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6833c26f385e866f3a0fa0dff311216e", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "683bb0d0f0c5df58557fba9dffc32c40", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia) [a]", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "683dc64ef7316c13ba04ee4398e2b93a", "Ed Federmeyer", "", "Edtris (1995) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68449e4aaba677abcd7cde4264e02168", "", "", "Horizonal Color Bars Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6847ce70819b74febcfd03e99610243b", "", "", "Ruby Runner 4A50", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "68489e60268a5e6e052bad9c62681635", "Bit Corporation", "PG201", "Sea Monster (1982) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68597264c8e57ada93be3a5be4565096", "Data Age", "DA1005", "Bugs (1982) (Data Age)", "Uses the Paddle Controllers", "Uncommon", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, - { "685e9668dc270b6deeb9cfbfd4d633c3", "CommaVid, Irwin Gaines - Ariola", "CM-004 - 712 004-720", "Room of Doom (1982) (CommaVid) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "68760b82fc5dcf3fedf84376a4944bf9", "CCE", "C-860", "Laser Gate (1983) (CCE)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "687c23224e26f81c56e431c24faea36d", "", "", "Qb (Simple Background Animation) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "68878250e106eb6c7754bc2519d780a0", "CCE", "C-809", "Squirrel (1983) (CCE)", "AKA Snail Against Squirrel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68ac69b8e1ba83af8792f693f5ae7783", "Digivision", "", "Fathon (Digivision)", "AKA Fathom", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68c80e7e1d30df98a0cf67ecbf39cc67", "Hozer Video Games", "", "Gunfight 2600 - One Step Forward & Two Steps Back (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68c938a2a2b45c37db50509f1037fe6e", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "68cd2adc6b1fc9a1f263ab4561112f30", "Thomas Jentzsch", "", "Boulderdash Demo (09-12-2002) (TJ)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "68feb6d6ff63e80df1302d8547979aec", "", "", "Starfield Demo 2 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "690a6049db78b9400c13521646708e9c", "King Tripod Enterprise Co.", "SS - 007", "Space Raid (King Tripod) (PAL)", "AKA Challenge of.... Nexar, The", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6913c90002636c1487538d4004f7cac2", "Atari - CCW", "CX26131", "Monster Cise (1984) (Atari) (Prototype)", "Uses the Keypad Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "691d67910b08b63de8631901d1887c1f", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "692202772d8b38ccf85a90c8003a1324", "", "", "Zi - The Flie Buster (2002) (Fernando Mora) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "693137592a7f5ccc9baae2d1041b7a85", "", "", "Qb (V2.02) (Stella) (2001) (Retroactive) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6936aa6763835f62ac13d1aaa79b9f91", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6979f30204149be3e227558cffe21c1d", "Atari", "CX26163P", "Miniaturer Golf (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Miniature Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6982854657a2cc87d712f718e402bf85", "Zellers", "", "Earth Attack (Zellers)", "AKA Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69877da5caded48315e3e45882a303d5", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "698f569eab5a9906eec3bc7c6b3e0980", "SpkLeader", "", "Demons! (2003) (SpkLeader) (Hack)", "Hack of Phoenix", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69974dd5d6420b90898cde50aec5ef39", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69df0411d4d176e558017f961f5c5849", "CCE", "C-831", "Cosmic Ark (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69e79b1352b9ee1754bbe63b4a7062c3", "Barry Laws Jr.", "", "Pink Floyd - The Wall (2003) (Barry Laws Jr.) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69ebf910ab9b63e5b8345f016095003b", "", "", "Maze Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69edfb4e1810a523311b3e250fc1e275", "Thomas Jentzsch", "", "Missile Command Atari Trak-Ball Hack v1.3 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "69fac82cd2312dd9ce5d90e22e2f070a", "Spectravision - Spectravideo - Quelle", "SA-202 - 412.851 8", "Planet Patrol (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a03c28d505bab710bf20b954e14d521", "", "", "Pressure Gauge 2 Beta (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a07836c382195dd5305ce61d992aaa6", "Apollo, Larry Martin", "AP-2008", "Guardian (1982) (Apollo) (Prototype)", "Uses the Paddle Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "6a091b8ffeacd0939850da2094b51564", "", "", "Vertically Scrolling Playfield (02-02-2003) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a222c26bcece3a510ddda21398f72c6", "Bit Corporation", "PG203", "Phantom Tank (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a2c68f7a77736ba02c0f21a6ba0985b", "Atari, Larry Wagner, Bob Whitehead", "", "Computer Chess (07-07-1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a3b0c33cf74b1e213a629e3c142b73c", "Cody Pittman", "", "Cory The Interviewer (Cody Pittman) (Hack)", "Hack of Ghostbusters", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a76d5f0ed721639474aa9bbde69ebf0", "", "", "Play Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6a82b8ecc663f371b19076d99f46c598", "Activision, Larry Miller - Ariola", "EAX-026, EAX-026-04B, EAX-026-04I - 711 026-725", "Enduro (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a882fb1413912d2ce5cf5fa62cf3875", "Video Game Cartridge - Ariola", "TP-605", "Dragon Defender (Ariola) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6a8c6940d3be6fd01274363c4d4b298e", "", "", "Spy Hunter (Genesis)", "Genesis controller (C is oil/smoke)", "Hack of Spy Hunter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a9b30ca46b0dba9e719f4cbd340e01c", "", "", "Frostbite (Unknown) (PAL) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6a9e0c72fab92df70084eccd9061fdbd", "CCE", "C-835", "Beany Bopper (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6aa66e9c3eea76a0c40ef05513497c40", "", "", "Hangman Ghost Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6ac3fd31a51730358708c7fdc62487f8", "Matthias Jaap", "", "PC Invaders (Matthias Jaap) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6aca52e11b597ab84b33d5252e1cd9d1", "Bit Corporation", "R320", "Tac-Scan (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "6ae4dc6d7351dacd1012749ca82f9a56", "Atari - GCC, Jaques Hugon, Seth Lipkin", "CX26125, CX26127", "Track and Field (1984) (Atari)", "Uses the Track & Field Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b01a519b413f8cfa2f399f4d2841b42", "", "", "Aphex Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b1fc959e28bd71aed7b89014574bdc2", "Bit Corporation", "PG203", "Phantom Tank (1982) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b4eb5b3df80995b8d9117cb7e9aeb3c", "Gameworld, J. Ray Dettling", "133-006", "Journey Escape (1983) (Gameworld) (PAL)", "AKA Rock 'n' Roll Escape", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6b683be69f92958abe0e2a9945157ad5", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Steven B. Sidley, Tom Sloper", "VC2007", "Entombed (1983) (U.S. Games)", "Released as Name That Game for a contest (winning name was Entombed)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6b6ca32228ae352b4267e4bd2cddf10c", "", "", "Pac-Man 4 (Pac-Man Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b71f20c857574b732e7a8e840bd3cb2", "", "", "Frostbite (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b72b691ea86f61438ed0d84c4d711de", "", "", "Fishing Derby (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b75f8fa4fd011a6698c58315f83d2ac", "Thomas Jentzsch", "", "Sprintmaster DC (TJ)", "Uses the Driving Controllers, Hack of Sprintmaster (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "6b7a56b6ac2ca4bf9254474bf6ed7d80", "", "", "Horizonal Color Bars Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b7e1c11448c4d3f28160d2de884ebc8", "Zirok", "", "Fast Food (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6b8fb021bb2e1f1e9bd7ee57f2a8e709", "Paul Slocum", "", "3-D Corridor (29-03-2003) (Paul Slocum) (PD) [a]", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6bb09bc915a7411fe160d0b2e4d66047", "Atari", "CX26163P", "UFO (32 in 1) (1988) (Atari) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6bb22efa892b89b69b9bf5ea547e62b8", "Dynacom", "", "Megamania (1982) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6bde3f6ac31aceef447ce57d4d2c2ec0", "Piero Cavina", "", "Mondo Pong V1 (Piero Cavina) (PD)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "01", "", "", "", "", "", "", "", "" }, - { "6c128bc950fcbdbcaf0d99935da70156", "Digitel", "", "Volleyball (1983) (Digitel)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c1553ca90b413bf762dfc65f2b881c7", "Quelle", "343.073 3", "Winterjagd (1983) (Quelle) (PAL)", "AKA Ski Hunt", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c1f3f2e359dbf55df462ccbcdd2f6bf", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c25f58fd184632ca76020f589bb3767", "Dynacom", "", "Beat 'Em & Eat 'Em (1983) (Dynacom)", "Uses the Paddle Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "6c449db9bbbd90972ad1932d6af87330", "", "", "20 Sprites at Once Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c658b52d03e01828b9d2d4718a998ac", "", "", "Hangman Invader Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c76fe09aa8b39ee52035e0da6d0808b", "Atari, Brad Stewart", "CX2622, CX2622P", "Breakout (1978) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, - { "6c85098518d3f94f7622c42fd1d819ac", "Suntek", "SS-028", "Firebug (1983) (Suntek) (PAL)", "AKA Spinning Fireball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c91ac51421cb9fc72c9833c4f440d65", "ITT Family Games", "554-33 375", "Cosmic Town (1983) (ITT Family Games) (PAL)", "AKA Base Attack (Perry Rhodan-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6c9a32ad83bcfde3774536e52be1cce7", "", "", "Space Treat (NTSC) (13-08-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6cab04277e7cd552a3e40b3c0e6e1e3d", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames) (Prototype)", "AKA Targ", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6cbe945e16d9f827d0d295546ac11b22", "", "", "Gunfight 2600 - AI (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6ccd8ca17a0e4429b446cdcb66327bf1", "", "", "RPG Engine (12-05-2003) (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6cd1dc960e3e8d5c5e0fbe67ab49087a", "", "", "Vertical Playfield Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6cd506509e8fd5627f55603780e862a8", "Greg Troutman", "", "Dark Mage (SuperCharger) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6ce2110ac5dd89ab398d9452891752ab", "Funvision - Fund. International Co.", "", "Persian Gulf War (Funvision)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6cea35ded079863a846159c3a1101cc7", "", "", "Atlantis (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6ceb7d6a54e9a5e62d26874d1cc88dbc", "Video Soft", "", "Atom Smasher (1984) (Video Soft) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6cf054cd23a02e09298d2c6f787eb21d", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6d218dafbf5a691045cdc1f67ceb6a8f", "Robin Harbron", "", "6 Digit Score Display (1998) (Robin Harbron) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6d475019ea30d0b29f695e9dcfd8f730", "Eric Mooney", "", "Invaders by Erik Mooney (Alpha 2) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6d74ebaba914a5cfc868de9dd1a5c434", "", "", "Fortress (Smooth Version) (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6d842c96d5a01967be9680080dd5be54", "Activision, Steve Cartwright, David Crane", "AB-035-04", "Pitfall II (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6d8a04ee15951480cb7c466e5951eee0", "Zirok", "", "Kanguru (1983) (Zirok)", "AKA Kangaroo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6d9afd70e9369c2a6bff96c4964413b7", "", "", "Time Warp (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6dda84fb8e442ecf34241ac0d1d91d69", "Atari - GCC, Douglas B. Macrae", "CX2677", "Dig Dug (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6de924c2297c8733524952448d54a33c", "CCE", "C-1006", "Moon Patrol (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6dfad2dd2c7c16ac0fa257b6ce0be2f0", "Parker Brothers, Larry Gelberg", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e179eee3d4631a7434d40cf7aeea6e8", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e19428387686a77d8c8d2f731cb09e0", "", "", "Purple Cross Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e372f076fb9586aff416144f5cfe1cb", "Atari, Tod Frye - Sears", "CX2646 - 49-75185", "Pac-Man (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e59dd52f88c00d5060eac56c1a0b0d3", "Atari, Bob Smith", "CX2648", "Video Pinball (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e5d5ba193d2540aec2e847aafb2a5fb", "Retroactive", "", "Qb (2.14) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6e7ed74082f39ad4166c823765a59909", "", "", "Poker Squares (V0.14) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6e7efb0ed13ec28a00d19572de9c9f03", "Apollo - Games by Apollo", "AP-2006", "Infiltrate (1982) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6eb10fd23c7161751d18b9e8484c0004", "Coleco - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "2465", "Smurf - Rescue in Gargamel's Castle (1983) (Coleco) (Prototype)", "AKA Smurf, Smurf Action", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6ed5012793f5ddf4353a48c11ea9b8d3", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Down on the Line (3 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "01 70", "", "", "", "", "", "", "", "" }, - { "6ed6bda5c42b2eb7a21c54e5b3ace3e3", "Canal 3 - Intellivision", "", "Ice Hockey (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6efe876168e2d45d4719b6a61355e5fe", "Bit Corporation", "PG207", "Mission 3,000 A.D. (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6f084daf265599f65422ef4173b69bc7", "", "", "Music Kit (V2.0) - Song Player (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6f2aaffaaf53d23a28bf6677b86ac0e3", "U.S. Games Corporation - Vidtec - JWDA, Garry Kitchen", "VC1001", "Space Jockey (1982) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6f3e3306da2aa6e74a5e046ff43bf028", "", "", "Defender Arcade (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender 2", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6f744f14aac04f7e1ea0d3f4bafcb3e4", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a3]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6f74ed915ffe73b524ef0f63819e2a1d", "Eckhard Stolberg", "", "An Exercise In Minimalism (V2) (1999) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fa0ac6943e33637d8e77df14962fbfc", "Imagic, Rob Fulop", "", "Cubicolor (1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fac680fc9a72e0e54255567c72afe34", "", "", "Superman (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fbd05b0ad65b2a261fa154b34328a7f", "", "", "Boardgame Demo (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fc0176ccf53d7bce249aeb56d59d414", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fc27a9233fc69d28d3f190b4ff80f03", "", "", "UFO #6 (Charles Morgan) (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fc394dbf21cf541a60e3b3631b817f1", "Imagic, Bob Smith", "720020-2A, IA3611P", "Dragonfire (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "6fd7c7057eeab273b29c7aafc7429a96", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6fe67f525c39200a798985e419431805", "Atari - GCC, Kevin Osborn", "CX2689, CX2689P", "Kangaroo (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "6ff4156d10b357f61f09820d03c0f852", "Atari, Larry Kaplan - Sears", "CX2612 - 99804, 49-75103", "Street Racer (1977) (Atari) (4K)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "10 60", "", "", "", "", "", "", "", "" }, - { "6ffc95108e5add6f9b8abcaf330be835", "Charles Morgan", "", "TP Bug (Charles Morgan) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "700a786471c8a91ec09e2f8e47f14a04", "Activision", "", "Hard-Head (1983) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "703d32062436e4c20c48313dff30e257", "", "", "Moving Maze Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "703f0f7af350b0fa29dfe5fbf45d0d75", "Bit Corporation", "P460", "4 Game in One Dark Green (1983) (BitCorp) (PAL)", "Rodeo Champ, Bobby is Going Home, Open Sesame, Festival", "", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "705fe719179e65b0af328644f3a04900", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "706e3cc4931f984447213b92d1417aff", "", "", "Joustpong (06-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "707ecd80030e85751ef311ced66220bc", "", "", "Double-Height 6-Digit Score Display (Background Color Change) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7096a198531d3f16a99d518ac0d7519a", "Telesys, Jim Rupp", "1004", "Ram It (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "709910c2e83361bc4bf8cd0c20c34fbf", "Rainbow Vision - Suntek", "SS-006", "Netmaker (1983) (Rainbow Vision) (PAL)", "AKA Amidar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "70a43fbdb1c039283ee5048d99842469", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "70a8480cfaf08776e5420365732159d2", "Rob Kudla", "", "Horizontally Scrolling Playfield Thing (Rob Kudla) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "70ce036e59be92821c4c7fd735ec6f68", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "70d14c66c319683b4c19abbe0e3db57c", "", "", "Oystron (V2.82) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "710497df2caab69cdcc45e919c69e13f", "Arcadia Corporation, Dennis Caswell", "5 AR-4200", "Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "713fde2af865b6ec464dfd72e2ebb83e", "", "", "Challenge (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "71464c54da46adae9447926fdbfc1abe", "M Network - INTV - APh Technological Consulting, Bruce Pedersen", "MT5663", "Lock 'n' Chase (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "714e13c08508ee9a7785ceac908ae831", "Home Vision - Gem International Corp. - VDI", "VCS83123", "Parachute (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "715dbf2e39ba8a52c5fe5cdd927b37e0", "Amiga - Video Soft", "3135", "S.A.C. Alert (1983) (Amiga) (Prototype)", "Uses Joyboard", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "715dd9e0240638d441a3add49316c018", "Atari", "", "128-in-1 Junior Console (Chip 2 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7187118674ff3c0bb932e049d9dbb379", "Zirok", "", "Keystone Keypers (1983) (Zirok)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "718ae62c70af4e5fd8e932fee216948a", "Data Age, J. Ray Dettling", "112-006", "Journey Escape (1983) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "718ee85ea7ec27d5bea60d11f6d40030", "Thomas Jentzsch", "", "Ghostbusters II (1992) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7197b6cbde6ecd10376155e6b848e80d", "Piero Cavina", "", "Multi-Sprite Game V2.1 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "71b193f46c88fb234329855452dfac5b", "Digitel", "", "Atlantis (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "71d005b60cf6e608d04efb99a37362c3", "Atari, Larry Kaplan", "CX2643", "Codebreaker (1978) (Atari) (PAL) (4K) [a]", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "71f09f128e76eb14e244be8f44848759", "Funvision - Fund. International Co.", "", "Time Race (Funvision) (PAL)", "AKA Time Warp", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "71f8bacfbdca019113f3f0801849057e", "Atari, Dan Hitchens", "CX26126", "Elevator Action (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72097e9dc366900ba2da73a47e3e80f5", "", "", "Euchre (15-06-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "721a5567f76856f6b50a6707aa8f8316", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72305c997f2cec414fe6f8c946172f83", "Arcadia Corporation, Dennis Caswell", "AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "724613effaf7743cbcd695fab469c2a8", "", "", "Super-Ferrari (Unknown)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "728152f5ae6fdd0d3a9b88709bee6c7a", "Spectravideo, Mark Turmell", "SA-217", "Gas Hog (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72876fd7c7435f41d571f1101fc456ea", "Quelle", "688.383 9", "Die Ente und der Wolf (1983) (Quelle) (PAL)", "AKA Pooyan", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72a46e0c21f825518b7261c267ab886e", "Xonox - K-Tel Software - Computer Magic", "99005, 6220, 6250", "Robin Hood (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72a5b5052272ac785fa076709d16cef4", "", "", "KC Munckin (29-01-2003) (J. Parlee)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72a63bcb5eb31bd0fd5e98ed05125ec1", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "72bda70c75dfa2365b3f8894bace9e6a", "Thomas Jentzsch", "", "Atlantis (TJ) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72d0acb5de0db662de0360a6fc59334d", "", "", "Cosmic Ark (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72db1194b1cc7d45b242f25eb1c148d3", "", "", "Pac-Man (1981) (Atari) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72fd08deed1d6195942e0c6f392e9848", "HES", "0701-406", "2 Pak Special - Wall Defender, Planet Patrol (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "72ffbef6504b75e69ee1045af9075f66", "Atari, Richard Maurer - Sears", "CX2632 - 49-75153", "Space Invaders (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73158ea51d77bf521e1369311d26c27b", "Zellers", "", "Challenge (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73521c6b9fed6a243d9b7b161a0fb793", "Atari, Tom Reuterdahl", "CX26163P", "Miniaturer Golf (32 in 1) (1988) (Atari) (PAL)", "AKA Miniature Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "736388d73198552d77d423962000006f", "Dactari", "", "Tennis (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73a710e621d44e97039d640071908aef", "", "", "Barber Pole Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73aa02458b413091ac940c0489301710", "Rainbow Vision - Suntek", "SS-016", "Boom Bang (1983) (Rainbow Vision) (PAL)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73b4e8f8b04515d91937510e680214bc", "", "", "Rubik's Cube Demo 3 (24-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73c545db2afd5783d37c46004e4024c2", "CBS Electronics - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "4L1767, 4L1768, 4L1769, 4L1770", "Smurf - Schtroumpfs (1983) (CBS Electronics) (PAL)", "Pitufo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73c839aff6a055643044d2ce16b3aaf7", "Activision, Alan Miller - Ariola", "EAX-016, PAX-016 - 711 016-725", "StarMaster (1982) (Activision) (PAL)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73cb1f1666f3fd30b52b4f3d760c928f", "", "", "Mines of Minos (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "73e66e82ac22b305eb4d9578e866236e", "Jone Yuan Telephonic Enterprise Co", "", "Unknown Datatech Game (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "73efa9f3cbe197f26e0fb87132829232", "CCE", "C-858", "Tennis (1983) (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "74023e0f2e739fc5a9ba7caaeeee8b6b", "Jone Yuan Telephonic Enterprise Co", "", "Fishing Derby (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "740a7fa80f52cc7287ba37677afb6b21", "", "", "Double Dragon (PAL) (Genesis)", "Genesis controller (C is jumpkick)", "Hack of Double Dragon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "740b47df422372fbef700b42cea4e0bf", "", "", "Dizzy Wiz (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "740f39e71104e90416c29a73560b9c6b", "Atari", "TE016643", "Diagnostic Test Cartridge 2.6P (1982) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7412f6788087d7e912c33ba03b36dd1b", "AtariAge, Omegamatrix", "", "Venture Reloaded (2019) (AtariAge) (Hack)", "Transformative hack of Venture", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "742de93b8d849220f266b627fbabba82", "", "", "SCSIcide (25-02-2001) (Chris Wilkson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7450ae4e10ba8380c55b259d7c2b13e8", "", "", "Register Twiddler Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7454786af7126ccc7a0c31fcf5af40f1", "", "", "Phantom Tank (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7465b06b6e25a4a6c6d77d02242af6d6", "Atari", "CX26193", "8 in 1 (01-16-92) (Atari) (Prototype)", "Game 2 is Centipede, but doesn't work", "Prototype", "", "", "8IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7481f0771bff13885b2ff2570cf90d7b", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "749fec9918160921576f850b2375b516", "Spectravision - Spectravideo", "SA-205", "China Syndrome (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "74d072e8a34560c36cacbc57b2462360", "Sancho - Tang's Electronic Co.", "TEC002", "Seahawk (1982) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "74ebaca101cc428cf219f15dda84b6f8", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "74f623833429d35341b7a84bc09793c0", "Zellers", "", "Radar (Zellers)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75028162bfc4cc8e74b04e320f9e6a3f", "Atari, Greg Easter, Mimi Nyden", "CX26107", "Snow White (02-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7511c34518a9a124ea773f5b0b5c9a48", "", "", "Donkey Kong (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75169c08b56e4e6c36681e599c4d8cc5", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5666", "Astroblast (1982) (M Network)", "Can also use left joystick", "Uncommon", "", "", "", "", "", "", "", "PADDLES", "", "YES", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "752da1c0acd7d132ccfb0b1067f53cf6", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "753375d183c713cfa0aa7298d1f3067b", "Arcadia Corporation, Steve Hales, Stephen Harland Landrum", "AR-4102", "Suicide Mission (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7550b821ee56fb5833dca2be88622d5a", "", "", "Multiple Moving Objects Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75511bb694662301c9e71df645f4b5a7", "Activision, Bob Whitehead - Ariola", "EAG-011, PAG-011 - 711 011-715", "Stampede (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "755fed16b48e81de05130708a905d00d", "SnailSoft", "", "Comitoid beta 3 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "756ca07a65a4fbbedeb5f0ddfc04d0be", "Atari, Jim Huether", "CX2629, CX2629P", "Sky Diver (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7574480ae2ab0d282c887e9015fdb54c", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7576dd46c2f8d8ab159d97e3a3f2052f", "Goliath - Hot Shot", "83-112", "Time Machine (1983) (Goliath) (PAL)", "AKA Asteroid Fire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "757f529026696e13838364dea382a4ed", "Activision, David Crane - Ariola", "EAX-014, PAX-014, EAX-014-04B, EAX-014-04I - 711 014-720", "Grand Prix (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75893a9dc5de4b91cc426959b82a1da0", "Champ Games", "CG-02-P", "Conquest Of Mars (2010) (PAL60)", "Rev 2 release", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "75a303fd46ad12457ed8e853016815a0", "ZiMAG - Emag - Vidco", "715-111 - GN-060", "Immies & Aggies (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75b22fdf632d76e246433db1ebccd3c4", "", "", "Skeleton+ (05-05-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75b557be7f08db84ec5b242207b9f241", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75e276ba12dc4504659481c31345703a", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75e8d8b9e9c5c67c2226dbfd77dcfa7d", "", "", "2600 Digital Clock (V b1) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75ea128ba96ac6db8edf54b071027c4e", "Atari, David Crane", "CX26163P", "Slot Machine (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "75ea60884c05ba496473c23a58edf12f", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari) (PAL) [a]", "ROM must be started in bank 0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "75ee371ccfc4f43e7d9b8f24e1266b55", "Atari, Greg Easter, Mimi Nyden", "CX26107", "Snow White (11-09-1982) (Atari) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7608abdfd9b26f4a0ecec18b232bea54", "Atari, Bob Whitehead", "CX26163P", "NFL Football (32 in 1) (1988) (Atari) (PAL)", "AKA Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7623a639a6fffdb246775fe2eabc8d01", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7628d3cadeee0fd2e41e68b3b8fbe229", "Atari", "CX26163P", "Fishing Derby (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7648e72a5b5899076688df18a1ddcf72", "CBS Electronics, Richard K. Balaska Jr., Andy Frank, Stuart Ross", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics) (Prototype)", "Black Box", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "764ce6801f28a9ad36f11de3e57c053b", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666", "RealSports Volleyball (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76809eb1ee0db8a318308a5cdda0f4e2", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "769ddc995dbb9edb8167efcea9f34a7c", "", "", "H.E.R.O. (Genesis)", "Genesis controller (B is laser, C is dynamite)", "Hack of H.E.R.0.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76a9bf05a6de8418a3ebc7fc254b71b4", "VideoSoft, Jerry Lawson, Dan McElroy", "VS1008", "Color Bar Generator (1984) (VideoSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76c685d1a60c0107aa54a772113a2972", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (3 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76c88341017eae660efc6e49c4b6ab40", "", "", "Indiana Pitfall (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76ee917d817ef9a654bc4783e0273ac4", "Otto Versand", "311377", "Fox & Goat (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Nuts", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76f53abbbf39a0063f24036d6ee0968a", "M Network, David Akers, Joe 'Ferreira' King, Patricia Lewis Du Long, Jeff Ratcliff - INTV", "MT7045", "Bump 'n' Jump (1983) (M Network)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "76f66ce3b83d7a104a899b4b3354a2f2", "UA Limited", "", "Cat Trax (1983) (UA Limited) (1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "77057d9d14b99e465ea9e29783af0ae3", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision)", "AKA Drag Strip", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7732e4e4cc2644f163d6650ddcc9d9df", "HES", "771-333", "2 Pak Special - Challenge, Surfing (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7761418d46af069b8cd80c29fe6cd814", "Dion Olsthoorn", "RetroN 77 edition", "Amoeba Jump (R77) (DionoiD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7778ac65d775a079f537e97cbdad541c", "", "", "Spider Fighter (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "777aece98d7373998ffb8bc0b5eff1a2", "", "", "2600 Collison Demo 2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "77887e4192a6b0a781530e6cf9be7199", "Atari", "CX2604", "Space War (1978) (Atari) [b1]", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "77be57d872e3f5b7ecf8d19d97f73281", "", "", "Basketball (208 in 1) (Unknown) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "77cd9a9dd810ce8042bdb9d40e256dfe", "Kyle Pittman", "", "Evil Dead (2003) (Kyle Pittman) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "77d0a577636e1c9212aeccde9d0baa4b", "Atari, Joe Decuir", "CX2621, CX2621P", "Video Olympics (1977) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "PADDLES_IAXDR", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "78297db7f416af3052dd793b53ff014e", "", "", "Poker Squares (V0.17) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7836794b79e8060c2b8326a2db74eef0", "", "", "RIOT RAM Test (26-11-2002) (Dennis Debro)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "784176346e9422733d55c427230e5bad", "Activision, Alex DeMeo", "", "Title Match Pro Wrestling (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "784abfdb31d5341e5bd404d8d2a71c3b", "Alessandro Ciceri", "", "MagiCard (TV format conversion) (alex_79) (PAL)", "MagiCard PAL conversion hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7860716fa5dbc0fffab93fb9a4cb4132", "", "", "Hangman Monkey Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7867ee819b53d69cfcfe740f7ddca574", "Arcadia Corporation, Dennis Caswell", "1 AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "787ebc2609a31eb5c57c4a18837d1aee", "Prescott", "", "Vault Assault (19xx) (Prescott)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "78821ef76ebc3934850d1bc1b9e4f4b0", "HES - Activision", "542", "Hot Action Pak - Ghostbusters, Tennis, Plaque Attack (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "78963290052fd17c6c7998305ab3a6a0", "", "", "Push (V0.08) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "78b84cfb1c57b0488d674d2374e656e6", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "78c2de58e42cd1faac2ea7df783eaeb3", "", "", "Fu Kung! (V0.07) (25-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79004f84bdeee78d142e445057883169", "CCE", "C-830", "Planet Patrol (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "791bc8aceb6b0f4d9990d6062b30adfa", "Activision, David Crane - Ariola", "EAX-018, EAX-018-04B, EAX-018-04I - 711 018-725", "Pitfall! (1982) (Activision) (PAL)", "Abenteuer im Urwald (Jungle Runner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7926083ad423ed685de3b3a04a914315", "Barry Laws Jr.", "", "Face Invaders 2 (Barry Laws Jr.) (Hack)", "Hack of Astroblast", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "792b1d93eb1d8045260c840b0688ec8f", "Kroko", "", "3E Bankswitch Test (TIA @ $00)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7972e5101fa548b952d852db24ad6060", "Atari - Sears", "CX2627 - 6-99841", "Human Cannonball (1979) (Atari)", "AKA Cannon Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "798b8921276eec9e332dfcb47a2dbb17", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari) (PAL) [a]", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "798cc114f1623c14085868cd3494fe8e", "", "", "Pins Revenge (Atari Freak 1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7991e1797e5e9f311fd957e62d889dff", "Joe Grand", "", "SCSIcide (v1.1) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "7996b8d07462a19259baa4c811c2b4b4", "", "", "Math Gran Prix (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79ab4123a83dc11d468fb2108ea09e2e", "Activision - Cheshire Engineering, David Rolfe, Larry Zwick", "AZ-037-04", "Beamrider (1984) (Activision)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79b649fb812c50b4347d12e7ddbb8400", "", "", "Red Pong Number 2 Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "79c27f90591e3fdc7d2ed020ecbedeb3", "CCE", "C-815", "Seaquest (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79d4af56036ec28f298cad964a2e2494", "", "", "Hangman Pac-Man Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79d6f61da3c64688ac8e075667f8a39f", "", "", "Tie-Fighters (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79e5338dbfa6b64008bb0d72a3179d3c", "M Network - INTV, David Akers, Patricia Lewis Du Long", "MT4313", "Star Strike (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "79fcdee6d71f23f6cf3d01258236c3b9", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673, CX2673P", "Phoenix (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a09299f473105ae1ef3ad6f9f2cd807", "Atari, Steve Wright", "CX2616P", "Pele's Soccer (1981) (Atari) (PAL)", "AKA Pele's Championship Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a2af383014f5d810ad26d322823549d", "", "", "FlickerSort Demo (20-04-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a5463545dfb2dcfdafa6074b2f2c15e", "20th Century Fox Video Games - Sirius Software, Mark Turmell", "11007", "Turmoil (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a63d7ea3f2851bcf04f0bb4ba1a3929", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (3 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a64a8b727c8215d945e37d565ca95a5", "Atari, Warren Robinett", "CX2606", "Slot Racers (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a64b5a6e90619c6aacf244cdd7502f8", "Baroque Gaming (Brian Eno)", "", "Warring Worms (Beta 1) (2002) (Baroque Gaming)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a7f6ab9215a3a6b5940b8737f116359", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7a93d0c029eaa72236523eedc3f19645", "", "", "20 Sprites at Once Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ab0917107b6ec768a5ebaadf28c497a", "", "", "Santa's Helper (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "7ab210f448de518fa61a5924120ba872", "", "", "Fortress (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ab2f190d4e59e8742e76a6e870b567e", "Apollo, Larry Martin", "AP-2008", "Guardian (1982) (Apollo)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 65", "", "", "", "", "", "", "", "" }, - { "7ac4f4fb425db38288fa07fb8ff4b21d", "Goliath", "83-213", "Space Eagle (1983) (Goliath) (PAL)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ad257833190bc60277c1ca475057051", "Atari, Alan J. Murphy, Robert Zdybel", "CX2668", "RealSports Football (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7ad782952e5147b88b65a25cadcdf9e0", "Imagic, Dave Johnson", "720119-1A, 03211", "Kwibble (1983) (Imagic) (Prototype)", "AKA Quick Step! Beta", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7adbcf78399b19596671edbffc3d34aa", "Atari, Mimi Nyden, Joseph Tung", "CX26152", "Super Baseball (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7af40c1485ce9f29b1a7b069a2eb04a7", "Amiga - Video Soft", "3120", "Mogul Maniac (1983) (Amiga)", "Uses the Amiga Joyboard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b24bfe1b61864e758ada1fe9adaa098", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b33407b2b198af74906b936ce1eecbb", "King Atari", "", "Ghostbuster 2 (King Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7b3cf0256e1fa0fdc538caf3d5d86337", "CommaVid, Joseph Biel", "CM-009", "Stronghold (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b43c32e3d4ff5932f39afcb4c551627", "Syncro, Daniel Wolf", "", "Kamikaze Saucers (1983) (Syncro) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b4be337ac4d73eda75c848355f6f480", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "7b5207e68ee85b16998bea861987c690", "Atari, Carol Shaw", "CX26163P", "3-D Tic-Tac-Toe (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b57318c489ff178f7ff500da1ec9e8c", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b6f3348dbf71ada88db0fdaf7feefe0", "", "", "3-D Corridor (Pink Spiral) (31-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b79beb378d1b4471def90ceccf413de", "", "", "Pitfall Cupcake (Hack)", "Hack of Pitfall", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b7b4ac05232490c28f9b680c72998f9", "Zellers", "", "Freeway (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b8a481e0c5aa78150b5555dff01f64e", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (05-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7b938c7ddf18e8362949b62c7eaa660a", "Atari, Bob Whitehead - Sears", "CX2603 - 99803, 49-75601", "Star Ship (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ba07d4ea18bf3b3245c374d8720ad30", "Starpath Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (Preview) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7bb286cb659d146af3966d699b51f509", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (04-03-1989) (Atari) (Prototype)", "AKA Saving Mary", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7bc4fd254ec8c0a25a13f02fd3f762ff", "Retroactive", "", "Qb (V1.00) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7c00e7a205d3fda98eb20da7c9c50a55", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo", "AP-2004", "Lost Luggage (1982) (Apollo)", "AKA Airport Mayhem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7c4a499d343fca0cef2d59dd16af621a", "", "", "Poker Card Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7c757bb151269b2a626c907a22f5dae7", "TNT Games - Sculptured Software, Adam Clayton", "26192", "BMX Air Master (1989) (TNT Games) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7c7a4a2d505c2d0c75337c44711d8d54", "Atari, Warren Robinett", "", "Elf Adventure (04-22-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7c9b3b8b25acf2fe3b8da834f69629c6", "", "", "I Robot (1984) (Atari) (Prototype) [!]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ca7a471d70305c673fedd08174a81e8", "Tim Snider", "", "Venture II (2001) (Tim Snider)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7cc77f6745e1f2b20df4a4327d350545", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ccf350354ee15cd9b85564a2014b08c", "", "", "Big Dig (13-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7cd379da92c93679f3b6d2548617746a", "", "", "Demo Image Series #5 - Clown (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7cd900e9eccbb240fe9c37fa28f917b5", "Jone Yuan Telephonic Enterprise Co", "", "Bi! Bi! (Jone Yuan) (PAL)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ced6709f091e79a2ab9575d3516a4ac", "Activision, Steve Cartwright - Ariola", "EAX-027 - 711 027-722", "Plaque Attack (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7cedffa0db65d610568b90aeca705ac6", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7cf3a9267cdb95aba91abc5838d61cc5", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "7d0b49ea4fe3a5f1e119a6d14843db17", "Gameworld, J. Ray Dettling", "133-008", "Frankenstein's Monster (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d1034bcb38c9b746ea2c0ae37d9dff2", "Atari, Brad Stewart", "", "Morse Code Tutor (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d3cdde63b16fa637c4484e716839c94", "CCE", "", "Road Runner (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d483b702c44ee65cd2df22cbcc8b7ed", "Atari, Warren Robinett", "", "Elf Adventure (05-25-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d5c3b7b908752b98e30690e2a3322c2", "Dactari - Milmar", "", "Freeway (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d726fa494f706784bafeb1b50d87f23", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (07-27-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d8287e8423a56d4f8cef10435d97179", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d903411807704e725cf3fafbeb97255", "Imagic, Rob Fulop", "720104-1A, 720104-1B, IA3204", "Cosmic Ark (Reaction) (1982) (Imagic) [selectable starfield]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d93071b3e3616093a6b5a98b0315751", "", "", "Gunfight 2600 - Music & Bugfixes 2 (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d940d749e55b96b7b746519fa06f2de", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (Preview) (1983) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7d9c96b215d1941e87b6fb412eb9204f", "", "", "Othello (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7da9de8d62fcdd3a2c545b2e720c2a61", "CommaVid, John Bronstein", "CM-001", "MagiCard (1981) (CommaVid) (4K)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7dbc8fa2e488e3f6b87fbe0f76c5b89f", "Ed Federmeyer", "", "Sound X (1996) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7dc03a1f56d0e6a8aae3e3e50d654a08", "", "", "Hozer Video Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7dcbfd2acc013e817f011309c7504daa", "Arcadia Corporation, Dennis Caswell", "AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7dd9c5284422f729066ab22a284c8283", "CCE", "C-833", "Target Practice (1983) (CCE) [a]", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ded20e88b17c8149b4de0d55c795d37", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.26)", "", "New Release, supports BoosterGrip", "", "", "", "", "", "", "", "BOOSTERGRIP", "DRIVING", "", "", "", "", "", "", "", "", "", "" }, - { "7dfd100bda9abb0f3744361bc7112681", "Telesys, Don Ruffcorn", "1006", "Demolition Herby (1983) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7e2fe40a788e56765fe56a3576019968", "Activision - Imagineering, Donald Hahn, Dan Kitchen", "AK-050-04", "Double Dragon (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e464186ba384069582d9f0c141f7491", "PlayAround - J.H.M.", "206", "General Re-Treat (1982) (PlayAround) (PAL)", "AKA Custer's Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e4783a59972ae2cd8384f231757ea0b", "Atari - Imagineering, Dan Kichen", "CX26139P", "Crossbow (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e51a58de2c0db7d33715f518893b0db", "CBS Electronics, E.F. Dreyer, Ed Salvo", "4L 2738 0000", "Mountain King (1983) (CBS Electronics) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7e52a95074a66640fcfde124fffd491a", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673", "Phoenix (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e7c4c59d55494e66eef5e04ec1c6157", "Baroque Gaming (Brian Eno)", "", "Warring Worms (2002) (Baroque Gaming)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e8aa18bc9502eb57daaf5e7c1e94da7", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "M8774, M8794", "Wizard of Wor (1982) (CBS Electronics)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7e9da5cb84d5bc869854938fe3e85ffa", "Atari, Ian Shepard - Sears", "CX2604 - 6-99812, 49-75106", "Space War (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7e9f088e15b2af9ff3411991393e6b1f", "Atari - Roklan, Joe Gaucher", "CX2679", "RealSports Basketball (12-28-1982) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7eab0284a0cd1043461d446a08d08cec", "Jone Yuan Telephonic Enterprise Co", "", "Basic Math (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ead257e8b5a44cac538f5f54c7a0023", "Xonox, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7eaf009a892f03d90682dc1e67e85f07", "Fabrizio Zavagli", "", "Bounce! (18-03-2003) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7eafc9827e8d5b1336905939e097aae7", "Atari, Mark R. Hahn", "", "Elk Attack (1987) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7eba20c2291a982214cc7cbe8d0b47cd", "Imagic, Dave Johnson", "720119-1A, 03211", "Quick Step! (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ed61a18cebdeca0a93be1f5461731e5", "Dactari", "", "Skiing (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ed7130a6e4020161836414332b11983", "", "", "Fu Kung! (V0.05 Cuttle Card Compatible) (13-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7edc8fcb319b3fb61cac87614afd4ffa", "Activision, Alan Miller", "AG-003", "Checkers (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ef3ca08abde439c6ccca84693839c57", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (1983) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "7ef74879d7cb9fa0ef161b91ad55b3bb", "CCE", "", "Vanguard (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f0209cfcc3d181715463f4d6451cecf", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (05-15-1983) (Atari) (Prototype)", "AKA RealSports Driving", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f07cd2e89dda5a3a90d3ab064bfd1f6", "Videospielkassette - Ariola", "PGP234", "Boxen (Ariola) (PAL)", "AKA Boxing", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f430c33044e0354815392b53a9a772d", "HES", "773-891", "2 Pak Special - Cavern Blaster, City War (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f525b07bc98080cc8950f7284e52ede", "Atari", "", "128-in-1 Junior Console (Chip 4 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f54fa6aa824001af415503c313262f2", "HES", "", "Boom Bang (HES) (PAL)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f6533386644c7d6358f871666c86e79", "CommaVid, Irwin Gaines", "CM-008", "Cakewalk (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f790939f7eaa8c47a246c4283981f84", "", "", "This Planet Sucks Demo 3 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7f819454734ddf93f83fefcffcd3e212", "Jone Yuan Telephonic Enterprise Co", "", "Outlaw (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7f9fbe3e00a21ea06e6ae5e0e5db2143", "", "", "Skate Boardin' (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7fcd1766de75c614a3ccc31b25dd5b7a", "PlayAround - J.H.M.", "203", "Knight on the Town (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "7fcd5fb59e88fc7b8473c641f44226c3", "CCE", "C-807", "Space Tunnel (1983) (CCE)", "AKA O Tunel Espacial", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ff53f6922708119e7bf478d7d618c86", "Suntek", "SS-032", "Walker (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "7ffc2d80fd49a124808315306d19868e", "Ishido", "", "Domino (Ishido) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "801ba40f3290fc413e8c816c467c765c", "Hozer Video Games", "", "Gunfight 2600 - Westward Ho! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "803393ed29a9e9346569dd1bf209907b", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (02-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "804ed85eadf1ce3e93721547cbea7592", "CCE", "", "Fishing Derby (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8055b9c2622136fd91edfea6df642daf", "Activision", "", "Unknown Activision Game #1 (1983) (Activision) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "805f9a32ef97ac25f999a25014dc5c23", "SnailSoft", "", "Balthazar (SnailSoft)", "AKA Babylon 5", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8068e07b484dfd661158b3771d6621ca", "Epyx, Steven A. Baker, Peter Engelbrite", "80561-00286", "California Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "807841df228ee8aab0a06ee639ce5a8a", "Coleco - Project Guild - GMA, Michael Green, Anthony R. Henderson, Gary Littleton", "2455", "Turbo (1982) (Coleco) (Prototype)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "807a8ff6216b00d52aba2dfea5d8d860", "John Payson", "", "Strat-O-Gems Deluxe (2005) (J. Payson)", "Uses the AtariVox controller", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "" }, - { "808c3b1e60ee0e7c65205fa4bd772221", "CCE", "", "Defender (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80cd42881e670e4b74a9ccd10d0d7b2e", "20th Century Fox Video Games - Sirius, Ed Hodapp", "11004", "Deadly Duck (1982) (20th Century Fox) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80cec82239913cb8c4016eb13749de44", "David Marli", "", "Invaders from Space by David Marli (Space Invaders Hack)", "Hack of Space Invaders (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80dcbe1b55f12be731a224a53ee4ad5f", "Bit Corporation", "R320", "Amidar (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80e1410ec98089e0733cc09e584dba4b", "Dynamics", "DY-293005", "Jumping Jack (1983) (Dynamics) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80e52315919bd8a8b82a407ccd9bb13f", "", "", "Euchre (Jul 28) (2002) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80e5400470ac788143e6db9bc8dd88cf", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (06-XX-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "80f7bf7418a462e8687ecefeaf6eb9c2", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8101efafcf0af32fedda4579c941e6f4", "", "", "Okie Dokie (4K) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81073d0377a2badef8d5e74fc44fc323", "Thomas Jentzsch", "", "Sadoom (TJ) (PAL60) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "PAL60", "", "", "", "", "", "", "" }, - { "8108162bc88b5a14adc3e031cf4175ad", "Suntek", "SS-030", "Skydiver (1983) (Suntek) (PAL)", "AKA Parachute", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8108ad2679bd055afec0a35a1dca46a4", "", "", "Maze Craze (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC", "", "", "", "", "", "", "" }, - { "810d8952af5a6036fca8d0c4e1b23db6", "Tiger Vision - Eram", "", "Keystone (Tiger Vision)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81254ebce88fa46c4ff5a2f4d2bad538", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81341f00b61ab37d19d1529f483d496d", "", "", "Fu Kung! (V0.04) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "813985a940aa739cc28df19e0edd4722", "Imagic, Bob Smith", "720000-201, 720102-1B, IA3201", "Star Voyager (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81414174f1816d5c1e583af427ac89fc", "Thomas Jentzsch", "", "Treasure Below (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "814210c0e121f7dbc25661b93c06311c", "", "", "Joustpong (16-09-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81591a221419024060b890665beb0fb8", "Atari, Carla Meninsky, Ed Riddle", "CX2611, CX2611P", "Indy 500 (1977) (Atari) (PAL)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "8190b403d67bf9792fe22fa5d22f3556", "", "", "Sky Diver (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "819aeeb9a2e11deb54e6de334f843894", "Atari, Gary Palmer", "CX2661", "Fun with Numbers (1980) (Atari)", "AKA Basic Math", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81a010abdba1a640f7adf7f84e13d307", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames)", "AKA Targ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "81b3bf17cf01039d311b4cd738ae608e", "CBS Electronics - Roklan, Joe Gaucher, Alex Leavens", "M8776, M8793", "Gorf (1982) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "81f4f0285f651399a12ff2e2f35bab77", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "822a950f27ff0122870558a89a49cad3", "", "", "Space Jockey (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82337e5fe0f418ca9484ca851dfc226a", "Thomas Jentzsch", "", "Robot City (V1.0) (Alpha) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "826481f6fc53ea47c9f272f7050eedf7", "Imagic, Dennis Koble", "720103-1A, IA3203", "Atlantis II (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "827a22b9dffee24e93ed0df09ff8414a", "CBS Electronics, Stuart Ross", "", "Wings (10-10-1983) (CBS Electronics) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8290daea8391f96d7c8e1482e184d19c", "Eckhard Stolberg", "", "Frame Timed Sound Effects (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82bf0dff20cee6a1ed4bb834b00074e6", "Suntek", "SS-035", "Panda (1983) (Quest) (Suntek) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82c25d1c35e6ac6f893d1d7c2fc2f9c8", "Atari, Larry Kaplan", "CX2628, CX2628P", "Bowling (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82de957d155fc041fc6afb8315a28550", "Coleco, Joseph Biel", "2457", "Venture (1982) (Coleco) (Prototype)", "2K", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82e7aab602c378cffdd8186a099e807e", "", "", "Space Robot (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "82efe7984783e23a7c55266a5125c68e", "CCE", "C-837", "Pizza Chef (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "834a2273e97aec3181ee127917b4b269", "Quelle", "043.151 0, 874.382 5", "Die hungrigen Froesche (1983) (Quelle) (PAL)", "AKA Frogs and Flies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "835759ff95c2cdc2324d7c1e7c5fa237", "20th Century Fox Video Games, Frank Cohen, Douglas 'Dallas North' Neubauer", "11011", "M.A.S.H (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8372eec01a08c60dbed063c5524cdfb1", "", "", "Cross Force (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8388d6fe59c38c0b3a6ab2c58420036a", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (12-06-1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83b8c01c72306d60dd9b753332ebd276", "", "", "Bank Heist (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83bdc819980db99bf89a7f2ed6a2de59", "Atari, Carla Meninsky - Sears", "CX2637 - 49-75158", "Dodge 'Em (1980) (Atari) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83d15fb9843d9f84aa3710538403f434", "", "", "Gunfight 2600 - Release Candidate (2001) (MP) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83e1b9f22f29259679e1018bc04cc018", "Bit Corporation", "R320", "Fast Eddie (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83f05ececae8be59ba1e51135f4bdcbf", "", "", "Demo Image Series #13 - Mario (4K Interleaved Chronocolour) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83f50fa0fbae545e4b88bb53b788c341", "Atari, Larry Kaplan - Sears", "CX2643 - 6-99815", "Codebreaker (1978) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "83fafd7bd12e3335166c6314b3bde528", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00251", "Winter Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "840a5a2eaea24d95d289f514fd12f9bb", "", "", "GBImprov (Hack)", "Hack of Ghostbusters", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "841057f83ce3731e6bbfda1707cbca58", "Champ Games", "CG-04-N", "Super Cobra Arcade (NTSC)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "841b7bc1cad05f5408302308777d49dc", "Activision", "", "Unknown Activision Game (10-22-1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "84290e333ff7567c2380f179430083b8", "Imagic, Dave Johnson", "13211, EIX-004-04I", "Quick Step! (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "843435eb360ed72085f7ab9374f9749a", "Joe Grand", "", "SCSIcide (1.31) (Joe Grand)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "84535afb9a69712ec0af4947329e08b8", "CCE", "C-868", "Bingo (1983) (CCE) (PAL)", "AKA Dice Puzzle", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8454ed9787c9d8211748ccddb673e920", "Froggo", "FG1002", "Spiderdroid (1987) (Froggo)", "AKA Amidar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8490e1014c2baa0d3a3a08854e5d68b3", "Xonox, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "84db818cd4111542a15c2a795369a256", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "850ffd5849c911946b24544ea1e60496", "", "", "Invasion (07-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "851cc1f3c64eaedd10361ea26345acea", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85227160f37aaa29f5e3a6c7a3219f54", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8530caaaf40acbdcd118c282b5f8a37a", "", "", "This Planet Sucks Demo 2 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8538c5e3ee83267774480649f83fa8d6", "", "", "Escape Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "853c11c4d07050c22ef3e0721533e0c5", "", "", "Oink! (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85470dcb7989e5e856f36b962d815537", "Atari - Sculptured Software, Inc., Steve Aguirre", "CX26162", "Fatal Run (1989) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85478bb289dfa5c63726b9153992a920", "", "", "Candi (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "854b68b93e7123a3be42b5a2a41f75d7", "Atari, Carol Shaw", "CX2618, CX2618P", "3-D Tic-Tac-Toe (1980) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85502d69fe46b7f54ef2598225678b47", "Jone Yuan Telephonic Enterprise Co", "", "Super-Ferrari (Jone Yuan)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85564dd0665aa0a1359037aef1a48d58", "ITT Family Games", "554-33 367", "Laser Base (1983) (ITT Family Games) (PAL) [a]", "AKA The End of the World (Perry Rhodan-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8556b42aa05f94bc29ff39c39b11bff4", "Atari, Craig Nelson - Sears", "CX2617 - 49-75183", "Backgammon (1979) (Atari)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 80", "", "", "", "", "", "", "", "" }, - { "855a42078b14714bcfd490d2cf57e68d", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (1983) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8597f66dd37d9c855663804669d69d7a", "Tigervision, Warren Schwader", "7-003", "Threshold (1982) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85a4133f6dcf4180e36e70ad0fca0921", "CCE", "C-827", "Chopper Command (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85b1bca93e69f13905107cc802a02470", "Atari, Craig Nelson", "CX2617, CX2617P", "Backgammon (1979) (Atari) (PAL)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 80", "", "", "", "", "", "", "", "" }, - { "85bbefb90e16bf386b304c1e9a1f6084", "Champ Games", "CG-02-P", "Conquest Of Mars (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "85e48d68c8d802e3ba9d494a47d6e016", "", "", "Ship Demo (V 15) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "85e564dae5687e431955056fbda10978", "Milton Bradley Company - Renaissance Technology, Ty Roberts", "4362", "Survival Run (1983) (Milton Bradley)", "AKA Cosmic Commander", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "86128001e69ab049937f265911ce7e8a", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Lochjaw (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "862cf669cbced78f9ed31a5d375b2ebe", "", "", "Gunfight 2600 - Flicker acceptance (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8644352b806985efde499ae6fc7b0fec", "CCE", "C-801", "Mr. Postman (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8654d7f0fb351960016e06646f639b02", "Home Vision, R.J.P.G. - Gem International Corp. - VDI", "VCS83106", "Ski Hunt (1983) (Home Vision) (PAL)", "AKA Skiiing Hunt", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "866e5150c995c4ae5172e5207ba948c7", "Canal 3 - Intellivision", "", "Stampede (Canal 3) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "869abe0426e6e9fcb6d75a3c2d6e05d1", "", "", "Stampede (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "86b4aa76bbeb70e1a4f9211a9880ba8e", "", "", "Incoming (1 Player Version) (05-11-2002) (Ben Larson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8712cceec5644aacc2c21203d9ebe2ec", "Retroactive", "", "Qb (V0.10) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8726c17ee7b559cb7bf2330d20972ad0", "", "", "Cave Demo (21-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "873fb75a7788ba0f4ae715229a05545e", "", "", "Euchre (Improved Colors) (PAL) (26-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8747ba79cd39fa83a529bb26010db21b", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL) [different speed and colors]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8749a0d088df25218c149dc325abc7ca", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a5]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "874c76726f68c166fcfac48ce78eef95", "", "", "Red Pong Number 2 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8764462d7d19a33b0717af22b99fc88f", "CCE", "", "Sky Jinks (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "87662815bc4f3c3c86071dc994e3f30e", "Intellivision Productions - M Network, Patricia Lewis Du Long, Stephen Tatsumi", "", "Swordfight (1983) (Intellivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "876a953daae0e946620cf05ed41989f4", "Retroactive", "", "Qb (V2.08) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "877a5397f3f205bf6750398c98f33de1", "Erik Eid", "", "Euchre (Beta) (PAL) (12-09-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8786c1e56ef221d946c64f6b65b697e9", "20th Century Fox Video Games, David Lubar", "11015", "AKA Space Adventure", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8786f229b974c393222874f73a9f3206", "Activision, Larry Miller - Ariola", "EAX-021, EAX-021-04I - 711 021-720", "Spider Fighter (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8786f4609a66fbea2cd9aa48ca7aa11c", "Goliath", "5", "Open Sesame (1983) (Goliath) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "87b460df21b7bbcfc57b1c082c6794b0", "Dennis Debro", "", "Climber 5 (20-03-2003) (Dennis Debro)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "87b6a17132fc32f576bc49ea18729506", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "87bea777a34278d29b3b6029833c5422", "Thomas Jentzsch", "", "Polaris (1983) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "87e79cd41ce136fd4f72cc6e2c161bee", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "87f020daa98d0132e98e43db7d8fea7e", "20th Century Fox Video Games - Sirius, David Lubar", "11001", "Worm War I (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "883258dcd68cefc6cd4d40b1185116dc", "Activision, David Crane - Ariola", "EAZ-030, EAZ-030-04B, EAZ-030-04I - 711 030-725", "Decathlon (1983) (Activision) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8874b68751fd2ba6d3306a263ae57a7d", "Eric Mooney", "", "Invaders by Erik Mooney (Alpha 1) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8885d0ce11c5b40c3a8a8d9ed28cefef", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner - Sears", "CX2608 - 49-75165", "Super Breakout (1982 - 1981) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "888debb162d7d1ae71025b4ab794257f", "", "", "Interleaved ChronoColour - Nude Art (17-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88a6c9c88cb329ee5fa7d168bd6c7c63", "CCE", "C-1007", "Jungle Hunt (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88d300a38bdd7cab9edad271c18cd02b", "Funvision - Fund. Int'l Co.", "", "Pac Kong (Funvision) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88d7b6b3967de0db24cdae1c7f7181bd", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88d8a1accab58cf1abb043613cf185e9", "Ultravison", "", "Sabotage (Ultravison)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88dce4037471424bb38ab6841aaa8cab", "", "", "Double-Height 6-Digit Score Display (Two Background Color Change) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88ed87c011f699dd27321dbe404db6c8", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "88f74ec75ef696e7294b7b6ac5ca465f", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (16K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8905d54f48b8024fc718ed643e9033f7", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (05-24-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "890c13590e0d8d5d6149737d930e4d95", "Atari, David Crane - Sears", "CX2605 - 6-99822, 49-75109", "Outlaw (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8917f7c1ac5eb05b82331cf01c495af2", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8933976f2029c0d8492ebd8f4eb21492", "", "", "Synthcart Plus (09-02-2003) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8953bc11352d794431d3303e31d3b892", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (02-17-1983) (Tigervision) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "896ec58f26e930e02f5e4f046602c3a1", "", "", "Synthcart (Beta) (2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "898143773824663efe88d0a3a0bb1ba4", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "AZ-033, AZ-033-04", "Space Shuttle (1983) (Activision) [FE]", "A Journey Into Space", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "898748d5eaac3164b0391a64ae1e0e32", "", "", "Hangman Man 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "898b5467551d32af48a604802407b6e8", "Bit Corporation", "PG208", "Snail Against Squirrel (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "89a65b83203980d5d4d60f52a584a5b8", "", "", "Marble Craze (PAL) (02-02-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "89a68746eff7f266bbf08de2483abe55", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1984) (Atari)", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "89afff4a10807093c105740c73e9b544", "", "", "Pooyan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "89eaba47a59cbfd26e74aad32f553cd7", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2001", "Spacechase (1982) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a159ee58b2f0a54805162984b0f07e5", "Atari - Sculptured Software, Inc., Steve Aguirre", "CX26162", "Fatal Run (1989) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a183b6357987db5170c5cf9f4a113e5", "Atari - Roklan, Joe Gaucher", "CX2679", "RealSports Basketball (01-11-1983) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a42e2c7266439d8997a55d0124c912c", "", "", "Hangman Invader Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a49cf1785e3dea2012d331a3ad476e1", "", "", "Boulderdash (10 Blocks Wide) (02-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a6c84f481acf42abcb78ba5064ad755", "128-in-1 Junior Console", "", "Street Racer (128-in-1 Junior Console) (PAL) (4K)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "10 75", "", "", "", "", "", "", "", "" }, - { "8a8e401369e2b63a13e18a4d685387c6", "Activision, David Crane - Ariola", "EAG-008, PAG-008, EAG-008-04I - 711 008-720", "Laser Blast (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8a9d874a38608964f33ec0c35cab618d", "Chris Cracknell", "", "Rescue Bira Bira (Chris Cracknell)", "Hack of Jungle Fever", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8a9d953ac3db52a313a90d6a9b139c76", "", "", "Hangman Invader Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8aad33da907bed78b76b87fceaa838c1", "Atari, Larry Kaplan", "CX26163P", "Air-Sea Battle (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ac18076d01a6b63acf6e2cab4968940", "Atari, Dan Hitchens, Mimi Nyden", "CX2685", "Gravitar (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8af58a9b90b25907da0251ec0facf3b8", "Jone Yuan Telephonic Enterprise Co", "", "Cosmic Swarm (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8b04e9d132b8e30d447acaa6bd049c32", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8b40a9ca1cfcd14822e2547eaa9df5c1", "Parker Brothers - Western Technologies, Dave Hampton, Tom Sloper", "931517", "Q-bert (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8b504b417c8626167a7e02f44229f0e7", "Retroactive", "", "Qb (V1.00) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8b556c3d9ca8e5e6e665bd759b93ffae", "", "", "Synthcart (2002) (Paul Slocum) (PAL) [!]", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8b5b1e3a434ebbdc2c2a49dc68f46360", "CBS Electronics - Woodside Design Associates - Imaginative Systems Software, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8b7ca29a55432f886cee3d452fb00481", "Starpath Corporation, Stephen H. Landrum, Jon Leupp", "11 AR-4201", "Sword of Saros (1983) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8b8152d6081f31365406cb716bd95567", "Atari", "CX2626, CX2626P", "Miniature Golf (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8b8789c6669a4cee86c579a65332f852", "Digivision", "", "Plaque Attack (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8bbfd951c89cc09c148bfabdefa08bec", "UA Limited", "", "Pleiades (1983) (UA Limited) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8bc0d2052b4f259e7a50a7c771b45241", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox) [a]", "AKA Thundarr the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8bd8f65377023bdb7c5fcf46ddda5d31", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8bebac614571135933116045204f0f00", "Thomas Jentzsch", "", "Missile Command (Trakball) (2002) (TJ) (PAL)", "Uses the Trakball Controller", "Homebrew", "", "", "", "", "", "", "", "TRAKBALL", "TRAKBALL", "", "", "", "", "YES", "", "", "", "", "" }, - { "8c103a79b007a2fd5af602334937b4e1", "Thomas Jentzsch", "", "Laser Base (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c136e97c0a4af66da4a249561ed17db", "", "", "Poker Squares (V0.27) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c146c61817edd376bc1354c7f1ddc63", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "8c1cc284edba691139d6626d062c606f", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (PAL60) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "PAL60", "", "", "", "", "", "", "" }, - { "8c2fa33048f055f38358d51eefe417db", "Home Vision - Gem International Corp. - VDI", "VCS83137", "Teddy Apple (1983) (Home Vision) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8c36ed2352801031516695d1eeefe617", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00251", "Winter Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c7e5e2329f4f4e06cbcc994a30fd352", "Data Age", "DA1004", "Airlock (1982) (Data Age) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c8a26ed57870daba8e13162d497bad1", "HES", "", "2 Pak Special - Dolphin, Oink (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c8b15b3259e60757987ed13cdd74d41", "Supergame", "71", "River Raid (1984) (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8c941fa32c7718a10061d8c328909577", "Digivision", "", "River Raid (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ccaa442d26b09139685f5b22bf189c4", "Retroactive", "", "Qb (V1.01) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8ccf63141a029603572d1056e772990e", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8cd26dcf249456fe4aeb8db42d49df74", "Atari - Imagineering, Dan Kichen", "CX26139", "Crossbow (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ce9126066f2ddd5173e9f1f9ce1494e", "Thomas Jentzsch", "", "Missile Command (Trakball) (2002) (TJ)", "Uses the Trakball Controller", "Homebrew", "", "", "", "", "", "", "", "TRAKBALL", "TRAKBALL", "", "", "", "", "YES", "", "", "", "", "" }, - { "8cf0d333bbe85b9549b1e6b1e2390b8d", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8d00a38f4c8f8800f1c237215ac243fc", "", "", "3-D Corridor (Green) (30-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8d1e2a6d2885966e6d86717180938f87", "Thomas Jentzsch", "", "Missile Command (Amiga Mouse) (2002) (TJ)", "Uses Amiga Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8d8b7d7b983f75debbdaac651e814768", "", "", "Demo Image Series #15 - Three Marios (PAL) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8d9a06101ebb0f147936356e645309b8", "", "", "Grid Pattern Demo 2 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8da51e0c4b6b46f7619425119c7d018e", "Atari - Imagineering, David Lubar", "CX26183", "Sentinel (1991) (Atari)", "Uses the Light Gun Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8db152458abaef3cfa7a4e420ddbda59", "", "", "Keystone Kapers (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8df4be9ddc54ac363b13dc57ceaf161a", "Scott Stilphen", "", "Asteroids SS (Scott Stilphen) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8e0ab801b1705a740b476b7f588c6d16", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e42674972d6805068fc653e014370fd", "", "", "Skeleton (PAL) (15-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e48ea6ea53709b98e6f4bd8aa018908", "CBS Electronics, Stuart Ross", "", "Wings (06-03-1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8e4cd60d93fcde8065c1a2b972a26377", "Imagic, Dan Oliver", "720118-2A, 13208, EIX-007-04I", "Laser Gates (1983) (Imagic) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e4fa8c6ad8d8dce0db8c991c166cdaa", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e512ad4506800458f99dec084fc2c64", "Bob Montgomery, Nathan Strum", "", "Reindeer Rescue (2005)", "2005 AtariAge Holiday Cart", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e7241bfc8380aac3c0ef1b6881cdded", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (09-01-81) (Atari) (Prototype)", "Time Freeze", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8e737a88a566cc94bd50174c2d019593", "Quelle", "343.173 1", "Feuerwehr im Einsatz (1983) (Quelle) (PAL)", "AKA Fire Fighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e822b39a71c84ac875f0107fb61d6f0", "", "", "Hangman Ghost Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8e879aa58db41edb67cbf318b77766c4", "Thomas Jentzsch", "", "Cosmic Commuter (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "8e887d1ba5f3a71ae8a0ea16a4af9fc9", "", "", "Skeleton (V1.1) (PAL) (24-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ed5a746c59571feb255eaa7d6d0cf98", "", "", "Carnival (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ed73106e2f42f91447fb90b6f0ea4a4", "Spectravision - Spectravideo", "SA-204", "Tapeworm (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8ee3f64dc0f349adc893fe93df5245d8", "", "", "Euchre (20-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8ef96ace4a1d6dfb65926c1e868b0188", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "8f33bce5ba1053dcf4cea9c1c69981e4", "", "", "Jawbreaker (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f53a3b925f0fd961d9b8c4d46ee6755", "", "", "Astrowar (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f5ac5139419c5d49bacc296e342a247", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (12-22-1982) (Atari) (Prototype)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f60551db6d1535ef0030f155018c738", "", "", "Space War (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f613ea7c32a587d6741790e32872ddd", "", "", "Troll Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f88309afad108936ca70f8b2b084718", "Spectravision - Spectravideo - Quelle", "SA-203 - 413.223 9", "Cross Force (1982) (Spectravision) (PAL)", "AKA Kreuzfeuer (Cross Fire)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f90590dba143d783df5a6cff2000e4d", "", "", "Gopher (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8f98519a91dbbf4864f135a10050d9ed", "Silvio Mogno", "", "Rainbow Invaders (non-playable demo) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8fa47e5242776e841df7e708b12eb998", "", "", "Sea Hawk (Genesis)", "Genesis controller (C drops bomb)", "Hack of Sea Hawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8fbabaa87941cdf3a377c15e95bdb0f3", "", "", "Meteor Smasher (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8fe00172e7fff4c1878dabcf11bb8dce", "Quelle", "689.302 8", "Hili Ball (1983) (Quelle) (PAL)", "AKA Racquetball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "8febdd9142960d084ab6eeb1d3e88969", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "8fffc8f15bb2e6d24e211884a5479aa5", "Retroactive", "", "Qb (V1.00) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9007c3cbb55ce05ad7d1c34d4906750a", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (03-18-1983) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9048ccb7e0802cd8fa5bfc2609f292d8", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (1983) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9057694dce8449521e6164d263702185", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "90578a63441de4520be5324e8f015352", "Bit Corporation", "PGP204", "Open Sesame (4 Game in One) (1983) (BitCorp) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9072c142728a3a3d994956d03bfacba2", "Fabrizio Zavagli", "", "Crash Dive (Fabrizio Zavagli) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "90a3c3255f2a54225cdcb50831f8793a", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "90b1799dddb8bf748ee286d22e609480", "", "", "Ship Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "90b647bfb6b18af35fcf613573ad2eec", "AtariAge (Chris Walton)", "", "Juno First (2009)", "AtariVox supported", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "YES", "", "", "", "", "" }, - { "90ccf4f30a5ad8c801090b388ddd5613", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "90d77e966793754ab4312c47b42900b1", "Imagic, Brad Stewart", "720105-2A, IA3400P, EIX-005-04I", "Fire Fighter (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "90f502cbf4438a95f69f848cef36eb64", "Digitel", "", "River Raid II (1985) (Digitel)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "910dd9bf98cc5bc080943e5128b15bf5", "", "", "Gunfight 2600 - Improved AI (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "911d385ee0805ff5b8f96c5a63da7de5", "Thomas Jentzsch", "", "Jammed (V0.1) (Demo) (2001) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "913d5d959b5021f879033c89797bab5e", "", "", "Robot Player Graphic (1996) (J.V. Matthews) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "914a8feaf6d0a1bbed9eb61d33817679", "Atari", "CX26163P", "Freeway Chicken (32 in 1) (1988) (Atari) (PAL)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91925abce3a29e33b6a8b81482f4f5af", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9193b6fff6897d43274741d4f9855b6d", "", "", "M.A.S.H (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91a3749ff7b7e72b7fa09e05396a0e7b", "", "", "Gunfight 2600 - Final Run Part 2 (2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91b007f33f9b790be64f57220ec52e80", "Jone Yuan Telephonic Enterprise", "", "Laser Blast (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91c2098e88a6b13f977af8c003e0bca5", "Atari - GCC", "CX2676", "Centipede (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91d1c82ceaf8af2add3973a3c34bc0cb", "", "", "Starfield Demo 1 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91f0a708eeb93c133e9672ad2c8e0429", "", "", "Oystron (V2.9) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "91fdb6541f70c40b16aabf8308123be8", "", "", "Interlacing Game (19-08-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9222b25a0875022b412e8da37e7f6887", "Panda", "106", "Dice Puzzle (1983) (Panda)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9245a84e9851565d565cb6c9fac5802b", "Bomb - Onbase", "CA282", "Great Escape (1983) (Bomb)", "AKA Asteroid Fire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "927d422d6335018da469a9a07cd80390", "Activision, Carol Shaw - Ariola", "EAX-020, EAX-020-04B, EAX-020-04I - 711 020-720", "River Raid (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9281eccd7f6ef4b3ebdcfd2204c9763a", "Retroactive", "", "Qb (2.15) (Retroactive) (PAL)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9295570a141cdec18074c55dc7229d08", "Telegames", "7045 A015", "Bump 'n' Jump (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "929e8a84ed50601d9af8c49b0425c7ea", "Bit Corporation", "PG205", "Dancing Plate (1982) (BitCorp) (PAL)", "AKA Dishaster, Dancing Plates, Tanzende Teller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "92a1a605b7ad56d863a56373a866761b", "U.S. Games Corporation - Western Technologies, Dave Hampton", "VC2006", "Raft Rider (1983) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "92d1b6cb8a1b615266c4088a58464779", "Bit Corporation", "R320", "Fishing Derby (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "92d1f6ac179ebe5963868d6bc1bdda8d", "HES", "498", "Smash Hit Pak - Frogger, Boxing, Seaquest, Skiing, Stampede (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "92e72f7cc569584c44c9530d645ae04e", "Canal 3 - Intellivision", "", "Spider Fighter (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "931b91a8ea2d39fe4dca1a23832b591a", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9333172e3c4992ecf548d3ac1f2553eb", "Konami", "RC 101-X 02", "Strategy X (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93420cc4cb1af1f2175c63e52ec18332", "Tim Snider", "", "Blair Witch Project (Tim Snider) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9364ad51c321e0f15c96a8c0aff47ceb", "Atari, Rob Fulop", "CX2638", "Missile Command (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "936ef1d6f8a57b9ff575dc195ee36b80", "", "", "Pac Kong (Unknown)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "936f555b4b1a2cd061b659ff63f4f5f2", "HES, David Lubar", "535", "My Golf (1990) (HES) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "937736d899337036de818391a87271e0", "Atari, Peter C. Niday", "CX26108", "Donald Duck's Speedboat (04-12-1983) (Atari) (Prototype)", "AKA Donald Duck's Regatta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "939ce554f5c0e74cc6e4e62810ec2111", "ZiMAG - Emag - Vidco", "711-111 - GN-020", "Dishaster (1983) (ZiMAG)", "AKA Dancing Plate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "93acd5020ae8eb5673601e2edecbc158", "Chris Cracknell", "", "Video Time Machine (Chris Cracknell)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93b9229fc0ea4fb959d604f83f8f603c", "Thomas Jentzsch", "", "Amidar DS (Fast Enemies) (2003) (TJ) (Hack)", "Hack of Amidar", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93c4b910f7649b3e998bb6d8527c6f4a", "Sparrow - Enter-Tech, Paul Walters, Rick Harris, George Hefner, Barbara Ultis", "", "Arkyology (1983) (Sparrow) (Prototype) [fixed]", "Fix for un-initialized 'X' register", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93c52141d3c4e1b5574d072f1afde6cd", "Imagic, Mark Klein", "720112-1A, 03213", "Subterranea (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93c8d9d24f9c5f1f570694848d087df7", "Digivision", "", "Galaxian (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93c9f9239a4e5c956663dd7affa70da2", "Quelle", "626.610 0", "Billard (1983) (Quelle) (PAL)", "AKA Trick Shot", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "93db185c3b3dc382f3aecd6a2fea7fd9", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "93dc15d15e77a7b23162467f95a5f22d", "CCE", "", "Sky Jinks (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93e276172b521c4491097f8b1393eea7", "Atari", "", "Diagnostic Test Cartridge 4.2 (06-01-1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "93eb1795c8b1065b1b3d62bb9ec0ccdc", "JSK", "", "Custer's Viagra (JSK) (Hack)", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94102febc53b4a78342d11b645342ed4", "", "", "Joustpong (14-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9433770890f087bfcf3e50122694d8c0", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) (Y Inverted) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9436b7ad131b5a1f7753ce4309ba3dee", "Kyle Pittman", "", "War of The Worlds (Kyle Pittman) (Hack)", "Hack of Defender", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "943798452ceba9357e2c56303cadb4f7", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.28)", "", "New Release, supports BoosterGrip and Genesis (switched by Color/B+W)", "", "", "", "", "", "", "", "JOYSTICK", "DRIVING", "", "", "", "", "", "", "", "", "", "" }, - { "9446940866c9417f210f8552cf6c3078", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (PAL60) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "94507dee401b0a072a481c00d7699ffe", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9469d18238345d87768e8965f9f4a6b2", "CCE", "", "Ms. Pac-Man (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "947317a89af38a49c4864d6bdd6a91fb", "CBS Electronics, Bob Curtiss", "4L 2487 5000", "Solar Fox (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94b92a882f6dbaa6993a46e2dcc58402", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94d90f63678e086f6b6d5e1bc6c4c8c2", "Digivision", "", "Seaquest (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94e3fbc19107a169909e274187247a9d", "", "2402-044-01", "2-in-1 Freeway and Tennis (Unknown)", "", "", "", "", "2IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94e4c9b924286038527f49cdc20fda69", "Retroactive", "", "Qb (V2.12) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "94e7cc6342d11e508e7e8b2ddf53c255", "", "", "Missile Command (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "94ff6b7489ed401dcaaf952fece10f67", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-31-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "951e8cec7a1a1d6c01fd649e7ff7743a", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dark Chambers (1988) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9526e3db3bdfbc27989a9cbfd0ee34bf", "", "", "Atari Logo Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "95351b46fa9c45471d852d28b9b4e00b", "Atari, Tom Rudadahl", "CX26163P", "Golf (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "955c408265ad6994f61f9b66657bbae9", "", "", "Quadrun (Video Conversion) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "956496f81775de0b69a116a0d1ad41cc", "CCE", "", "Alien (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "956b99511c0f47b3a11d18e8b7ac8d47", "", "", "Bones (Arcade Golf Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "95956108289a917f80667eccd3ce98a9", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "95a69cf8c08ef1522b050529464f0bca", "", "", "Grid Pattern Demo 1 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "95a89d1bf767d7cc9d0d5093d579ba61", "PlayAround - J.H.M.", "204", "Lady in Wading (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "95e1d834c57cdd525dd0bd6048a57f7b", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "95e542a7467c94b1e4ab24a3ebe907f1", "Suntek", "SS-021", "Dragon Defender (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "95fd6097dc27c20666f039cfe34f7c69", "", "", "Oh No! (Version 1) (17-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "961112b74a920a5242e233480326c356", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "962ffd3eaf865230a7a312b80e6c5cfd", "Imagic, Wilfredo 'Willy' Aguilar, Michael Becker, Rob Fulop", "13205", "Fathom (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "96662271ae50b6859017bffbdda75525", "Andrew Davie & Thomas Jentzsch", "", "Boulder Dash - Demo (2011)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "96670d0bf3610da2afcabd8e21d8eabf", "", "", "Boring Pitfall (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "966b11d3c147d894dd9e4ebb971ea309", "", "", "Marble Craze Song (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "966c955e4aaca7082d9ffb9a68e3f3ed", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9671b658286e276cc4a3d02aa25931d2", "", "", "Hangman Ghost Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "968efc79d500dce52a906870a97358ab", "TNT Games - Sculptured Software, Adam Clayton", "26192", "BMX Air Master (1989) (TNT Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "969b968383d9f0e9d8ffd1056bcaef49", "Atari, Larry Kaplan", "CX2628, CX2628P", "Bowling (1979) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "96bcb3d97ce4ff7586326d183ac338a2", "", "", "Revenge of the Apes (Hack) [h2]", "Hack of Planet of the Apes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "96e798995af6ed9d8601166d4350f276", "20th Century Fox Video Games - Videa, David Ross", "11029", "Meltdown (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "96eccc2277043508a6c481ea432d7dd9", "Thomas Jentzsch", "", "Missile Command (Atari Mouse) (2002) (TJ) (PAL)", "Uses Atari ST Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "ATARIMOUSE", "ATARIMOUSE", "", "", "", "", "YES", "", "", "", "", "" }, - { "96f806fc62005205d851e758d050dfca", "", "", "Push (V0.05) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97184b263722748757cfdc41107ca5c0", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9718b85ac5a55cbc7348963c63ffa35a", "Robby", "", "Demon Attack (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "972486110933623039a3581db308fda6", "", "", "Xeno Plus (Hack)", "Hack of Xenophobe", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97327d6962f8c64e6f926f79cd01c6b9", "", "", "Jawbreaker (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "977294ae6526c31c7f9a166ee00964ad", "Atari - GCC, Douglas B. Macrae", "CX2677, CX2677P", "Dig Dug (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9784290f422e7aeeab4d542318bd9a1f", "AtariAge, Chris Walton", "1.0 (Release)", "Chetiry (2011) (AtariAge) (60k)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, - { "97842fe847e8eb71263d6f92f7e122bd", "Imagic, Wilfredo Aguilar, Michael Becker, Dennis Koble", "720113-1A, 03206", "Solar Storm (1983) (Imagic)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "97933c9f20873446e4c1f8a4da21575f", "", "", "Racquetball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "97a9bb5c3679d67f5c2cd17f30b85d95", "Atari", "", "Colors (1980) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97cd63c483fe3c68b7ce939ab8f7a318", "Thomas Jentzsch", "", "Robot City (V0.21) (15-09-2002) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97d0151beb84acbe82aa6db18cd91b98", "Steve Engelhardt", "", "Lunar Attack (2002) (Steve Engelhardt) (Hack)", "Hack of Z-Tack", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97d079315c09796ff6d95a06e4b70171", "Activision, Garry Kitchen", "AZ-032", "Pressure Cooker (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97e47512f89e79818d988d078dc90410", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (NTSC) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "97f4da9f1031486f4e588f1e53572e53", "SpiceWare - Darrell Spice Jr.", "", "Draconian", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9813b9e4b8a6fd919c86a40c6bda8c93", "Atari", "CX26177", "Ikari Warriors (1989) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9831efc7f4cb8ffb4df0082bab2f07a3", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9848b5ef7a0c02fe808b920a2ac566d2", "Skyworks Technology Inc.", "", "Baseball (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9853089672116117258097dbbdb939b7", "Hozer Video Games", "", "Gunfight 2600 - Cowboy Hair (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98555b95cb38e0e0b22b482b2b60a5b6", "", "", "Spinning Fireball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "98ba601a60172cb46c5bf9a962fd5b1f", "", "", "Gorilla Kong (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98ccd15345b1aee6caf51e05955f0261", "Retroactive", "", "Qb (V2.03) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "98e5e4d5c4dd9a986d30fd62bd2f75ae", "", "", "Air-Sea Battle (Unknown) (Hack) (4K)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98e6e34af45a0664597972c3bb31180f", "", "", "Space Instigators (V1.7) (17-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98e7caaab8ec237558378d2776c66616", "Bradford W. Mott", "", "HMOVE Test (Bradford W. Mott) (1998) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98ea10c47c13f1b3306c7b13db304865", "", "", "Jam Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98ec0fa4199b9c01f7b8fa3732e43372", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98ef1593624b409b9fb83a1c272a0aa7", "CCE", "C-831", "Cosmic Ark (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98f63949e656ff309cefa672146dc1b8", "Atari - Axlon, John Vifian", "CX26168", "Off the Wall (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "98fa3ad778a668a79449350de4b3b95b", "Thomas Jentzsch", "", "Thrust (V1.1) (2000) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9905f9f4706223dadee84f6867ede8e3", "HES", "", "Challenge (HES) (PAL)", "Surfer's Paradise if right difficulty = 'A'", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9912d06eea42200a198dd3e2be18c601", "Imagic, Michael Greene", "IA3312", "No Escape! (1982) (Imagic) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "991d57bbcd529ad62925098e0aec1241", "", "", "Gunfight 2600 - The Final Kernel (MP) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9945a22f60bbaf6d04a8d73b3cf3db75", "Activision, Dan Kitchen", "EAX-039-04B, EAX-039-04I", "Kung-Fu Master (1987) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9947f1ebabb56fd075a96c6d37351efa", "CBS Electronics", "4L 2737 0000", "Omega Race (1983) (CBS Electronics)", "Set right difficulty to 'A' for BoosterGrip in both ports", "", "", "", "", "", "A", "", "", "BOOSTERGRIP", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "" }, - { "9962034ea7b3d4a905d0991804670087", "", "", "Grid Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9989f974c3cf9c641db6c8a70a2a2267", "Eckhard Stolberg", "", "Colours Selector (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "99a24d7bb31d49b720b422550b32c35f", "", "", "Hangman Ghost Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "99ac89241365b692255ba95d745edd91", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (18-03-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "99f7c6c26046bbe95f1c604b25da8360", "SnailSoft", "", "Comitoid beta 2 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9a01115206f32eb0b539c7e5a47ccafa", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (07-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9a165c39af3f050fdee6583fdfcdc9be", "Zirok", "", "Mario Bros. (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9a21fba9ee9794e0fadd7c7eb6be4e12", "Atari - Imagineering, Dan Kitchen", "CX26177", "Ikari Warriors (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9a25b3cfe2bbb847b66a97282200cca2", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, - { "9a4274409216ff09ecde799f2a56ac73", "CCE", "C-801", "Mr. Postman (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ab72d3fd2cc1a0c9adb504502579037", "Epyx, Steven A. Baker, Peter Engelbrite", "80561-00286", "California Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ad362179c2eea4ea115c7640b4b003e", "", "", "Barnstorming (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC50", "", "", "", "", "", "", "" }, - { "9ad36e699ef6f45d9eb6c4cf90475c9f", "Imagic, Dennis Koble", "720103-1A, 720103-1B, IA3203, IX-010-04", "Atlantis (1982) (Imagic)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9aeb5206c5bf974892a9cc59f1478db3", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9af615951e9719df2244bc77fc50cb95", "Dactari - Milmar", "", "Defender (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9afdfe1cff7f37f1c971fe3f0c900606", "Funvision - Fund. International Co.", "", "Plug Attack (Funvision)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9b150a42fc788960fbb4cbe250259ee2", "Kroko", "", "3E Bankswitch Test (TIA @ $40)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9b21d8fc78cc4308990d99a4d906ec52", "CCE", "C-838", "Immies & Aggies (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9b246683f44c963a50e41d6b485bee77", "", "", "Boring (PAL) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9bb136b62521c67ac893213e01dd338f", "Xonox - Beck-Tech", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9bd4e0d5f28ba6da417c26649171f8e4", "", "", "Hangman Pac-Man Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9be58a14e055b0e7581fc4d6c2f6b31d", "", "", "Adventure (Color Scrolling) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9c27ef3bd01c611cdb80182a59463a82", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9c40bf810f761ffc9c1b69c4647a8b84", "", "", "2 in 1 - Frostbite, River Raid (Unknown)", "", "", "", "", "2IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9c6d65bd3b477aace0376f705b354d68", "", "", "RPG Kernal (18-04-2003) (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9c6faa4ff7f2ae549bbcb14f582b70e4", "U.S. Games Corporation, Garry Kitchen, Paul Willson - Vidtec", "VC1002", "Sneak 'n Peek (1982) (U.S. Games)", "AKA Hide 'n Seek", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9c6fd6ed3599978ab7b6f900484b9be6", "Andrew Wallace", "", "Laseresal 2002 (PAL60) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "9c729017dd2f9ccbadcb511187f80e6b", "", "", "J-Pac (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9c7fa3cfcaaafb4e6daf1e2517d43d88", "", "", "PIEROXM Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ca2deb61318eba4fb784d4bf7441d8b", "", "", "Purple Bar Demo 2 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9cbb07f1993a027bc2f87d5205457ec9", "", "", "Eckhard Stolberg's Scrolling Text Demo 1 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d0befa555f003069a21d2f6847ad962", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d1556ae5890398be7e3d57449774b40", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d2938eb2b17bb73e9a79bbc06053506", "Imagic, Michael Greene", "EIZ-002-04I", "Wing War (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d2f05d0fe8b2dfcf770b02eda066fc1", "", "", "Push (V0.06) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d33d31fb1de58c5460d8a67b57b36da", "", "", "Star Voyager (Genesis)", "Genesis controller (C is secondary lasers)", "Hack of Star Voyager", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d37a1be4a6e898026414b8fee2fc826", "M Network - INTV - APh Technological Consulting, David Rolfe", "MT5665", "Super Challenge Baseball (1982) (M Network)", "AKA Big League Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d4bc7c6fe9a7c8c4aa24a237c340adb", "Dennis Debro", "", "Climber 5 (16-04-2003) (Dennis Debro)", "For Philly Classic 4", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d522a3759aa855668e75962c84546f7", "Atari, Tom Rudadahl", "CX2634, CX2634P", "Golf (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9d7f04618bb4043f531d087e3aaa7ac8", "Parker Brothers, Larry Gelberg, Gary Goltz", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL) (16K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9de0d45731f90a0a922ab09228510393", "20th Century Fox Video Games - Sirius, Mark Turmell", "11003", "Fast Eddie (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9dec0be14d899e1aac4337acef5ab94a", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9e01f7f95cb8596765e03b9a36e8e33c", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9e135f5dce61e3435314f5cddb33752f", "Fabrizio Zavagli", "", "Space Treat Deluxe (2003)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9e192601829f5f5c2d3b51f8ae25dbe5", "PlayAround - J.H.M.", "201", "Cathouse Blues (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9e2c7299c69b602443d327c7dad51cbf", "Charles Morgan", "", "Xaxyrax Road (Charles Morgan) (Hack)", "Hack of Freeway", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9e437229136f1c5e6ef4c5f36178ed18", "Funvision - Fund. International Co.", "", "Grand Prize (Funvision)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9e5007131695621d06902ab3c960622a", "Sega", "", "Tac Scan (1983) (Sega) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "YES", "", "", "", "", "" }, - { "9e792a59f8795664cbaaff1ba152d731", "", "", "Bullet Demo (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9e904e2eaa471c050c491289b8b80f60", "", "", "How to Draw a Playfield II (1997) (Erik Mooney) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ea8ed9dec03082973244a080941e58a", "Eric Mooney, Piero Cavina", "", "INV+", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ec1b259a1bcffa63042a3c2b3b90f0a", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9eca521db1959156a115dee85a405194", "", "", "Fu Kung! (V0.08) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9ed0f2aa226c34d4f55f661442e8f22a", "", "", "Nuts (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9eeb40f04a27efb1c68ba1d25e606607", "Kyle Pittman", "", "Rambo II (2003) (Kyle Pittman) (Hack)", "Hack of Double Dragon", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9efa877a98dd5a075e058214da428abb", "Hozer Video Games", "", "SCSIcide (1.32) (Hozer Video Games)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, - { "9efb4e1a15a6cdd286e4bcd7cd94b7b8", "20th Century Fox Video Games, John W.S. Marvin", "", "Planet of the Apes (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9f2d58dce1b81c6ba201ed103507c025", "", "", "Fu Kung! (V0.02) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9f48eeb47836cf145a15771775f0767a", "Atari, Warren Robinett", "CX2620", "Basic Programming (1979) (Atari)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9f5096a6f1a5049df87798eb59707583", "20th Century Fox Video Games, Mark Klein", "11036", "Entity, The (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9f52271759f8a2004d207b2247ae0bb3", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (03-12-84) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9f59eddf9ba91a7d93bce7ee4b7693bc", "Thomas Jentzsch", "", "Montezuma's Revenge (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "9f8fad4badcd7be61bbd2bcaeef3c58f", "Parker Brothers, Charlie Heath", "PB5330", "Reactor (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "9f901509f0474bf9760e6ebd80e629cd", "Atari, Bob Whitehead - Sears", "CX2623 - 6-99819, 49-75108, 49-75125", "Home Run (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9f93734c68f6479eb022cab40814142e", "", "", "Push (V0.07) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9f982421b9b4320ede00fe4aa2e812f4", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "9f9ee0f60c119c831e80694b6678ca1a", "Jeffry Johnston", "", "Radial Pong - Version 8 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9fa0c664b157a0c27d10319dbbca812c", "Chris Walton, Justin Hairgrove, Tony Morse", "", "Hunchy II (2005)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "9fc2d1627dcdd8925f4c042e38eb0bc9", "Atari - GCC, John Allred, Mike Feinstein", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "E68E28752D3C54EDD3CCDA42C27E320C", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox)", "Genesis controller (B is jump and throw, C switches between players)", "Hack of Tomarc the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0028f057d496f22b549fd8deecc6f78", "Joe Grand", "", "SCSIcide Pre-release 6 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a00ec89d22fcc0c1a85bb542ddcb1178", "CCE", "C-1012", "Phoenix (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a00ee0aed5c8979add4c170f5322c706", "Barry Laws Jr.", "", "Egghead (Barry Laws Jr.) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0185c06297b2818f786d11a3f9e42c3", "", "", "International Soccer (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a025a8f83a42a4d6d46c4887e799bfac", "Hozer Video Games", "", "Gunfight 2600 - Descissions had to be made (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0297c4788f9e91d43e522f4c561b4ad", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari) (PAL)", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "a0563dd6d8215c38c488fbbd61435626", "", "", "Ship Demo (V 1501) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0675883f9b09a3595ddd66a6f5d3498", "Telegames - VSS", "6057 A227", "Quest for Quintana Roo (1988) (Telegames)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a075ad332942740c386f4c3814925ece", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (2 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0d502dc8b90b1d7daa5f6effb10d349", "", "", "Demo Image Series #5 - Sam (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a0e2d310e3e98646268200c8f0f08f46", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a100eff2d7ae61ca2b8e65baf7e2aae8", "David Marli", "", "Muncher (David Marli) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a11099b6ec24e4b00b8795744fb12005", "Activision - Bobco, Robert C. Polaro", "EAK-049-04B", "Rampage! (1989) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1403fef01641dcd3980cac9f24d63f9", "Dactari - Milmar", "", "Atlantis (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a14d8a388083c60283e00592b18d4c6c", "", "", "Tunnel Demo (28-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a15b5831a1fab52e4c416068c85ec011", "Hozer Video Games", "", "Gunfight 2600 - The Good, The Bad, The Ugly (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a174cece06b3abc0aec3516913cdf9cc", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (1980) (Sears) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1770ef47146ab7b12e2c4beccd68806", "Digitel", "", "Kaystone Kapers (1983) (Digitel)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a184846d8904396830951217b47d13d9", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a189f280521f4e5224d345efb4e75506", "Atari - Thomas Jentzsch", "", "Obelix (1983) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1bcbe0bfe6570da2661fc4de2f74e8a", "Imagic - Advanced Program Technology, Rob Fulop", "", "Actionauts (Microbots) (1984-2008) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1ca372388b6465a693e4626cc98b865", "Quelle", "176.543 7", "Der Vielfrass (1983) (Quelle) (PAL)", "AKA Fast Food", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1ead9c181d67859aa93c44e40f1709c", "American Videogame - Dunhill Electronics, Darrell Wagner, Todd Clark Holm, John Simonds", "", "Tax Avoiders (1986) (American Videogame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a1f9159121142d42e63e6fb807d337aa", "Quelle - Otto Versand", "700.223 1 - 781627", "Der moderne Ritter (1983) (Quelle) (PAL)", "AKA Fast Eddie", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a204cd4fb1944c86e800120706512a64", "Coleco, Rob Harris", "2511", "Smurfs Save the Day (1983) (Coleco)", "Uses the Kid Vid Controller", "", "", "", "", "", "", "", "", "", "KIDVID", "", "", "", "", "", "", "", "", "", "" }, - { "a20b7abbcdf90fbc29ac0fafa195bd12", "Quelle - Otto Versand", "719.383 2 - 649635, 781393, 781784, 986404", "Motocross (1983) (Quelle) (PAL)", "AKA Motorcross", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a20d931a8fddcd6f6116ed21ff5c4832", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a2170318a8ef4b50a1b1d38567c220d6", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) [a1]", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2276822c772f72073a8a40a72a1ca52", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (NTSC) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2424c1a0c783d7585d701b1c71b5fdc", "", "", "Video Pinball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a25bb76e9e773117e567fd4300b1bb23", "", "", "Interleaved ChronoColour Demo (NTSC) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a28d872fc50fa6b64eb35981d0f4bb8d", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari) (4K)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a29df35557f31dfea2e2ae4609c6ebb7", "Atari", "", "Circus Atari (1980) (Atari) (Joystick)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a29fc854838e08c247553a7d883dd65b", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision) (16K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2a384d3a16d5be50afd12906f146827", "Bit Corporation", "R320", "Flash Gordon (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2aae759e4e76f85c8afec3b86529317", "", "", "Boom Bang (Unknown)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2d7cc2e5419a9e4ab91fdb26339b726", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "a2de0fc85548871279ed2a3c1325c13e", "George Veeder", "", "Cat and Mouse (George Veeder) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2eb84cfeed55acd7fece7fefdc83fbb", "", "", "Kool Aid Man (Fixed) (15-11-2002) (CT)", "HMOVE handling fixed in this version", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2f296ea2d6d4b59979bac5dfbf4edf0", "", "", "Warring Worms (28-01-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a2f9e3b6aaa23b6dc06099cdd5b51b31", "Nukey Shay", "", "Montezuma's Revenge (Genesis) (PAL60) (F6_Conversion)", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "a302b922a8dbec47743f28b7f91d4cd8", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (Preview) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a30ece6dc4787e474fbc4090512838dc", "Zellers", "", "Circus (Zellers)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a310494ad5ba2b5b221a30d7180a0336", "", "", "Demo Image Series #6 - Mario (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a336beac1f0a835614200ecd9c41fd70", "Atari, Christopher H. Omarzu, Robert Vieira", "CX26121", "Zoo Keeper Sounds (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a34560841e0878c7b14cc65f79f6967d", "Multivision, Michael Case", "", "Harem (1982) (Multivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3486c0b8110d9d4b1db5d8a280723c6", "Atari, Alan J. Murphy, Robert C. Polaro", "CX26100", "Bugs Bunny (08-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a35d47898b2b16ec641d1dfa8a45c2b7", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3873d7c544af459f40d58dfcfb78887", "", "", "Tennis (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3b9d2be822eab07e7f4b10593fb5eaa", "", "", "GREGXM Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3c1c70024d7aabb41381adbfb6d3b25", "Telesys, Alex Leavens", "1005", "Stargunner (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3d7c299fbcd7b637898ee0fdcfc47fc", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (Preview) (1982) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "a3f2a0fcf74bbc5fa763b0ee979b05b1", "Quelle", "873.790 0", "Eishockey-Fieber (1983) (Quelle) (PAL)", "AKA Ice Hockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3f8aebb38182749cb8da85cfbc63d7c", "", "", "Tennis (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a3fee8ce15525ea00d45a06f04c215d1", "Aaron Curtis", "", "AStar (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "a406d2f6d84e61d842f4cb13b2b1cfa7", "Tigervision, John Harris - Teldec", "7-002", "Jawbreaker (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a412c8577b2d57b09185ae51739ac54f", "Arcadia Corporation, Dennis Caswell", "AR-4000", "Phaser Patrol (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a41450333f8dd0e96e5e9f0af3770ae9", "", "", "Basic Math (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a422194290c64ef9d444da9d6a207807", "M Network - APh Technological Consulting, Hal Finney", "MT5667", "Dark Cavern (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a428068d3e51498907d97cec40000515", "Bit Corporation", "R320", "Sky Alien (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a47878a760f5fa3aa99f95c3fdc70a0b", "", "", "Demo Image Series #5 - Baboon (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4790224bd5afabd53cbe93e46a7f241", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a47e26096de6f6487bf5dd2d1cced294", "Atari", "CX2643", "Codebreaker (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a484638990de7b12c62947c79dafa4c6", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (PAL60) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "a499d720e7ee35c62424de882a3351b6", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "009-01", "Up 'n Down (1984) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4aa7630e4c0ad7ebb9837d2d81de801", "", "", "Atari 2600 Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4ab331e8768eafdc20ce8b0411ff77a", "", "", "Demo Image Series #1 - Sam (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4b9423877a0b86ca35b52ca3c994ac5", "CCE", "C-805", "Sea Monster (1983) (CCE)", "O Monstro Marinho", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4b99aa5ed85cfdb7d101923147de035", "Jim Goebel", "", "Pac-Law (Jim Goebel) (Hack)", "Hack of Outlaw", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4c08c4994eb9d24fb78be1793e82e26", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4d026a5c200ef98518ebb77719fe8dc", "Kyle Pittman", "", "SpongeBob SquarePants (2003) (Kyle Pittman) (Hack)", "Hack of Revenge of the Beefsteak Tomatoes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4e885726af9d97b12bb5a36792eab63", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4ecb54f877cd94515527b11e698608c", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (12-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4f1cea2c8479284e2a2292f8d51b5fa", "", "", "Gunfight 2600 - The Final Kernel Part 2 (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a4ff39d513b993159911efe01ac12eba", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (1983) (Atari)", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a511f7ee13e4b35512f9217a677b4028", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a5262fe6d01d6a1253692682a47f79dd", "", "", "JKH Text Scrolling Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a537879d8e82e1061d3ad800479d3b84", "Andrew Wallace", "", "Brooni (2001) (Andrew Wallace) (PD) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a539b9fd1ba57e46442b3e9351e6383b", "", "", "River Raid (208 in 1) (Unknown) (PAL) (Hack) [a]", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a56b642a3d3ab9bbeee63cd44eb73216", "Carrere Video - JWDA, Sylvia Day, Todd Marshall, Robin McDaniel, Henry Will IV - Teldec - Prism", "USC2001", "Gopher (1983) (Carrere Video) (PAL)", "AKA Vossicht Whlmaus!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a5855d73d304d83ef07dde03e379619f", "Atari, David Crane", "", "Boggle (08-07-1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a58b11148c18d85e4c2aef4ff46ade67", "", "", "Video Chess (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a591b5e8587aae0d984a0f6fe2cc7d1c", "", "", "Globe Trotter Demo (24-03-2003) (Weston)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a5b7f420ca6cc1384da0fed523920d8e", "", "", "Adventure (New Graphics) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a5c96b046d5f8b7c96daaa12f925bef8", "Activision, Alan Miller - Ariola", "EAG-007, EAG-007-04I, PAG-007 - 711 007-720", "Tennis (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a5e9ed3033fb2836e80aa7a420376788", "Atari, Carla Meninsky", "CX2637, CX2637P", "Dodge 'Em (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a60598ad7ee9c5ccad42d5b0df1570a1", "Atari, Alan Miller", "CX26163P", "Surround (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a6127f470306eed359d85eb4a9cf3c96", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a6239810564638de7e4c54e66b3014e4", "Personal Games Company, Robert Anthony Tokar", "", "Birthday Mania (1984) (Personal Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a62e3e19280ff958407e05ca0a2d5ec7", "", "", "Hangman Ghost Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a6737c81542a99ee71cb5f5ff14703d9", "", "", "Scrolling Playfield 3 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a69f5b1761a8a11c98e706ec7204937f", "", "", "Pharaoh's Curse (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a6ed8d72ed691fd3aad5b6974fa17978", "Bit Corporation", "R320", "Bank Heist (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a74689a08746a667a299b0507e1e6dd9", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (1983) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7523db9a33e9417637be0e71fa4377c", "Videospielkassette - Ariola", "PGP238", "Gangster (Ariola) (PAL)", "AKA Outlaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7673809068062106db8e9d10b56a5b3", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118, CX26118P", "Millipede (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a779b9fa02c62d00d7c31ed51268f18a", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7a58e9291aefa1064e933071f60d4ef", "Arcadia Corporation, Dennis Caswell", "1 AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a7b584937911d60c120677fe0d47f36f", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5661", "Armor Ambush (1982) (M Network)", "AKA Tank Battle", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7b96a8150600b3e800a4689c3ec60a2", "Atari, Mike Lorenzen - Sears", "CX2630 - 49-75122", "Circus Atari (1980) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, - { "a7bf8353f77caca407ef85c2698fdff2", "Atari, Suki Lee - Sears", "CX2658 - 49-75128", "Math Gran Prix (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7cf2b9afdbb3a161bf418dbcf0321dc", "Barry Laws Jr.", "", "Attack Of The Mutant Space Urchins (2002) (Barry Laws Jr.) (Hack)", "Hack of Alien", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a7d2e9408bb7cd70139ecced407ff238", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a1]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7ed7dc5cbc901388afa59030fb11d26", "Atari, Warren Robinett", "CX2606, CX2606P", "Slot Racers (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a7ef44ccb5b9000caf02df3e6da71a92", "Atari, Ian Shepard - Sears", "CX2604 - 6-99812, 49-75106", "Space War (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8101cb667e50a46165c6fb48c608b6b", "", "", "Kung Fu Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a81697b0c8bbc338ae4d0046ede0646b", "CCE", "", "Gravitar (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a81b29177f258494b499fbac69789cef", "Greg Thompson", "", "Console Wars (Greg Thompson) (Hack)", "Hack of Space Jockey", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a83b070b485cf1fb4d5a48da153fdf1a", "Apollo", "AP-2011", "Pompeii (1983) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8435ec570141de5d833c4abec499e55", "", "", "Happy Birthday Demo (2001) (Dennis Debro) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8633050a686270fcf6c0cc4dcbad630", "Zirok", "", "Phoenix (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a867b76098786c4091dba2fcee5084c3", "", "", "Dragrace (Hack)", "Hack of Dragster", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a875f0a919129b4f1b5103ddd200d2fe", "Atari, Dan Hitchens. Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) (PAL)", "AKA Adventure I, SwordQuest I - EarthWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8916734ff8c64ec3342f4c73fd5b57d", "Atari", "", "Stand Alone Test Cart (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a89a3e0547d6887279c34aba4b17a560", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (1983) (Mattel) (Prototype)", "", "Prototype", "", "", "4K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8a703e073183a89c94d4d99b9661b7f", "Franklin Cruz", "", "Spice Invaders (Franklin Cruz) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8b3ea6836b99bea77c8f603cf1ea187", "CCE", "C-861", "Boxing (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8c48b4e0bf35fe97cc84fdd2c507f78", "Puzzy - Bit Corporation", "PG201", "Seamonster (1982) (Puzzy)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8d0a4a77cd71ac601bd71df5a060e4c", "", "", "Space Shuttle (1983) (Activision) [t2] (Fuel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8d4a9500b18b0a067a1f272f869e094", "", "", "Red And White Checkerboard Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a8e49d7e24ce293629ca29614862821b", "", "", "Enduro (Genesis)", "Genesis controller (B is acceleration, C is brakes)", "Hack of Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a91d0858a52de3a2e6468437212d93e8", "", "", "Q-bert (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a936d80083e99d48752ad15c2b5f7c96", "", "", "Room of Doom (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a93e8ea1f565c3c1e86b708cf0dc2fa9", "Jess Ragan", "", "Kabul! (Jess Ragan) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "a94528ae05dd051894e945d4d2349b3b", "Genus", "", "River Raid (Genus)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a94b8ca630f467b574b614808d813919", "HES", "773-883", "2 Pak Special - Space Voyage, Fire Alert (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a9531c763077464307086ec9a1fd057d", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a957dbe7d85ea89133346ad56fbda03f", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "a97733b0852ee3096300102cb0689175", "CCE", "C-834", "Fast Eddie (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a9784c24cddb33bd0d14442b97784f3d", "Thomas Jentzsch", "", "Omega Race DC (2003) (TJ) (Omega Race Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a98b649912b6ca19eaf5c2d2faf38562", "", "", "This Planet Sucks (Greg Troutman) (PAL) [!]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a995b6cbdb1f0433abc74050808590e6", "Imagic, Rob Fulop, Bob Smith", "720106-1A, IA3600", "Riddle of the Sphinx (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a9cb638cd2cb2e8e0643d7a67db4281c", "M Network - INTV - APh Technological Consulting, Larry Zwick", "MT5861", "Air Raiders (1983) (M Network)", "AKA Air Battle", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "a9d9e19d0c89fb31780b5d63e1f8c6a4", "AtariAge, Chris Spry", "CX26201", "Zippy the Porcupine (2014) (Sprybug) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "a9e3c23599c0d77151602f8e31daf879", "", "", "Kung Fu Master (Genesis)", "Genesis controller (C is extra kick modes)", "Hack of Kung Fu Master", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "aa1c41f86ec44c0a44eb64c332ce08af", "Spectravideo, David Lubar", "SA-218", "Bumper Bash (1983) (Spectravideo)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "PADDLES", "", "", "", "", "", "", "", "", "", "", "" }, - { "aa2c4b32656bde9a75042a4d158583e1", "", "", "Oystron X (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aa5cfe3b20395aba1d479135943ad85c", "", "", "Defender (Hack) (Unknown)", "", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aa7bb54d2c189a31bb1fa20099e42859", "CBS Electronics, Ed English", "4L4478", "Mr. Do! (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "aa8c75d6f99548309949916ad6cf33bc", "Bob Montgomery (aka vdub_bobby)", "", "Squish 'Em (2007)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aa8e4b2cb8a78ffe6b20580033f4dec9", "", "", "Bitmap Demo (13-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aaac0d277eda054861e613c59c2e4ff2", "JWDA, Todd Marshall", "", "Music Demo (JWDA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aab840db22075aa0f6a6b83a597f8890", "Home Vision, R.J.P.G. - Gem International Corp. - VDI", "VCS83124", "Racing Car (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aad61898633f470ce528e3d7ef3d0adb", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a1]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aad91be0bf78d33d29758876d999848a", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1981) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aaea37b65db9e492798f0105a6915e96", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Tug of War (2 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "02", "", "", "", "", "", "", "", "" }, - { "aafc79ffc32c4c9b2d73c8ada7602cfe", "", "", "Planet Patrol (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab10f2974dee73dab4579f0cab35fca6", "ITT Family Games", "", "Wilma Wanderer (1983) (ITT Family Games) (PAL)", "AKA Lilly Adventure", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab2cfcaad3daaf673b2b14fdbb8dac33", "M Network - INTV, David Akers, Joe King, Patricia Lewis Du Long, Jeff Ratcliff", "MT7045", "Bump 'n' Jump (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab2ea35dcc1098c87455bb8210b018cf", "", "", "Fu Kung! (V0.04 Single Line Resolution) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab301d3d7f2f4fe3fdd8a3540b7a74f5", "Jone Yuan Telephonic Enterprise Co", "", "IQ 180 (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab434f4c942d6472e75d5490cc4dd128", "HES", "773-875", "2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab48c4af46c8b34c3613d210e1206132", "Andrew Davie & Thomas Jentzsch", "", "Boulder Dash - Demo V2 (2014)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab4ac994865fb16ebb85738316309457", "Atari, Alan Miller - Sears", "CX2624 - 6-99826, 49-75113", "Basketball (1978) (Atari)", "Console ports are swapped", "Common", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab56f1b2542a05bebc4fbccfc4803a38", "Activision - Imagineering, Dan Kitchen, David Lubar", "AK-048-04", "River Raid II (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab5bf1ef5e463ad1cbb11b6a33797228", "Imagic, Rob Fulop", "720104-1A, 720104-1B, IA3204", "Cosmic Ark (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab60ea7b707c58d356cad858eb18db43", "", "", "Tazer (John K. Harvey)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ab8d318da4addd39c65b7f9c408df2a6", "", "", "Star Trek (Genesis)", "Genesis controller (B is phaser, C is warp)", "Hack of Star Trek", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "abb740bea0a6842831b4f53112fb8145", "", "", "Qb (V1.01) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "abb741c83f665d73c86d90a7d9292a9b", "Telegames", "", "Space Attack (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "abc64037ca5d5b04ae8a7eedbca3ed74", "", "", "Green and Yellow Number 1 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "abe40542e4ff2d1c51aa2bb033f09984", "Absolute Entertainment, David Crane", "EAZ-042-04B, EAZ-042-04I", "Skate Boardin' (1987) (Absolute) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac05c0e53a5e7009ddd75ed4b99949fc", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac0ddbcff34d064009591607746e33b8", "Thomas Jentzsch", "", "Atlantis FH (2003) (TJ) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac26d7d37248d1d8eac5eccacdbef8db", "", "", "Snail Against Squirrel (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac3dd22dd945724be705ddd2785487c2", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (06-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac53b83e1b57a601eeae9d3ce1b4a458", "Retroactive", "", "Qb (2.15) (Retroactive) (NTSC)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ac5f78bae0638cf3f2a0c8d07eb4df69", "", "", "Minesweeper (V.99) (Soren Gust) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac7c2260378975614192ca2bc3d20e0b", "Activision, David Crane", "AG-930-04, AZ-030", "Decathlon (1983) (Activision)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ac9adbd6de786a242e19d4bec527982b", "Activision, Alan Miller - Ariola", "EAG-012-04I, EAX-012, EAX-012-04B - 711 012-720", "Ice Hockey (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aca09ffea77174b148b96b205109db4d", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "acaa27d214039d89d7031609aafa55c3", "", "", "Sprite Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "acb6787b938079f4e74313a905ec3ceb", "", "", "Chronocolor Donkey Kong (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "acb7750b4d0c4bd34969802a7deb2990", "Parker Brothers, Ed Temple", "PB5310", "Amidar (1982) (Parker Bros)", "", "Uncommon", "", "", "", "A", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "acb962473185d7a652f90ed6591ae13b", "Imagic, Dennis Koble", "IA3203, IX-010-04", "Atlantis (1982) (Imagic) (16K)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ace319dc4f76548659876741a6690d57", "Atari, Steve Wright", "CX2616", "Pele's Soccer (1981) (Atari)", "AKA Pele's Championship Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ad2e6bfb3b9b9b36ba8bf493ce764c49", "", "", "2600 Collison Demo 1 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ad42e3ca3144e2159e26be123471bffc", "Atari", "CX26163P", "Human Cannonball (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ad72d616030a17634ff29ce8680d3c4c", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "ad7e97c19bd25d5aa3999430845c755b", "", "", "Sprite Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ad8072675109d13fdd31a2e0403d5cff", "Funvision - Fund. International Co.", "", "Tank City (Funvision)", "AKA Thunderground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "adb770ff70e9adf08bbb907a7eccd240", "", "", "Inv Demo 3 (2001) (Erik Mooney) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "adb79f9ac1a633cdd44954e2eac14774", "Digivision", "", "Frostbite (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "adf1afac3bdd7b36d2eda5949f1a0fa3", "Quelle - Otto Versand", "495.463 2 - 746381", "Angriff der Luftflotten (1983) (Quelle) (PAL)", "AKA Paris Attack, M.A.D.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "adfbd2e8a38f96e03751717f7422851d", "Champ Games", "CG-01-N", "Lady Bug (NTSC)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ae047e9468bda961d8e9e9d8ff52980f", "", "", "Tunnel Demo (Red Spiral) (30-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae0d4f3396cb49de0fabdff03cb2756f", "Retroactive", "", "Qb (V2.02) (PAL) (2001) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ae10527840a1ac24de43730645ed508d", "Charles Morgan", "", "Planet Invaders (Charles Morgan) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae18c11e4d7ed2437f0bf5d167c0e96c", "", "", "Multi-Color Demo 3 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae2f1f69bb38355395c1c75c81acc644", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-23-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ae465044dfba287d344ba468820995d7", "", "", "Inca Gold (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae4be3a36b285c1a1dff202157e2155d", "Spectravideo", "SA-210", "Master Builder (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae682886058cd6981c4b8e93e7b019cf", "Retroactive", "", "Qb (V0.12) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ae6cb335470788b94beb5787976e8818", "", "", "Mortal Kurling (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae83541cf4a4c0bce0adccd2c1bf6288", "", "", "Maze 003 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ae97cf8ed21f4154b4360a3cf6c95c5e", "", "", "Teleterm 2600 (John K. Harvey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aeb104f1e7b166bc0cbaca0a968fde51", "", "", "Ms. Pac-Man (1999) (Hack)", "Hack of Ms. Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aec9b885d0e8b24e871925630884095c", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype)", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aed0b7bd64cc384f85fdea33e28daf3b", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666", "RealSports Volleyball (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "aed82052f7589df05a3f417bb4e45f0c", "Atari, Warren Robinett - Sears", "CX2606 - 6-99825, 49-75112", "Slot Racers (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "af6ab88d3d7c7417db2b3b3c70b0da0a", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "af6f3e9718bccfcd8afb421f96561a34", "Atari, Tod Frye", "CX2695", "Xevious (01-18-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "afb3bc45c6a82739cc82582127cd96e6", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dungeon (11-22-1985) (Atari) (Prototype)", "Dark Chambers Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "afc194534c1b346609ef05eff6d3cef6", "Jone Yuan Telephonic Enterprise Co", "", "Boxing (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "afd2cf258d51ae4965ee21abba3627ab", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (12-08-1982) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "" }, - { "afe4eefc7d885c277fc0649507fbcd84", "Atari", "CX26163P", "Ant Party (32 in 1) (1988) (Atari) (PAL)", "AKA Cosmic Swarm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "afe776db50e3378cd6f29c7cdd79104a", "Thomas Jentzsch", "", "Bobby is Going Home (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "afe88aae81d99e0947c0cfb687b16251", "Apollo - Games by Apollo", "AP-2006", "Infiltrate (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "aff8cba0f2d2eb239953dd7116894a08", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (3 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b00088418fc891f3faa3d4ddde6ace94", "", "", "Unknown Title (bin00007 (200102)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b00a8bc9d7fe7080980a514005cbad13", "K-Tel Vision", "", "Vulture Attack (1982) (K-Tel Vision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b00e8217633e870bf39d948662a52aac", "Konami", "RC 102-X 02", "Marine Wars (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b011d8fdc450597c0762c2c0010a9b17", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b049fc8ac50be7c2f28418817979c637", "Activision - Imagineering, Dan Kitchen, David Lubar", "EAK-048-04, EAK-048-04B", "River Raid II (1988) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b06050f686c6b857d0df1b79fea47bb4", "Activision", "AIZ-001", "Moonsweeper (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b061e98a4c854a672aadefa233236e51", "Atari, Warren Robinett", "CX2620, CX2620P", "Basic Programming (1979) (Atari) (PAL)", "Uses Keypad Controllers", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b095009004df341386d22b2a3fae3c81", "", "", "Sub-Scan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b09b79c9628878be051e89f7f1e77378", "Activision, Larry Kaplan, David Crane - Ariola", "EAG-010, PAG-010 - 711 010-720", "Kaboom! (1981) (Activision) (PAL) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "b0a9c6f6c8014c4023e0341ba11ca35e", "The Atari 2600 Connection - John K. Harvey, Tim Duarte", "v75", "Mean Santa (2009) (PAL)", "Released in 2019", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b0ba51723b9330797985808db598fc31", "Atari, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b0c47e426c7f799aee2c40422df8f56a", "", "", "Space Treat (PAL) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b0c9cf89a6d4e612524f4fd48b5bb562", "Atari - GCC", "CX2663", "Combat Two (1982) (Atari) (Prototype)", "AKA Super Combat", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b0e1ee07fbc73493eac5651a52f90f00", "Colin Hughes", "", "Tetris 2600 (Colin Hughes)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b1276417fb0f79bc52e741bb8f4d8360", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (NTSC) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b129d7541cff79ebe33852a83057c524", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (NTSC) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b12a7f63787a6bb08e683837a8ed3f18", "Imagic, Rob Fulop", "720000-200, 720101-1B, 720101-1C, IA3200, IA3200C, IX-006-04", "Demon Attack (1982) (Imagic) [fixed]", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1339c56a9ea63122232fe4328373ac5", "Goliath - Hot Shot", "83-215", "Dream Flight (1983) (Goliath) (PAL)", "AKA Nightmare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1486e12de717013376447ac6f7f3a80", "Spectravideo, Mark Turmell, Quelle", "SA-217, SA-217C - 413.723 8", "Gas Hog - Piraten Schiff (1983) (Spectravideo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b15026b43c6758609667468434766dd8", "Retroactive", "", "Qb (0.06) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b16cd9784589219391c839cb68c47b9c", "Video Soft, Jerry Lawson, Dan McElroy", "", "Golf Diagnostic (1983) (Video Soft) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b17b9cc4103844dcda54f77f44acc93a", "Quelle", "377.943 6", "Stopp die Gangster (1983) (Quelle) (PAL)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b182d9708e00709830caab9cf8205ca0", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "b1a6c96e9093352106bc335e96caa154", "Joe Grand", "", "SCSIcide Pre-release 1 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1b20536aef4eed9c79dc5804f077862", "", "", "Euchre (NTSC) (09-11-2001) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1c14b5ac896400cc91c8e5dd67acb59", "", "", "River Raid (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1d1e083dc9e7d9a5dc1627869d2ade7", "CCE", "C-1004", "Mario's Bros. (1983) (CCE)", "AKA Mario Bros.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b1e2d5dc1353af6d56cd2fe7cfe75254", "Atari - Axlon, Steve DeFrisco", "CX26171", "MotoRodeo (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b1fd0b71de9f6eeb5143a97963674cb6", "", "", "Multi-Color Demo 7 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b227175699e372b8fe10ce243ad6dda5", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [a1]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b23ebf427713dd0198b7ef47dbd07ef4", "Jone Yuan Telephonic Enterprise Co", "", "Sky Diver (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b24f6a5820a4b7763a3d547e3e07441d", "CCE", "C-823", "Demon Attack (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b25841173f058380b1771aacd5e7cdf3", "Bit Corporation", "PG205", "Dancing Plate (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b26506fbf411009e5e3f7365f442960e", "Atari, Alan Miller", "CX2642", "Hunt & Score (1978) (Atari) (PAL) (4K)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2737034f974535f5c0c6431ab8caf73", "CBS Electronics, Richard K. Balaska Jr., Andy Frank, Stuart Ross", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2761efb8a11fc59b00a3b9d78022ad6", "Atari, Bob Whitehead - Sears", "CX2651 - 99805, 49-75602", "Blackjack (1977) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "b290c2b139344fcff5b312c71b9ac3b2", "Atari", "CX26163P", "UFO (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b29359f7de62fed6e6ad4c948f699df8", "Goliath", "3", "Phantom Tank (1983) (Goliath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2a6f31636b699aeda900f07152bab6e", "", "", "Space Instigators (Public Release 2) (06-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2ab209976354ad4a0e1676fc1fe5a82", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a3]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2d1e63f7f22864096b7b6c154151d55", "Fabrizio Zavagli", "", "Bounce! (17-03-2003) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b2d3bcee001cff2bd2d8a21b2cb55109", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (08-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b2d5d200f0af8485413fad957828582a", "Atari - Bobco, Robert C. Polaro", "CX26155P", "Sprint Master (1988) (Atari) (PAL)", "AKA Sprint 88, Sprint 2000", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b2f0d7217147160b2f481954cedf814b", "", "", "Marquee Drawer (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b3017e397f74efd53caf8fae0a38e3fe", "Retroactive", "", "Qb (2.12) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b311ab95e85bc0162308390728a7361d", "Parker Brothers - Roklan, Joe Gaucher", "PB5080", "Gyruss (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b31dc989f594764eacfa7931cead0050", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (2 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b31e9487efc06f18dfc3d7ebadf54416", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) v4 (PAL60) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "b31f178aa0d569cccac7959f84e0a724", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (07-13-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b3203e383b435f7e43f9492893c7469f", "Gameworld", "133-003", "Sssnake (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b36040a2f9ecafa73d835d804a572dbf", "Digitel", "", "Pac Man (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b37f0fe822b92ca8f5e330bf62d56ea9", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b392964e8b1c9c2bed12246f228011b2", "", "", "Name This Game (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b4030c38a720dd84b84178b6ce1fc749", "M Network - APh Technological Consulting, Kevin Miller", "MT5687", "International Soccer (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b40dea357d41c5408546e4e4d5f27779", "Digivision", "", "Spider Fighter (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b41fdd4a522e1d5a2721840028684ac2", "", "", "Green and Yellow Number 1 Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b42df8d92e3118dc594cecd575f515d7", "Mystique - American Multiple Industries", "1003", "Burning Desire (1982) (Mystique) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b438a6aa9d4b9b8f0b2ddb51323b21e4", "Telegames", "5861 A030", "Bogey Blaster (1988) (Telegames) (PAL)", "AKA Air Raiders", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b451307b8b5e29f1c5f2cf064f6c7227", "", "", "Demo Image Series #6 - Mario (Fixed) (26-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b49331b237c8f11d5f36fe2054a7b92b", "", "", "Condor Attack (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b4a4c87840613f102acb5b3a647d0a67", "", "", "Mobile 48 Sprite Kernel (04-01-2003) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b4daedb43511521db9036d503b3c1b69", "", "", "Sokoban (01-01-2003) (Adam Wozniak) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b4e2fd27d3180f0f4eb1065afc0d7fc9", "Avalon Hill, Jean Baer, Bill 'Rebecca Ann' Heineman, William O. Sheppard", "5002002", "London Blitz (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b4f05e544834d0238a0c263491775edf", "Starpath Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (Preview) (1982) (Starpath) (PAL)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b4f31ea8a6cc9f1fd4d5585a87c3b487", "Mystique - American Multiple Industries, Joel H. Martin", "", "Beat 'Em & Eat 'Em (1982) (Mystique) (PAL)", "Uses the Paddle Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "b4f87ce75f7329c18301a2505fe59cd3", "Videospielkassett - Ariola", "PGP232", "Autorennen (Ariola) (PAL)", "AKA Grand Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b50ae55aac93fbed258bc5a873edd2cb", "Recompile", "", "E.T. The Extra-Terrestrial (Recompile) (Hack)", "www.neocomputer.org/projects/et", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b5110f55ed99d5279f18266d001a8cd5", "Eckhard Stolberg", "", "Auto-mobile Demo (2001) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b56264f738b2eb2c8f7cf5a2a75e5fdc", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694, CX2694P", "Pole Position (1983) (Atari) (PAL)", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b5657d4c1c732fbb6af150668464247f", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b59417d083b0be2d49a7d93769880a4b", "Pet Boat", "", "Donkey Kong (1983) (Pet Boat) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b59fd465abf76f64c85652ff29d5952d", "VentureVision, Dan Oliver", "", "Innerspace (1983) (VentureVision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b5a1a189601a785bdb2f02a424080412", "Imagic, Dennis Koble", "720021-1A, IA3410", "Shootin' Gallery (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b5cb9cf6e668ea3f4cc2be00ea70ec3c", "CommaVid, Irwin Gaines - Ariola", "CM-005 - 712 005-720", "Mines of Minos (1982) (CommaVid) (PAL)", "AKA Im Labyrinth des Roboters", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b5cdbab514ea726a14383cff6db40e26", "Video Gems", "VG-04", "Mission Survive (1983) (Video Gems) (PAL) [a]", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b5efe0271d2214e4d5dc798881486884", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (06-14-1990) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b6166f15720fdf192932f1f76df5b65d", "Amiga - Video Soft", "3130", "Off Your Rocker (1983) (Amiga) (Prototype)", "Uses the Amiga Joyboard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b64426e787f04ff23ee629182c168603", "Dynacom", "", "Plaque Attack (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b65d4a38d6047735824ee99684f3515e", "Dynacom", "", "MegaBoy (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b676a9b7094e0345a76ef027091d916b", "Thomas Jentzsch", "", "Mission Survive (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b6812eaf87127f043e78f91f2028f9f4", "Simage", "", "Eli's Ladder (1984) (Simage)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b6821ac51c4c1dcb283f01be2f047dc1", "Thomas Jentzsch", "", "Rubik's Cube 3D Demo (25-11-2002) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b6960be26bee87d53ba4e2e71cfe772f", "", "", "3-D Corridor (Spiral Words) (31-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b6d52a0cf53ad4216feb04147301f87d", "Imagic, Michael Greene", "720055-1A, IA3312", "No Escape! (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b6e40bce550672e5495a8cdde7075b8b", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b702641d698c60bcdc922dbd8c9dd49c", "Atari, Ian Shepard", "CX26163P", "Space War (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b719ada17771a8d206c7976553825139", "Ron Corcoran", "", "DUP Space Invaders (Ron Corcoran) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b731d35e4ac6b3b47eba5dd0991f452f", "Thomas Jentzsch", "", "Rubik's Cube 3D Demo (Final) (08-01-2003) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b7345220a0c587f3b0c47af33ebe533c", "Quelle", "176.433 1", "Landungskommando (1983) (Quelle) (PAL)", "AKA Strategy X", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b76fbadc8ffb1f83e2ca08b6fb4d6c9f", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b77468d586957d1b7fb4cccda2684f47", "Atari", "CX26163P", "Boxing (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b7903268e235310dc346a164af4c7022", "Thomas Jentzsch", "", "Cat Trax (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "b79fe32320388a197ac3a0b932cc2189", "Imagic, Bob Smith", "13207, EIZ-001-04I", "Moonsweeper (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b7a7e34e304e4b7bc565ec01ba33ea27", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b7b1d3ce07e75976c43a2dca3866237e", "Atari", "CX26163P", "Freeway Chicken (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b7d0aae399781b3c18679debda6d32b1", "Thomas Jentzsch", "", "Three.s (v1.02)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b7d7c76e37f372f4e4979b380ed95a58", "AtariAge - Michael Haas", "RC2", "Flappy (2014) (AtariAge) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "b7e459d5416eeb196aaa8e092db14463", "", "", "Push (V0.02) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b7f184013991823fc02a6557341d2a7a", "", "", "Blue Rod Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b80d50ecee73919a507498d0a4d922ae", "20th Century Fox Video Games - Sirius Software, David Lubar", "11008", "Fantastic Voyage (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b816296311019ab69a21cb9e9e235d12", "Atari, Bob Whitehead - Sears", "CX2652 - 6-99816, 49-75151", "Casino (1979) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "b822fba8b7c8a97ea4e92aeb2c455ef9", "Dactari", "", "Freeway (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b83579c4450fcbdf2b108903731fa734", "", "", "Mission 3,000 A.D. (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b83df1f32b4539c324bdf94851b4db55", "Angelino", "", "One On One by Angelino (Basketball Hack)", "Hack of Basketball (1978) (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b86552198f52cfce721bafb496363099", "Apollo, Tim Martin", "AP-2007", "Kyphus (1982) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b86a12e53ab107b6caedd4e0272aa034", "Funvision - Fund. International Co.", "", "Treasure Hunting (Funvision)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b879e13fd99382e09bcaf1d87ad84add", "Zellers", "", "Time Warp (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b8865f05676e64f3bec72b9defdacfa7", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b897f9e3f939b9f21566d56db812a84e", "Atari, Jim Huether", "CX26163P", "Flag Capture (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b8e715223ba65cf716b3620a90ca3ec1", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b8ed78afdb1e6cfe44ef6e3428789d5f", "Data Age, J. Ray Dettling", "112-007", "Bermuda Triangle (1983) (Data Age)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b9232c1de494875efe1858fc8390616d", "Panda", "110", "Harbor Escape (1983) (Panda)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b9336ed6d94a5cc81a16483b0a946a73", "Atari, Jerome Domurat, Michael Sierchio", "CX2667, CX2667P", "RealSports Soccer (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "b955eb0e2baf7a437c186bddd4c49958", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (PAL60) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "b958d5fd9574c5cf9ece4b9421c28ecd", "Piero Cavina", "", "Multi-Sprite Game V1.0 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b95a6274ca0e0c773bfdc06b4c3daa42", "Paul Slocum", "", "3-D Corridor (29-03-2003) (Paul Slocum)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b98cc2c6f7a0f05176f74f0f62c45488", "Spectravideo", "SV-010", "CompuMate (1983) (Spectravideo)", "", "", "", "", "CM", "", "", "", "", "COMPUMATE", "COMPUMATE", "", "", "", "", "YES", "", "", "", "", "" }, - { "b9b4612358a0b2c1b4d66bb146767306", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b9d1e3be30b131324482345959aed5e5", "Activision - Boston Design Center, Rex Bradford", "", "Kabobber (07-25-1983) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "b9f6fa399b8cd386c235983ec45e4355", "Parker Brothers, John Emerson", "931511", "Action Force (1983) (Parker Bros) (PAL)", "AKA G.I. Joe - Cobra Strike", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, - { "b9f9c0fed0db08c34346317f3957a945", "SuperVision", "405, 427, 806, 808, 813, 816", "Chopper Command (SuperVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ba257438f8a78862a9e014d831143690", "U.S. Games Corporation - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "VC2002", "Squeeze Box (1983) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ba317f83cdfcd58cbc65aac1ccb87bc5", "Thomas Jentzsch", "", "Jammed (2001) (XYPE) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ba3a17efd26db8b4f09c0cf7afdf84d1", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ba3b0eebccc7b791107de5b4abb671b4", "Thomas Jentzsch", "", "Thrust (V0.9) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ba657d940a11e807ff314bba2c8b389b", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bac28d06dfc03d3d2f4a7c13383e84ee", "Supergame", "", "Demon Attack (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bae1a23f9b6acdadf465cfb330ba0acb", "Atari - GCC, Doug Macrae", "CX2677", "Dig Dug (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bae66907c3200bc63592efe5a9a69dbb", "Spectravision - Spectravideo - Quelle", "SA-201 - 412.783 3", "Gangster Alley (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "baf4ce885aa281fd31711da9b9795485", "Atari, Douglas Neubauer", "CX26176", "Radar Lock (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb18189021d58362d9e4d317cd2e28b7", "Activision, David Crane - Ariola", "EAG-001, PAG-001, EAG-001-04B, EAG-001-04I - 711 001-715", "Dragster (1980) (Activision) (PAL) (4K)", "AKA Dragster Rennen", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb2b83fff97604f74ada565e0b5bae94", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (PAL60) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "bb5049e4558daade0f87fed69a244c59", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [no copyright]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "bb579404924c40ca378b4aff6ccf302d", "", "", "Lightbulb Lightens, The (PD) (Non Functional)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb6a5a2f7b67bee5d1f237f62f1e643f", "", "", "Demo Image Series #5 - Animegirl (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb745c893999b0efc96ea9029e3c62ca", "Play Video", "", "Planet Patrol (1982) (Play Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb756aa98b847dddc8fc170bc79f92b2", "", "", "Golf (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bb9112d478a1a922d2c289a752bba695", "Omegamatrix", "", "SpaceMaster X-7 (Amiga Mouse) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bbf8c7c9ed280151934aabe138e41ba7", "Amiga", "1130", "Power Play Arcade Video Game Album V (1984) (Amiga) (Prototype)", "Mogul Maniac, Surf's Up, Off Your Rocker, S.A.C. Alert", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc24440b59092559a1ec26055fd1270e", "", "", "Private Eye (1984) (Activision) [a]", "", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc3057a35319aae3a5cd87a203736abe", "CCE", "C-845", "Time Warp (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc33c685e6ffced83abe7a43f30df7f9", "Dynacom", "", "Seaquest (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc4cf38a4bee45752dc466c98ed7ad09", "Atari, Douglas Neubauer, Mimi Nyden", "CX26136", "Solaris (1986) (Atari) (PAL)", "AKA Universe, Star Raiders II, The Last Starfighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc526185ad324241782dc68ba5d0540b", "", "", "Dodge Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc5389839857612cfabeb810ba7effdc", "Atari, Tod Frye", "CX2671", "SwordQuest - WaterWorld (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc703ea6afb20bc089f04d8c9d79a2bd", "", "", "Gunfight 2600 - Not mergeable with Colbert wizardry... (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bc97d544f1d4834cc72bcc92a37b8c1b", "", "", "Sky Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bcb31f22856b0028c00d12f0e4c0a952", "Canal 3 - Intellivision", "", "Thunderground (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bcb73b534ed7c613ac379ecd726effb5", "Bob Montgomery (aka vdub_bobby)", "", "Squish 'Em (2007) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "bccb4e2cfad5efc93f6d55dc992118ce", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bce4c291d0007f16997faa5c4db0a6b8", "Quelle", "292.651 7", "Weltraumtunnel (1983) (Quelle) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bce93984b920e9b56cf24064f740fe78", "Atari", "CX26163P", "Checkers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bcef7880828a391cf6b50d5a6dcef719", "Rainbow Vision - Suntek", "SS-009", "Bermuda, The (1983) (Rainbow Vision) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bd1bd6f6b928df17a702def0302f46f4", "", "", "Binary To Decimal Routine (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bd39598f067a1193ae81bd6182e756d1", "Telegames", "", "Night Stalker (1988) (Telegames) (PAL)", "AKA Dark Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bd430c2193045c68d1a20a018a976248", "", "", "Pac Ghost Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bd551ff1264f5c367a3ad7cf0d2f266c", "Bit Corporation", "R320", "SpaceMaster X-7 (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bda1463e02ae3a6e1107ffe1b572efd2", "Atari, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bdb4b584ddc90c9d2ec7e21632a236b6", "Atari Freak 1", "", "Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack)", "Hack of Pac-Man Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bdbaeff1f7132358ea64c7be9e46c1ac", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11105", "Mega Force (1982) (20th Century Fox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bdc381baf7c252c63739c5e9ed087a5c", "", "", "Vertical Ship Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bdecc81f740200780db04a107c3a1eba", "Quelle", "874.254 6", "Super-Cowboy beim Rodeo (1983) (Quelle) (PAL)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bdf1996e2dd64baf8eff5511811ca6ca", "Tron", "", "H.E.R.O. (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be060a704803446c02e6f039ab12eb91", "Parker Brothers, Rex Bradford, Sam Kjellman", "931501", "Star Wars - The Empire Strikes Back (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be1922bd8e09d74da471287e1e968653", "Cropsy", "", "Hangman Pacman Demo (Cropsy) (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be2870a0120fd28d25284e9ccdcbdc99", "", "", "Tomb Raider 2600 [REV 01] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be35d8b37bbc03848a5f020662a99909", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be3f0e827e2f748819dac2a22d6ac823", "Puzzy - Bit Corporation", "PG202", "Space Tunnel (1982) (Puzzy)", "AKA Le Tunnel de L'Estace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be41463cd918daef107d249f8cde3409", "", "", "Berzerk (Voice Enhanced) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be561b286b6432cac71bccbae68002f7", "", "", "Counter Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "be929419902e21bd7830a7a7d746195d", "Activision, Garry Kitchen", "AX-025, AX-025-04", "Keystone Kapers (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "becd908f9d7bb361982c3dc02d6475c6", "Kyle Pittman", "", "THX-1138 (Kyle Pittman) (Hack)", "Hack of Berserk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bedfbde71fb606601f936b5b057f26f7", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "befce0de2012b24fd6cb8b53c17c8271", "", "", "Push (V0.03) (No Illegal Opcodes) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bf1970b692275b42c4ec0683588eb062", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bf52327c2197d9d2c4544be053caded1", "HES - Activision", "AG-930-04, AZ-030", "Decathlon (HES) (PAL) (16K)", "AKA Activision Decathlon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bf84f528de44225dd733c0e6a8e400a0", "CCE", "", "Demons to Diamonds (CCE)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "10 57", "", "", "", "", "", "", "", "" }, - { "bf976cf80bcf52c5f164c1d45f2b316b", "Atari, Tod Frye, Mimi Nyden", "CX2657", "SwordQuest - FireWorld (1982) (Atari) (PAL)", "AKA Adventure II, SwordQuest II - FireWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bfa58198c6b9cd8062ee76a2b38e9b33", "", "", "20 Sprites at Once Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bfb73aabb2489316cd5882c3cd11d9f9", "AtariAge, Chris Walton & Thomas Jentzsch", "165", "Star Castle Arcade (2014) (AtariAge)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "bff8f8f53a8aeb1ee804004ccbb08313", "", "", "Droid Demo 22 (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "bffe34516aaa3cbf5d307eab382a7e95", "", "", "Euchre (Release Candidate) (PAL) (28-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c00734a2233ef683d9b6e622ac97a5c8", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26133", "A-Team, The (03-30-1984) (Atari) (Prototype)", "AKA Saboteur", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c00b65d1bae0aef6a1b5652c9c2156a1", "Atari, Joe Decuir - Sears", "CX2621 - 99806, 6-99806, 49-75104", "Video Olympics (1977) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "c02e1afa0671e438fd526055c556d231", "Atari", "", "A-Team (Atari) (Prototype) (PAL60)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "c032c2bd7017fdfbba9a105ec50f800e", "Activision, Charlie Heath", "", "Thwocker (04-09-1984) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c033dc1d7b6fde41b9cadce9638909bb", "", "", "Skeleton (V1.1) (06-09-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c0589bb73858924389077fa3c2e9441a", "SOLID Corp. (D. Scott Williamson)", "CX2655-014", "Star Castle 2600 (SolidCorp) [014]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c05f367fa4767ceb27abadf0066df7f4", "Thomas Jentzsch", "", "TomInv (31-07-2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c08d0cee43077d3055febb00e5745c1d", "HES - Activision", "", "Super Hit Pak - River Raid, Sky Jinks, Grand Prix, Fishing Derby, Checkers (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c0a68837c60e15d1fc5a40c9a62894bc", "Arcadia Corporation, Kevin Norman", "7 AR-4103", "Killer Satellites (1983) (Arcadia) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c0c7eddefce9015346db88ade3e1e096", "CBS Electronics, Bob Curtiss", "4L 2487 5000", "Solar Fox (1983) (CBS Electronics) (Prototype) (4K)", "RAM must be zero'ed to start correctly", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c0d2434348de72fa6edcc6d8e40f28d7", "SEGA - Beck-Tech, Steve Beck", "010-01", "Tapper (1984) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1034a5bfb0bb13cc5bdf86cc58989a7", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c118854d670289a8b5d5156aa74b0c49", "Jone Yuan Telephonic Enterprise Co", "", "Skiing (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c11e8473c652619ac6166900150ce215", "AtariAge, Chris Walton", "1.0 (Release)", "Chetiry (2011) (AtariAge) (60k) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, - { "c126656df6badfa519cc63e681fb3596", "Ron Corcoran", "", "Space Invaders (2002) (Ron Corcoran) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c15042e54c7408498f051d782aaa8945", "Omegamatrix", "", "Millipede (Atari Trak-Ball) v6.5 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c150c76cbde2c9b5a97eb5399d46c64f", "", "", "Unknown Title (xxx00000 (200203)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c16c79aad6272baffb8aae9a7fff0864", "U.S. Games Corporation - JWDA, Sylvia Day, Todd Marshall, Robin McDaniel, Henry Will IV", "VC2001", "Gopher (1982) (U.S. Games)", "AKA Gopher Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c16fbfdbfdf5590cc8179e4b0f5f5aeb", "", "", "Wall Break (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c17bdc7d14a36e10837d039f43ee5fa3", "Spectravision - Spectravideo", "SA-203", "Cross Force (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1a83f44137ea914b495fc6ac036c493", "Atari, Carla Meninsky", "CX2660", "Star Raiders (1982) (Atari) (PAL)", "Uses Joystick (left) and Keypad (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1b038ce5cb6d85e956c5509b0e0d0d8", "", "", "Rotating Colors Demo 2 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1b1049b88bcd98437d8872d1d62ba31", "", "", "Demo Image Series #4 - Donald (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1b7aeabc3ec41556d924c8372a9ba5b", "Atari, Robert C. Polaro", "", "Dukes of Hazard (1980) (Atari) (Prototype)", "AKA Stunt Cycle", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1cb228470a87beb5f36e90ac745da26", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1e6e4e7ef5f146388a090f1c469a2fa", "Bomb - Onbase", "CA283", "Z-Tack (1983) (Bomb)", "AKA Base Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1f209d80f0624dada5866ce05dd3399", "Telegames", "", "Deadly Discs (1988) (Telegames) (PAL)", "AKA TRON - Deadly Discs", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c1fdd44efda916414be3527a47752c75", "Parker Brothers, John Emerson", "PB5920", "G.I. Joe - Cobra Strike (1983) (Parker Bros)", "Uses the Paddle (left) and Joystick (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c20f15282a1aa8724d70c117e5c9709e", "Video Gems", "VG-02", "Surfer's Paradise (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c21450c21efb7715746e9fa87ad6f145", "Hozer Video Games", "", "Gunfight 2600 - It could've been soooo cool, but... (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c216b91f5db21a093ded6a5aaec85709", "Jone Yuan Telephonic Enterprise Co", "", "Dragster (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c221607529cabc93450ef25dbac6e8d2", "Eckhard Stolberg", "", "Color Test (26-09-2002) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c225379e7c4fb6f886ef9c8c522275b4", "Video Mania", "", "Frostbite (1983) (Video Mania)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c225abfb584960efe1f359fc94b73379", "", "", "Joustpong (21-09-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2410d03820e0ff0a449fa6170f51211", "", "", "Pac-Man (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c246e05b52f68ab2e9aee40f278cd158", "Thomas Jentzsch", "", "Star Wars - Ewok Adventure (Thomas Jentzsch) (Prototype)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2778507b83d9540e9be5713758ff945", "", "", "Island Flyer Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c28b29764c2338b0cf95537cc9aad8c9", "", "", "Multi-Color Demo 4 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c29d17eef6b0784db4586c12cb5fd454", "Jone Yuan Telephonic Enterprise Co", "", "River Raid (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c29f8db680990cb45ef7fef6ab57a2c2", "Parker Brothers - Roklan, Paul Crowley, Bob Curtiss", "931505", "Super Cobra (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2a37f1c7603c5fd97df47d6c562abfa", "Roger Williams", "", "Bar-Score Demo (2001) (Roger Williams)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2b5c50ccb59816867036d7cf730bf75", "Salu - Avantgarde Software, Michael Buetepage", "460741", "Ghostbusters II (1992) (Salu) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c2bcd8f2378c3779067f3a551f662bb7", "Activision, Bob Whitehead - Ariola", "EAG-002, EAG-002-04I, PAG-002 - 711 002-715", "Boxing (1980) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2c7a11717e255593e54d0acaf653ee5", "", "", "Chopper Command (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2c8eb642765137bb82b83a65232961f", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (PAL) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2dea467f4a02fa1f06d66f52bc12e6e", "Thomas Jentzsch", "", "Missile Command Atari Trak-Ball Hack v1.3 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c2fbef02b6eea37d8df3e91107f89950", "Champ Games", "CG-02-N", "Conquest Of Mars (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c31a17942d162b80962cb1f7571cd1d5", "Home Vision - Gem International Corp. - VDI", "VCS83112", "Sky Alien (1983) (Home Vision) (PAL)", "AKA Sky Aliem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3205e3707f646e1a106e09c5c49c1bf", "", "", "Unknown Title (bin00003 (200206)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3472fa98c3b452fa2fd37d1c219fb6f", "Atari, Carla Meninsky - Sears", "CX2637 - 49-75158", "Dodge 'Em (1980) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c370c3268ad95b3266d6e36ff23d1f0c", "Atari, Alan Miller", "CX2641, CX2641P", "Surround (1977) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3a9550f6345f4c25b372c42dc865703", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3aeb796fdaf9429e8cd6af6346f337e", "", "", "If It's Not One Thing It's Another (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3bbc673acf2701b5275e85d9372facf", "Atari, Robert C. Polaro", "CX26157", "Stunt Cycle (07-21-1980) (Atari) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3e4aa718f46291311f1cce53e6ccd79", "", "", "Hangman Ghost 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3ef5c4653212088eda54dc91d787870", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c3f53993ade534b0982ca3a286c85bb5", "", "", "Full Screen Bitmap Drawing System (12-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c4060a31d61ba857e756430a0a15ed2e", "Thomas Jentzsch", "", "Pick 'n Pile (2003) (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c41e7735f6701dd50e84ee71d3ed1d8f", "Dynacom", "", "Spider Fighter (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c43bd363e1f128e73ba5f0380b6fd7e3", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c446288fe62c0c2737639fd788ae4a21", "", "", "Mark's Sound Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c450a285daa7a3b65188c2c3cf04fb3e", "Wizard Video Games", "007", "Halloween (1983) (Wizard Video Games) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c469151655e333793472777052013f4f", "", "", "Base Attack (Unknown) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c471b97446a85304bbac021c57c2cb49", "First Star Software, Alex Leavens, Shirley Ann Russell", "", "Boing! (1983) (First Star Software) (PAL)", "AKA Bubbles, Soap Suds, The Emphysema Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c47244f5557ae12c61e8e01c140e2173", "Atari - GCC, Mike Feinstein, John Allred", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c47b7389e76974fd0de3f088fea35576", "Funvision - Fund. International Co.", "", "Mighty Mouse (Funvision)", "AKA Gopher", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c482f8eebd45e0b8d479d9b71dd72bb8", "Retroactive", "", "Push (V0.03) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c49fe437800ad7fd9302f3a90a38fb7d", "Atari, Dan Hitchens, Mimi Nyden", "CX2697, CX2697P", "Mario Bros. (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c4b73c35bc2f54b66cd786f55b668a82", "Arcadia Corporation, Stephen Harland Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c4bbbb0c8fe203cbd3be2e318e55bcc0", "", "", "Atlantis (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c4bc8c2e130d76346ebf8eb544991b46", "Imagic", "", "Imagic Selector ROM (1982) (Imagic) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c4d888bcf532e7c9c5fdeafbb145266a", "", "", "Space Robot (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c504a71c411a601d1fc3173369cfdca4", "Retroactive", "", "Qb (V2.02) (Stella) (2001) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c5124e7d7a8c768e5a18bde8b54aeb1d", "Imagic, Rob Fulop", "720104-2A, IA3204P, EIX-008-04I", "Cosmic Ark (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c517144e3d3ac5c06f2f682ebf212dd7", "Tigervision - Teldec", "7-008 - 3.60006 VG", "Miner 2049er (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c529e63013698064149b9e0468afd941", "", "", "S.I.PLIX 2 (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "c52d9bbdc5530e1ef8e8ba7be692b01e", "Atari, Robert C. Polaro", "CX26130", "Holey Moley (02-29-1984) (Atari) (Prototype)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5301f549d0722049bb0add6b10d1e09", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "c5387fc1aa71f11d2fa82459e189a5f0", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp) (PAL)", "AKA Weltraum-Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c53c0d10c74325deae9ba84074281983", "The Atari 2600 Connection - John K. Harvey, Tim Duarte", "v75", "Mean Santa (2009)", "Released in 2019", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c541a5f6fc23b40a211196dd78233780", "Atari, Carla Meninsky - Sears", "CX2660 - 49-75187", "Star Raiders (1981) (Atari) (Prototype) (4K)", "Uses Joystick (left) and Keypad (right) Controllers", "Prototype", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "c54b4207ce1d4bf72fadbb1a805d4a39", "Billy Eno", "", "Sniper (Feb 30) (2001) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c560a3ecb7b751021953819efcfe5b41", "Omegamatrix", "", "Ghostbusters (Genesis)", "Genesis controller", "", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "c569e57dca93d3bee115a49923057fd7", "", "", "Pac-Space (Pac-Man Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c58708c09ccb61625cda9d15ddcd8be6", "SPIKE the Percussionist", "", "NOIZ Invaders (SPIKE) (2002) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5930d0e8cdae3e037349bfa08e871be", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c59633dbebd926c150fb6d30b0576405", "Telegames", "5861 A030", "Bogey Blaster (1988) (Telegames)", "AKA Air Raiders", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5a76bafc4676edb76e0126fb9f0fb2d", "Charles Morgan", "", "Zero Patrol (Charles Morgan) (Hack)", "Hack of Moon Patrol", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5bab953ac13dbb2cba03cd0684fb125", "SpiceWare - Darrell Spice Jr.", "", "Stay Frosty (SpiceWare)", "Part of Stella's Stocking 2007 Xmas compilation", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c5bf03028b2e8f4950ec8835c6811d47", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a2]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5c7cc66febf2d4e743b4459de7ed868", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1983) (Atari) (PAL) [a]", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5d2834bf98e90245e545573eb7e6bbc", "CCE", "", "Snoopy and the Red Baron (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5dd8399257d8862f3952be75c23e0eb", "Atari - GCC", "CX2680", "RealSports Tennis (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5f71dfbdca9cc96b28643ff4d06aa6f", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c5fe45f2734afd47e27ca3b04a90213c", "Atari, Brad Stewart", "CX2622, CX2622P", "Breakout (1978) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "c63a98ca404aa5ee9fcff1de488c3f43", "Atari", "CX26145", "Venture (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c6556e082aac04260596b4045bc122de", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6688781f4ab844852f4e3352772289b", "Atari, Tod Frye", "CX2695", "Xevious (08-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c67ff409f28f44883bd5251cea79727d", "", "", "Gunfight 2600 - Music & Bugfixes 1 (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c689148ad9275667924ab334107b517e", "Jone Yuan Telephonic Enterprise Co", "", "Space Raid (Jone Yuan)", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c68a6bafb667bad2f6d020f879be1d11", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6ae21caceaad734987cb24243793bd5", "CCE", "", "Frostbite (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6c63da3bc2e47291f63280e057061d0", "128-in-1 Junior Console", "", "Human Cannonball (128-in-1 Junior Console) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6d48c6ae6461e0e82753540a985ac9e", "Ed Federmeyer", "", "Edtris (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6d7fe7a46dc46f962fe8413c6f53fc9", "Parker Brothers, Mark Lesser", "PB5950", "Lord of the Rings (1983) (Parker Bros) (Prototype) [a]", "Journey to Rivendell (The Lord of the Rings I)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c6db733e0b108c2580a1d65211f06dbf", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (07-09-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c738fc3f5aae1e8f86f7249f6c82ac81", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) (16K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, - { "c73ae5ba5a0a3f3ac77f0a9e14770e73", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c745487828a1a6a743488ecebc55ad44", "Rainbow Vision - Suntek", "SS-002", "Galactic (1983) (Rainbow Vision) (PAL)", "AKA The Challenge of.... Nexar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c74bfd02c7f1877bbe712c1da5c4c194", "Thomas Jentzsch", "", "River Raid Tanks (Thomas Jentzsch) (Hack)", "Hack of River Raid", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7600d72247c5dfa1ec1a88d23e6c85e", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (1 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c77c35a6fc3c0f12bf9e8bae48cba54b", "Xonox - K-Tel Software - Action Graphics, Michael Schwartz, David Thiel", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c77d3b47f2293e69419b92522c6f6647", "Panda", "101", "Tank Brigade (1983) (Panda)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7900a7fe95a47eef3b325072ad2c232", "Larry Petit", "", "Super Congo Bongo (2003) (Larry Petit) (Hack)", "Hack of Bongo", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7d5819b26b480a49eb26aeb63cc831e", "Bit Corporation", "PGP210", "Ice Hockey (4 Game in One Light Green) (1983) (BitCorp) (PAL)", "AKA Hockey, Hockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7e43ad79c5e5c029d9f5ffde23e32cf", "", "", "PAL-NTSC Detector (15-11-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7eab66576696e11e3c11ffff92e13cc", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c7f13ef38f61ee2367ada94fdcc6d206", "Parker Brothers - Roklan, Joe Gaucher", "PB5370", "Popeye (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c82ec00335cbb4b74494aecf31608fa1", "CCE", "", "E.T. - The Extra-Terrestrial (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c830f6ae7ee58bcc2a6712fb33e92d55", "Atari, Michael Kosaka", "CX2687", "Tempest (01-05-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c866c995c0d2ca7d017fef0fc0c2e268", "Retroactive", "", "Qb (2.00) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c880c659cdc0f84c4a66bc818f89618e", "Thomas Jentzsch", "", "Open Sesame (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c89c3138a99fd1fd54367d65f75b0244", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (PAL) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c8c7da12f087e8d16d3e6a21b371a5d3", "", "", "Demo Image Series #9 - Genius (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c8e90fc944596718c84c82b55139b065", "Atari - Roklan, Bob Curtiss", "", "Firefox (1983) (Atari) (Prototype) [a]", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c8fa5d69d9e555eb16068ef87b1c9c45", "Atari", "CX26144", "Donkey Kong Junior (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c90788d9aa71a78bcc78c015edb22c54", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (PAL60) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "c9196e28367e46f8a55e04c27743148f", "Atari", "CX26163P", "Stampede (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c92cfa54b5d022637fdcbdc1ef640d82", "Retroactive", "", "Qb (V2.05) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "c98e8c918a40b4d3a243dd6c49196330", "AtariAge, Omegamatrix", "", "Venture Reloaded (2019) (AtariAge) (PAL60) (Hack)", "Transformative hack of Venture", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "c9b7afad3bfd922e006a6bfc1d4f3fe7", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c9c25fc536de9a7cdc5b9a916c459110", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c9d02d3cfeef8b48fb71cb4520a4aa84", "", "", "Euchre (More for less) (PAL) (22-08-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c9e721eb29c940c2e743485b044c0a3f", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "c9f6e521a49a2d15dac56b6ddb3fb4c7", "Parker Brothers, Rex Bradford", "PB5000", "Star Wars - Jedi Arena (1983) (Parker Bros)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "10 50", "", "", "", "", "", "", "", "" }, - { "ca09fa7406b7d2aea10d969b6fc90195", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ca4f8c5b4d6fb9d608bb96bc7ebd26c7", "M Network - INTV - APh Technological Consulting, Hal Finney, Glenn Hightower, Peter Kaminski", "MT4317", "Adventures of TRON (1983) (M Network)", "AKA Tron Joystick", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ca50cc4b21b0155255e066fcd6396331", "Suntek", "SS-031", "UFO Patrol (1983) (Suntek) (PAL)", "AKA X'Mission", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ca53fc8fd8b3c4a7df89ac86b222eba0", "CCE", "C-812", "Pac Man (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ca54de69f7cdf4d7996e86f347129892", "PlayAround - J.H.M.", "201", "Philly Flasher (1982) (PlayAround)", "Uses the Paddle Controllers, AKA Beat 'Em & Eat 'Em", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, - { "ca7aaebd861a9ef47967d31c5a6c4555", "Atari, Bob Whitehead", "CX26163P", "Homerun (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ca7abc774a2fa95014688bc0849eee47", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ca7f166a94eed1a349dec6d6a358bcad", "Activision, Alan Miller - Ariola", "EAG-007, EAG-007-04I, PAG-007 - 711 007-720", "Tennis (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cac9928a84e1001817b223f0cecaa3f2", "Amiga - Video Soft, Jerry Lawson, Dan McElroy", "", "3-D Genesis (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cad982c9b45bc5eff34e4ea982d5f1ca", "", "", "Song (17-02-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cade123747426df69570a2bc871d3baf", "Gakken", "011", "Marine Wars (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cae8f83c06831ec7bb6a3c07e98e9342", "Colin Hughes", "", "Tetris 2600 (Colin Hughes) [o1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cb18d8d5fbdcb1cd7bd36c5423348859", "", "", "RAM-Pong (NTSC) v1.0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cb24210dc86d92df97b38cf2a51782da", "Video Gems", "VG-01", "Missile Control (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cb4a7b507372c24f8b9390d22d54a918", "ITT Family Games", "554-37 338", "Peter Penguin (1983) (ITT Family Games) (PAL)", "AKA Frisco (Pumuckl-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cb8399dc0d409ff1f531ef86b3b34953", "", "", "Demo Image Series #12 - Luigi And Mario (01-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cb9626517b440f099c0b6b27ca65142c", "Atari, Larry Kaplan - Sears", "CX2664 - 6-99818", "Brain Games (1978) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "cb96b0cf90ab7777a2f6f05e8ad3f694", "Silvio Mogno", "", "Rainbow Invaders", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cb9b2e9806a7fbab3d819cfe15f0f05a", "Parker Brothers - JWDA, Todd Marshall, Robin McDaniel, Ray Miller", "931513", "Star Wars - Death Star Battle (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cba56e939252b05df7b7de87307d12ca", "", "", "Playfield Text Demo (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cbad928e10aeee848786cc55394fb692", "", "", "Fu Kung! (V0.06a Cuttle Cart Compatible) (15-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cbb0ee17c1308148823cc6da85bff25c", "", "", "Rotating Colors Demo 1 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cbc373fbcb1653b4c56bfabba33ea50d", "CCE", "", "Super Voleyball (CCE)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cbced209dd0575a27212d3eee6aee3bc", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cbd981a23c592fb9ab979223bb368cd5", "Atari, Carla Meninsky - Sears", "CX2660 - 49-75187", "Star Raiders (1982) (Atari)", "Uses Joystick (left) and Keypad (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cbe5a166550a8129a5e6d374901dffad", "Atari, Carla Meninsky - Sears", "CX2610 - 49-75127", "Warlords (1981) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, - { "cbeafd37f15e0dddb0540dbe15c545a4", "", "", "Black and White Fast Scolling Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc03c68b8348b62331964d7a3dbec381", "Jone Yuan Telephonic Enterprise Co", "", "Marauder (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc12581e079cd18330a89902625b8347", "Dave Neuman", "", "Space Battle (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc1939e4769d0c157ace326efcfdcf80", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (3 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc2973680c150886cce1ed8693c3aca2", "Quelle", "874.254 6", "Super-Cowboy beim Rodeo (1983) (Quelle) (PAL) (4K)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc3d942c6958bd16b1c602623f59e6e1", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc7138202cd8f6776212ebfc3a820ecc", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (03-30-1983) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "cc724ebe74a109e39c0b2784ddc980ca", "Atari, Jerome Domurat, Dave Staugas", "CX2682", "Krull (05-27-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cc74ddb45d7bc4d04c2e6f1907416699", "", "", "Colour Display Programme (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cca33ae30a58f39e3fc5d80f94dc0362", "", "", "Okie Dokie (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ccb56107ff0492232065b85493daa635", "Bit Corporation", "PG206 [demonstration cartridge]", "Bobby Is Going Home (1983) (BitCorp) (PAL) [demo cart]", "AKA Bobby geht Heim", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ccb5fa954fb76f09caae9a8c66462190", "Answer Software Corporation - TY Associates, Mike Wentz", "ASC1001", "Malagai (1983) (Answer Software)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ccb807eb79b0ed0f5fdc460445ef703a", "", "", "Superman (Stunt_Cycle_Rules!) (Hack)", "Hack of Superman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ccbd36746ed4525821a8083b0d6d2c2c", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [no copyright]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cccfe9e9a11b1dad04beba46eefb7351", "", "", "Poker Squares (V0.25) (PAL) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ccd6ce508eee4b3fca67212833edcd85", "Otto Versand", "746422", "Hot Wave (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Ram It", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ccd92a269a4c2bd64d58cf2c0114423c", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (09-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd032ab6764b55438a7b0bfb5e78595a", "", "", "Hangman Pac-Man 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd139ae6d09f3665ad09eb79da3f9e49", "Eric Mooney", "", "Invaders by Erik Mooney (4-24-97) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd34b3b3ef9e485201e841ba71beb253", "Bradford W. Mott", "", "Hit HMOVE At Various Cycles After WSYNC Test (Bradford W. Mott) (1998) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd38ad19f51b1048d8e5e99c86a2a655", "", "", "Demo Image Series #5 - Flag (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd399bc422992a361ba932cc50f48b65", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (Preview) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd3e26786136a4692fd2cb2dfbc1927e", "", "", "Multiple Moving Objects Demo 2 (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd4423bd9f0763409bae9111f888f7c2", "Jone Yuan Telephonic Enterprise Co", "", "River Raid (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd4ded1ede63c4dd09f3dd01bda7458c", "Future Video Games", "", "Laser Gate (Future Video Games) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd568d6acb2f14477ebf7e59fb382292", "Videospielkassette - Ariola", "PGP235", "Fussball (Ariola) (PAL)", "AKA International Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd5af682685cfecbc25a983e16b9d833", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26133", "A-Team, The (05-08-1984) (Atari) (Prototype)", "AKA Saboteur", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd88ef1736497288c4533bcca339f881", "SEGA - Teldec", "005-10", "Buck Rogers - Planet of Zoom (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL", "", "YES", "", "", "", "", "" }, - { "cd8fa2e9f6255ef3d3b9b5a4f24a54f7", "", "", "Daredevil (V2) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cd98be8a48ebf610c9609a688b9c57f2", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Arcadia) (Prototype)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cd9fea12051e414a6dfe17052067da8e", "Paul Slocum", "", "Marble Craze Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cda38714267978b9a8b0b24bee3529ae", "", "", "Space Instigators (V1.6) (17-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cdadb57b34438805ee322ff05bd3d43e", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "cdb81bf33d830ee4ee0606ee99e84dba", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "cdc1a5c61d7488eadc9aba36166b253d", "Retroactive", "", "Qb (V0.12) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cddabfd68363a76cd30bee4e8094c646", "Computer Magic - CommaVid, John Bronstein", "CM-001", "MagiCard (1981) (CommaVid)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce17325834bf8b0a0d0d8de08478d436", "", "", "Boring Freeway (Hack)", "Hack of Freeway", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce1cbe159b9ae5992dacf09371de5e13", "Atari - GCC, Kevin Osborn", "CX2689", "Kangaroo (01-19-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce243747bf34a2de366f846b3f4ca772", "Home Vision - Gem International Corp. - VDI", "", "Jacky Jump (1983) (Home Vision) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce4bbe11d682c15a490ae15a4a8716cf", "", "", "Okie Dokie (Older) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce5524bb18e3bd8e092273ef22d36cb9", "Carrere Video - JWDA, Todd Marshall, Wes Trager, Henry Will IV - Teldec - Prism", "USC1004", "Commando Raid (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce5cc62608be2cd3ed8abd844efb8919", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce64812eb83c95723b04fb56d816910b", "Retroactive", "", "Qb (V2.04) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ce6c4270f605ad3ce5e82678b0fc71f8", "", "", "Vertical Rainbow Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce82a675c773ff21e0ffc0a4d1c90a71", "", "", "Defender 2 (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender 2", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ce8467ae2a3a5bc88ca72a2ce44ce28c", "SOLID Corp. (D. Scott Williamson)", "CX2655-015", "Star Castle 2600 (SolidCorp) (PAL) [015]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ce89529d6e98a13ddf3d84827bbdfe68", "", "", "Kung Fu Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ce904c0ae58d36d085cd506989116b0b", "Telegames", "5687 A279", "International Soccer (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cea9f72036dc6f7af5eff52459066290", "Retroactive", "", "Qb (2.07) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ceba7965a93c689bdecdb46a5b2ac0c1", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "cedbd67d1ff321c996051eec843f8716", "Ultravision", "1044", "Karate (1982) (Ultravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cef01595000627ee50863d4290372c27", "", "", "Many Blue Bars and Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cef2287d5fd80216b2200fb2ef1adfa8", "Milton Bradley Company", "4363", "Spitfire Attack (1983) (Milton Bradley)", "AKA Flight Commander)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cf0c593c563c84fdaf0f741adb367445", "Retroactive", "", "Qb (V0.05) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cf3a9ada2692bb42f81192897752b912", "", "", "Air Raiders (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cf3c2725f736d4bcb84ad6f42de62a41", "Rainbow Vision - Suntek", "SS-009", "Bermuda, The (1983) (Rainbow Vision) (PAL) [a]", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cf507910d6e74568a68ac949537bccf9", "SEGA, Jeff Lorenz", "003-01", "Thunderground (1983) (SEGA)", "AKA Underground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cf63ffac9da89ef09c6c973083061a47", "CCE", "C-859", "MASH (1983) (CCE)", "AKA M.A.S.H", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cf9069f92a43f719974ee712c50cd932", "Video Gems", "VG-04", "Mission Survive (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cfad2b9ca8b8fec7fb1611d656cc765b", "Bit Corporation", "PG207", "Mission 3,000 A.D. (1983) (BitCorp) (PAL) [demo cart]", "demonstration cartridge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cfb3260c603b0341d49ddfc94051ec10", "Dactari - Milmar", "", "Boxing (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfb83a3b0513acaf8be4cae1512281dc", "Starpath Corporation", "", "Going-Up (1983) (Starpath) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfc226d04d7490b69e155abd7741e98c", "Atari, Matthew L. Hubbard", "CX26159", "Double Dunk (1989) (Atari) (PAL)", "AKA Super Basketball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfce5596a7e8ca13529e9804cad693ef", "Canal 3 - Intellivision", "", "Tennis (Canal 3) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfd5518c71552b8bb853b0e461e328d7", "Bit Corporation", "R320", "Spider Fighter (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfd6a8b23d12b0462baf6a05ef347cd8", "Activision, Larry Kaplan", "AX-006", "Bridge (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfdb4d0427a1ea8085c6bc6eb90259d8", "", "", "Gunfight 2600 - Release Candidate (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfe2185f84ce8501933beb5c5e1fd053", "", "", "Football (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfe62ed7125ff9fae99b4c8a367c0399", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfee10bd7119f10b136921ced2ee8972", "", "", "Space Instigators (V1.8) (19-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cfef1a2d1f6a5ee7a5e1f43f3056f112", "", "", "Skeleton+ (05-05-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cff1e9170bdbc29859b815203edf18fa", "Retroactive", "", "Push (V0.01) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cff578e5c60de8caecbee7f2c9bbb57b", "George Veeder", "", "Suicide Adventure (George Veeder) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "cff9950d4e650094f65f40d179a9882d", "Paul Slocum", "", "Mr. Roboto (Paul Slocum) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "cfffc4b97d01cc3e7b9f47575f7b11ec", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox) (PAL60)", "Genesis controller (B is jump and throw, C switches between players)", "Hack of Tomarc the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "d00f6f8ba89559e4b20972a478fc0370", "Spiceware", "SW-01", "Medieval Mayhem (PAL)", "", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "d010e3dfe7366e47561c088079a59439", "Retroactive", "", "Qb (V0.10) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d026716b3c5be2c951cc4c064317c524", "", "", "Fu Kung! (V0.06) (14-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0498baca989e792db4b8270a02b9624", "", "", "Pac Ghost Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d071d2ec86b9d52b585cc0382480b351", "UA Limited", "", "Cat Trax (1983) (UA Limited) (1) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d078674afdf24a4547b4b32890fdc614", "Jone Yuan Telephonic Enterprise Co", "", "Laser Blast (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d078d25873c5b99f78fa267245a2af02", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "006-01", "Congo Bongo (1983) (SEGA) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0796a0317abf9018d6745086bef411f", "Edward Smith", "", "Alien Attack (2018)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d08fccfbebaa531c4a4fa7359393a0a9", "Activision, David Crane, Bob Whitehead", "", "Venetian Blinds Demo (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d090836f0a4ea8db9ac7abb7d6adf61e", "Hozer Video Games", "", "Yahtzee (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d09935802d6760ae58253685ff649268", "Telesys, Don Ruffcorn", "1006", "Demolition Herby (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d09a7504ee8c8717ac3e24d263e7814d", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d09f1830fb316515b90694c45728d702", "Imagic, Brad Stewart", "720105-1A, IA3400", "Fire Fighter (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0a379946ed77b1b126230ca68461333", "Ataripoll", "", "Atari Invaders (Ataripoll) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0af33865512e9b6900714c26db5fa23", "Telegames", "", "Armor Ambush (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0b26e908370683ad99bc6b52137a784", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo - RCA Video Jeux", "AP-2004", "Lost Luggage (1982) (Apollo) (PAL)", "AKA La valise piegee", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0b9df57bfea66378c0418ec68cfe37f", "20th Century Fox Video Games - Sirius, Grady Ward", "11002", "Beany Bopper (1982) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0b9f705aa5f61f47a748a66009ae2d2", "", "", "Synthcart (14-01-2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d0cb28e1b7bd6c7f683a0917b59f707e", "Atari, Gary Palmer", "CX2661P", "Fun with Numbers (1980) (Atari) (PAL) (4K)", "AKA Basic Math", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0cdafcb000b9ae04ac465f17788ad11", "Quelle - Otto Versand", "732.273 8 - 600273, 781644", "Lilly Adventure (1983) (Quelle) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0e05ba5f10e3df3023c5ee787f760ef", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0e15a3ce322c5af60f07343594392af", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) (4K)", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d0e9beb2347595c6c7d158e9d83d2da8", "Retroactive", "", "Qb (2.00) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d100b11be34a1e5b7832b1b53f711497", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d15655fe355fa57dd541487dc5725145", "Rentacom", "", "Vanguard (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d170317ae4c7d997a989c7d6567c2840", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d175258b2973b917a05b46df4e1cf15d", "Suntek", "SS-032", "Walker (1983) (Suntek) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d17a671029b1532b197defca5f3649a7", "Hozer Video Games", "", "Gunfight 2600 - Limit broken again! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d17a8c440d6be79fae393a4b46661164", "", "", "Warring Worms (Beta 3) (2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d1a1841b7f2007a24439ac248374630a", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d1a9478b99d6a55e13a9fd4262da7cd4", "U.S. Games Corporation, Garry Kitchen - Vidtec", "VC1001", "Space Jockey (1982) (U.S. Games) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d1b4075925e8d3031a7616d2f02fdd1f", "", "", "Demo Image Series #7 - Two Marios (27-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d1c3520b57c348bc21d543699bc88e7e", "Gameworld", "133-002", "Warplock (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "YES", "", "", "", "", "" }, - { "d1ca47b262f952413c1234117c4e4e21", "Bit Corporation", "R320", "Missile Command (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d1d704a7146e95709b57b6d4cac3f788", "Atari, Warren Robinett", "CX26163P", "Slot Racers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d20e61c86ed729780feca162166912ca", "Supergame", "32", "Pitfall (1984) (Supergame)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d214c7a734e133a5c18e93229435b57a", "Digivision", "", "Mickey (Digivision)", "AKA Sorcerer's Apprentice", "", "", "", "UASW", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d223bc6f13358642f02ddacfaf4a90c9", "Rainbow Vision - Suntek", "SS-003", "Pac-Kong (1983) (Rainbow Vision) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d245e2f27c84016041e9496b66b722fe", "", "", "Gunfight 2600 - The Final Kernel (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d25018349c544320bf3fd5092ee072bc", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d28afe0517a046265c418181fa9dd9a1", "", "", "Dodge 'Em (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2901c34bb6496bb96c7bc78a9e6142a", "Greg Zumwalt", "", "Fish Revenge (2003) (Greg Zumwalt) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2c4f8a4a98a905a9deef3ba7380ed64", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1001", "Sorcerer (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2c8e6aa8172b16c8aa9aae739ac9c5e", "Activision, David Crane", "08-08-1980", "Laser Blast (08-08-1980) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2c957dd7746521b51bb09fde25c5774", "Eckhard Stolberg", "", "Cubis (6K) (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2d8c4f1ea7f347c8bcc7d24f45aa338", "", "", "20 Sprites at Once Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2deddb77c8b823e4be9c57cb3c69adc", "Canal 3 - Intellivision", "C 3007", "Snoopy and the Red Baron (Canal 3)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d2f713c78a9ebba9da6d10aeefc6f20f", "Digivision", "", "Enduro (Digivision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d3171407c3a8bb401a3a62eb578f48fb", "ZiMAG - Emag - Vidco", "GN-080", "Spinning Fireball (1983) (ZiMAG) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d326db524d93fa2897ab69c42d6fb698", "Parker Brothers - Roklan, Paul Crowley, Bob Curtiss", "931505", "Super Cobra (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d339b95f273f8c3550dc4daa67a4aa94", "", "", "Laser Blast (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d341d39774277cee6a1d378a013f92ac", "Xonox, John Perkins", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d3423d7600879174c038f53e5ebbf9d3", "U.S. Games Corporation - Western Technologies", "VC2005", "Piece o' Cake (1983) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "d3456b4cf1bd1a7b8fb907af1a80ee15", "Avalon Hill, Duncan Scott", "5003002", "Wall Ball (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d34b933660e29c0a0a04004f15d7e160", "", "", "Multi-Color Demo 5 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d36308387241e98f813646f346e7f9f7", "King Atari", "", "Ghostbuster 2 (King Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d39e29b03af3c28641084dd1528aae05", "Funvision - Fund. Int'l Co.", "", "Spider Monster (1982) (Funvision) (PAL)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d3bb42228a6cd452c111c1932503cc03", "UA Limited", "", "Funky Fish (1983) (UA Limited) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d44d90e7c389165f5034b5844077777f", "Parker Brothers, Larry Gelberg", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d45bf71871b196022829aa3b96bfcfd4", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d45ebf130ed9070ea8ebd56176e48a38", "SEGA, Jeff Lorenz", "001-01", "Tac-Scan (1983) (SEGA)", "Uses the Paddle Controllers (right only)", "", "", "", "", "", "", "", "YES", "", "", "YES", "AUTO 60", "", "", "YES", "", "", "", "", "" }, - { "d47387658ed450db77c3f189b969cc00", "PlayAround - J.H.M.", "206", "Westward Ho (1982) (PlayAround) (PAL)", "AKA Custer's Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d4806775693fcaaa24cf00fc00edcdf3", "Atari - Bobco, Robert C. Polaro", "CX26140, CX26140P", "Desert Falcon (1987) (Atari) (PAL)", "AKA Nile Flyer, Sphinx", "", "", "", "", "", "", "", "", "", "", "", "", "PAL", "", "", "", "", "", "", "" }, - { "d483f65468d9a265661917bae1a54f3e", "Joe Grand", "", "SCSIcide Pre-release 3 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d4942f4b55313ff269488527d84ce35c", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675, CX2675P", "Ms. Pac-Man (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d49aff83f77a1b9041ad7185df3c2277", "", "", "Space Treat (60% complete) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d4aa89e96d2902692f5c45f36903d336", "", "", "Euchre (NTSC) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d4c590ccfb611a73b3331359700c01a3", "", "", "Sprite Movement Demo 2 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d541b20eae221a8ee321375e5971e766", "Arcadia Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (Preview) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d54cd41ecfd59e4b72d2c086152b9a75", "Amiga - Video Soft - Michael K. Glass, Jerry Lawson", "1110", "Power Play Arcade Video Game Album (1983) (Amiga) (Prototype)", "3-D Ghost Attack only (3-D Genesis & 3-D Havoc missing in ROM)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d5618464dbdc2981f6aa8b955828eeb4", "CCE", "C-829", "Megamania (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d563ba38151b8204c9f5c9f58e781455", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d573089534ca596e64efef474be7b6bc", "Parker Brothers, John Emerson", "931511", "Action Force (1983) (Parker Bros) (PAL) [a]", "AKA G.I. Joe - Cobra Strike", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, - { "d57913088e0c49ac3a716bf9837b284f", "Activision, Garry Kitchen", "EAZ-032", "Pressure Cooker (1983) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d57eb282d7540051bc9b5427cf966f03", "Atari Troll", "", "Custer's Viagra (Atari Troll) (Hack)", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d597d35c6022c590d6e75e865738558a", "", "", "Sprite Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5aa7472e7f2cc17e893a1a36f8dadf0", "", "", "Overhead Adventure Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5c6b81212ad86fd9542a1fedaf57cae", "", "", "Sprite Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5d2d44fb73785996ccc24ae3a0f5cef", "Robby", "", "Grand Prix (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5e17022d1ecc20fd9b53dc464c302f1", "Activision, Carol Shaw", "EAX-020", "River Raid (1982) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "SECAM", "", "", "", "", "", "", "" }, - { "d5e27051512c1e7445a9bf91501bda09", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5e5b3ec074fff8976017ef121d26129", "Star Game", "003", "River Raid (Star Game)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d5f965c159e26a1fb49a22a47fbd1dd0", "Supergame", "", "River Raid II (Supergame)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d605ed12f4eaaaec3dcd5aa909a4bad7", "", "", "Chronocolor Frame Demo (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d61629bbbe035f45552e31cef7d591b2", "", "", "Atari Logo Demo (PD) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d62283aed0f4199adb2333de4c263e9c", "Atari, Alan J. Murphy, Nick 'Sandy Maiwald' Turner", "CX2615", "Demons to Diamonds (1982) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "10 57", "", "", "", "", "", "", "", "" }, - { "d62d7d1a974c31c5803f96a8c1552510", "", "", "StarMaster (Unknown) (PAL)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d632b74fea533d593af82cf16e7c5e4a", "", "", "Fu Kung! (V0.13) (01-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d65028524761ef52fbbdebab46f79d0f", "CCE", "", "Galaxian (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d65900fefa7dc18ac3ad99c213e2fa4e", "", "", "Guntest (2000) (Eckhard Stolberg)", "Light Gun Test (based on Sentinel code)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d69559f9c9dc6ef528d841bf9d91b275", "Activision, Alan Miller", "AX-016", "StarMaster (1982) (Activision)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6a44277c3eb4f9d039185e0ecf7bfa6", "", "", "Trick (1997) (Eckhard Stolberg)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6acff6aed0f04690fe4024d58ff4ce3", "Spectravision - Spectravideo - Quelle", "SA-202 - 412.851 8", "Planet Patrol (1982) (Spectravision) (PAL) [different spaceship]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6b8beeb05e5b730084d4b8f381bbf8d", "", "", "208 in 1 Game Select ROM (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6d1ddd21e9d17ea5f325fa09305069c", "Funvision - Fund. International Co.", "", "Time Warp (1982) (Funvision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6d5dd8fd322d3cf874e651e7b6c1657", "", "", "How to Draw a Playfield (1997) (Nick Bensema) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d6dc9b4508da407e2437bfa4de53d1b2", "Bomb - Onbase", "CA283", "Z-Tack (1983) (Bomb) (PAL)", "AKA Base Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d726621c676552afa503b7942af5afa2", "Atari, Bob Whitehead", "CX26163P", "Blackjack (32 in 1) (1988) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d73ad614f1c2357997c88f37e75b18fe", "Goliath", "7", "Space Tunnel (1983) (Goliath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d74a81fcd89c5cf0bd4c88eb207ebd62", "", "", "Poker Squares (V0.00a) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d763e3a9cdcdd56c715ec826106fab6a", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d7759fa91902edd93f1568a37dc70cdb", "Atari, Robert C. Polaro", "CX26157", "Stunt Cycle (1980) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d782543818b6320e4f60d77da2b596de", "Atari", "CX26163P", "Fishing Derby (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d787ec6785b0ccfbd844c7866db9667d", "Retroactive", "", "Qb (V0.04) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d7891b0faa4c7f764482762d0ed427a5", "", "", "Bars and Text Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d7b2259f6bb57bf37eac82365c1f8ad6", "Parker Brothers, Mike Brodie", "PB5320", "Super Cobra (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d7b58303ec8d8c4dbcbf54d3b9734c7e", "", "", "Paddle Demo (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d7dd56677e4ec1e6627419478a4a9668", "", "", "Shadow Keep (Fixed) (04-03-2003) (Andrew Towers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d7f5bf138cfc7feab7b8ef1534c8b477", "", "", "Eric Bergstrom's KC-135 (Radar Map) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d816fea559b47f9a672604df06f9d2e3", "Atari, Gary Palmer", "CX26163P", "Fun with Numbers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d81bb6965e6c99b3be99ffd8978740e4", "", "", "Gunfight 2600 - The Final Kernel Part 3 (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d82675ce67caf16afe5ed6b6fac8aa37", "Thomas Jentzsch", "", "Robot City (V0.23) (13-11-2002) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d8295eff5dcc43360afa87221ea6021f", "Spectravideo", "SA-212", "Mangia' (1983) (Spectravideo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d82c8a58098a6b46c5b81c16180354d1", "Dennis Debro", "", "Climber 5 (30-10-2002) (Dennis Debro) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d85f1e35c5445ac898746719a3d93f09", "Suntek", "SS-034", "Farmyard Fun (1983) (Suntek) (PAL)", "AKA Play Farm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d86deb100c6abed1588aa84b2f7b3a98", "Atari, Bob Whitehead - Sears", "CX2625 - 6-99827, 49-75114", "Football (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d88691c995008b9ab61a44bb686b32e4", "", "", "Warring Worms (07-02-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d89262907e70c13dff23356c4a9055d0", "Bit Corporation", "R320", "Video Pinball (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d89fedded0436fdeda7c3c37e2fb7cf1", "", "", "Surround (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d8acaa980cda94b65066568dd04d9eb0", "CCE", "", "Sea Hunt (CCE)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d8b2c81cea5af04f795eb3dc6573d72b", "", "", "Tunnel Demo 2 (27-03-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d8df256c0d89e494a9fb3e9abb8e44ac", "Imagic, Michael Greene", "IA3312P", "No Escape! (1982) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d8e4c8e2d210270cd1e0f6d1b4582b91", "Imagic, Mark Klein", "EIZ-003-04I", "Subterranea (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d90205e29bb73a4cdf28ea7662ba0c3c", "Thomas Jentzsch", "", "Boulderdash Demo (Brighter Version) (09-12-2002) (TJ)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d912312349d90e9d41a9db0d5cd3db70", "CCE", "C-818", "Star Voyager (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d9548ad44e67edec202d1b8b325e5adf", "Apollo - Games by Apollo, Dan Oliver - RCA Video Jeux", "AP-2002", "Space Cavern (1982) (Apollo) (PAL)", "AKA Les guerriers de l'espace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d968de2b4ff18bfe4a95066cde310578", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d97e3d0b4575ce0b9a6132e19cfeac6e", "Fabrizio Zavagli", "", "Space Treat (061002) (PD)", "Won't work with Stella < V1.2", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d97fd5e6e1daacd909559a71f189f14b", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (04-20-1983) (M Network) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d9ab6b67a17da51e5ad13717e93fa2e2", "Thomas Jentzsch", "", "Turbo (Coleco) Prototype Fake v0.1 (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d9b49f0678776e04916fa5478685a819", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d9bd343533b61389b270c0787210943b", "Atari, Douglas 'Solaris' Neubauer", "CX26134", "Last Starfighter (1984) (Atari) (Prototype)", "Genesis controller (C switches to map mode)", "Hack of Last Starfighter (Solaris prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "d9c9cece2e769c7985494b1403a25721", "SOLID Corp. (D. Scott Williamson)", "CX2655*", "Star Castle 2600 (SolidCorp)", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "d9da2ae7c7894a29b43b3c6b79f3b7a2", "Atari, Rob Fulop", "CX2633, CX2633P", "Night Driver (1980) (Atari) (PAL) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "d9fbf1113114fb3a3c97550a0689f10f", "ZiMAG - Emag - Vidco", "713-111 - GN-050", "Pizza Chef (1983) (ZiMAG) (Prototype)", "AKA Pizza Time", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da0fb2a484d0d2d8f79d6e063c94063d", "", "", "Air Raiders (1982) (Unknown) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da4e3396aa2db3bd667f83a1cb9e4a36", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da5096000db5fdaa8d02db57d9367998", "Digitel", "", "River Raid (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da6465a34d2e44d26aa9a2a0cd1bce4d", "Absolute Entertainment, Alex DeMeo", "AG-041-04", "Title Match Pro Wrestling (1987) (Absolute) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da66d75e4b47fab99733529743f86f4f", "Digitel", "", "Chopper Command (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "da732c57697ad7d7af414998fa527e75", "Atari - Glenn Axworthy", "CX26129", "Midnight Magic (1986) (Atari) (PAL)", "AKA Pinball Wizard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "da79aad11572c80a96e261e4ac6392d0", "Salu - Ubi Soft, Dennis M. Kiss", "460673", "Pick 'n' Pile (1990) (Salu) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "PAL", "", "YES", "", "", "", "", "" }, - { "da7a17dcdaa62d6971393c0a6faf202a", "", "", "Flag Capture (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dab844deed4c752632b5e786b0f47999", "", "", "Super Challenge Baseball (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dac38b4dd3da73bb7b2e9d70c61d2b7c", "", "", "Hangman Monkey Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dac5c0fe74531f077c105b396874a9f1", "Atari - GCC", "CX2680", "RealSports Tennis (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dac762e4d01d445bdef20b7771f6570e", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari) (4K) [a]", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "45", "", "", "", "", "", "", "", "" }, - { "dad2ab5f66f98674f12c92abcfbf3a20", "", "", "Blue and White Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "daeb54957875c50198a7e616f9cc8144", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11005", "Mega Force (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "daef7d8e5a09981c4aa81573d4dbb380", "Adam Thornton", "", "Lord of the Rings (Adam Thornton) (Hack)", "Hack of Dark Mage", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dafc3945677ccc322ce323d1e9930beb", "Atari", "", "A-Team (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db1753cc702c18d3917ec7f3b0e8659f", "", "", "Frame Counter 2 (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db339aea2b65b84c7cfe0eeab11e110a", "", "", "Chronocolor Frame Demo 2 (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db4eb44bc5d652d9192451383d3249fc", "CBS Electronics - E.F. Dreyer - VSS, Ed Salvo", "4L 2738 0000", "Mountain King (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "db5073bd75eb05f7d62a7268396d1e77", "Atari", "CX26163P", "Golf (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db76f7a0819659d9e585f2cdde9175c7", "Xonox", "99005, 6220, 6250", "Robin Hood (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db80d8ef9087af4764236f7b5649fa12", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (1983) (Mattel) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "db971b6afc9d243f614ebf380af0ac60", "Gammation, Robert L. Esken Jr.", "", "Gamma-Attack (1983) (Gammation)", "Uses right joystick controller", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dba270850ae997969a18ee0001675821", "Greg Troutman", "", "Dark Mage (Greg Troutman) (PD) (4K)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dbabb80e92ff18d8eecf615c0539151e", "", "", "Sprite Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dbb10b904242fcfb8428f372e00c01af", "Atari, John Dunn", "CX2631, CX2631P", "Superman (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dbba14a0f69f0e13fdccb3fde3baedca", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dbc7485ad5814d466de780a3e7ed3b46", "Kyle Pittman", "", "Pink Floyd (Kyle Pittman) (PD)", "Hack of Adventures of Tron (Mattel)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dbc8829ef6f12db8f463e30f60af209f", "Data Age", "DA1001", "Encounter at L-5 (1982) (Data Age)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, - { "dbdaf82f4f0c415a94d1030271a9ef44", "CCE", "", "Kaboom! (CCE)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "dbdd21e1ee3d72119e8cd14d943c585b", "", "", "Slot Machine (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dc13df8420ec69841a7c51e41b9fbba5", "Atari, Mimi Nyden, Steve Woita", "CX26132", "Garfield (06-21-1984) (Atari) (Prototype)", "AKA Garfield on the Run", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dc33479d66615a3b09670775de4c2a38", "Suntek", "SS-033", "I.Q. Memory Teaser (1983) (Suntek) (PAL)", "AKA IQ 180", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dc81c4805bf23959fcf2c649700b82bf", "Imagic, Michael Greene", "720055-2A, IA3312P", "No Escape! (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dc905b22de0f191a029df13eddfcabc4", "Atari, Warren Robinett", "", "Elf Adventure (05-02-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dc97cbcf091a5ef4ca7fe95dc0848036", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a2]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dca90ea1084a2fdbe300d7178ca1a138", "Imagic, Dennis Koble", "IA3000P", "Trick Shot (1982) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dca941dab5c6f859b71883b13ade9744", "", "", "Hangman Pac-Man Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dcba0e33aa4aed67630a4b292386f405", "Retroactive", "", "Qb (V2.08) (Half Speed Version) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dcc2956c7a39fdbf1e861fc5c595da0d", "M Network - INTV - APh Technological Consulting, David Rolfe", "MT5664", "Frogs and Flies (1982) (M Network)", "AKA Frogs 'n' Flies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dcec46a98f45b193f07239611eb878c2", "", "", "Bars and Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd08e18cfee87a0e7fc19a684b36e124", "Atari - GCC, Kevin Osborn", "CX2689, CX2689P", "Kangaroo (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd0cbe5351551a538414fb9e37fc56e8", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd0de0f61af2a2a4878e377b880a3933", "SOLID Corp. (D. Scott Williamson)", "CX2655-013", "Star Castle 2600 (SolidCorp) [013]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dd10b5ee37fdbf909423f2998a1f3179", "", "", "Space Instigators (V1.9) (21-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd13a16d14100819f79b1ce3a5bf499c", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (PAL) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd1422ffd538e2e33b339ebeef4f259d", "Atari, Michael Sierchio", "", "Football Demo (1982) (Atari)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd17711a30ad60109c8beace0d4a76e8", "", "", "Karate (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd1842ba0f3f9d94dccb21eaa0f069b7", "Bit Corporation", "R320", "Defender (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd45e370aceff765f1e72c619efd4399", "Bit Corporation", "PG201", "Sea Monster (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd4f4e0fbd81762533e39e6f5b55bb3a", "Thomas Jentzsch", "", "Turbo WIP (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd7598b8bcb81590428900f71b720efb", "Xonox - K-Tel Software - Computer Magic", "99005, 6220, 6250", "Robin Hood (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd7884b4f93cab423ac471aa1935e3df", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "dd8a2124d4eda200df715c698a6ea887", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (3 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dd92d6ad50976f881d86b52d38616118", "SpkSoft", "", "River Raid (SpkSoft) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dda23757407c4e217f64962c87ad0c82", "Atari Freak 1", "", "Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack) [a]", "Hack of Pac-Man Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ddd1efc1862cd3eb3baf4cba81ff5050", "", "", "Max3 (2001) (Maxime Beauvais) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de0173ed6be9de6fd049803811e5f1a8", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99008, 6240", "Motocross Racer (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de07e9cb43ad8d06a35f6506e22c62e9", "", "", "Oh No! (Version 4) (22-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de1a636d098349be11bbc2d090f4e9cf", "", "", "Pressure Gauge (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de1e9fb700baf8d2e5ae242bffe2dbda", "Activision - Imagineering, Mike Reidel", "EAK-043-04I", "Commando (1988) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de24f700fd28d5b8381de13abd091db9", "CCE", "", "Plaque Attack (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de29e46dbea003c3c09c892d668b9413", "Coleco - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "4L1717, 4L1718, 4L1719, 4L2277", "Carnival (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de3d0e37729d85afcb25a8d052a6e236", "Spectravision - Spectravideo", "SA-204", "Tapeworm (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "de4436eaa41e5d7b7609512632b90078", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de5aab22e5aba5edcb29a3e7491ff319", "Star Game", "001", "Donkey Kong (Star Game)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de61a0b171e909a5a4cfcf81d146dbcb", "Rainbow Vision - Suntek", "SS-005", "Tom Boy (1983) (Rainbow Vision) (PAL)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de62f8a30298e2325249fe112ecb5c10", "CCE", "C-810", "Enduro (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de78b3a064d374390ac0710f95edde92", "Bomb - Onbase", "CA281", "Assault (1983) (Bomb)", "AKA Sky Alien", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de7a64108074098ba333cc0c70eef18a", "", "", "Nuts (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "de7bca4e569ad9d3fd08ff1395e53d2d", "Thomas Jentzsch", "", "Thrust (V1.22) (2000) (TJ)", "Supports BoosterGrip", "New Release", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "" }, - { "de8443ff47283e7b274a7838cb071fb6", "Atari, Lou Harp", "CX26122", "Sinistar (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dea0ade296f7093e71185e802b500db8", "CCE", "", "Fishing Derby (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "deb39482e77f984d4ce73be9fd8adabd", "Activision, David Lubar", "AK-048-04", "River Raid II (1988) (Activision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ded26e1cb17f875a9c17515c900f9933", "", "", "Space Treat (29-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df12953b919844dad2070ed2e70c9fa2", "Amiga - Video Soft", "3135", "S.A.C. Alert (1983) (Amiga) (Prototype) (PAL)", "Uses Joyboard", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df2745d585238780101df812d00b49f4", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df3e6a9b6927cf59b7afb626f6fd7eea", "", "", "Tuby Bird (208 in 1) (Unknown) (PAL)", "AKA Dolphin", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df40af244a8d68b492bfba9e97dea4d6", "Franklin Cruz", "", "Asteroids 2 (Franlin Cruz) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "df5cc5cccdc140eb7107f5b8adfacda1", "Cracker Jack Productions", "", "Lumberman (Cracker Jack) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df62a658496ac98a3aa4a6ee5719c251", "Atari, Tom Reuterdahl - Sears", "CX2626 - 6-99829, 49-75116", "Miniature Golf (1979) (Atari)", "AKA Arcade Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df6a28a89600affe36d94394ef597214", "Apollo - Games by Apollo, Dan Oliver", "AP-2002", "Space Cavern (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df6a46714960a3e39b57b3c3983801b5", "Puzzy - Bit Corporation", "PG201", "Sea Monster (1982) (Puzzy) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df753cb87d3af4d03f694ab848638108", "CBS Electronics, Bob Curtiss", "4L1845, 4L1852, 4L1853, 4L1854", "Solar Fox (1983) (CBS Electronics) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df91277a3569344b89e6e8bd5bebc8d1", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (PAL) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "df95e4af466c809619299f49ece92365", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (06-03-1983) (Atari) (Prototype) (PAL)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfad86dd85a11c80259f3ddb6151f48f", "HES - Imagineering, David Lubar", "535", "My Golf (1990) (HES) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfafa3fa58f5cc3f0342cca475df6095", "", "", "Space Treat (V1.1 Beta) (24-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfc03ef371cf5163f54c50d8ee73c8cf", "Atari, Gary Palmer", "CX2661", "Fun with Numbers (1980) (Atari) (4K)", "AKA Basic Math", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfc3dbbb39f05d7dd8ee3ac987478970", "", "", "Imagic Selector ROM (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfcdd6f593bb7b05dbc2e8e1fc6ee0de", "", "", "Gunfight 2600 - Scenarios complete (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfe034297200dff672df9533ed1449a9", "", "", "Sprite Movement Demo 1 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dfe6aa7443bb813cefa35a4cf4887422", "", "", "This Planet Sucks (Greg Troutman) [a1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "dff33523ccd2fdc8912e84cab8e0d982", "", "", "Fu Kung! (V0.03) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e01e00504e6d4b88fa743c0bbe8a96e5", "", "", "Qb (Special Edition, some bugfixes) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e020f612255e266a8a6a9795a4df0c0f", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames) (PAL)", "AKA Targ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e02156294393818ff872d4314fc2f38e", "Sancho - Tang's Electronic Co.", "TEC005", "Dice Puzzle (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e0221c95aa657f5764eeeb64c8429258", "", "", "Tomb Raider 2600 [REV 02] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e03b0b091bea5bc9d3f14ee0221e714d", "CBS Electronics, Bob Curtiss", "4L1852, 4L1853, 4L1854, 4L1855", "Solar Fox (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e040df95a055b18ebdb094e904cb71b2", "", "", "Score Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e04f1c1e4401d584d3f4343410a5bcc4", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e0b24c3f40a46cda52e29835ab7ad660", "Quelle - Otto Versand", "626.502 9 - 746381", "Top Gun (1983) (Quelle) (PAL)", "AKA Air Raiders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e0cf2dcc4c1348c468f5bb1e421c9164", "", "", "Invader Sprites in a Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e0de3773f5b867795db557be7b8a703e", "", "", "Boulderdash (13 Blocks Wide) (02-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e0eff071f578ecf19edc2ab276644e46", "", "", "Gas Gauge Demo (2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1029676edb3d35b76ca943da7434da8", "Atari, Robert C. Polaro, Alan J. Murphy - Sears", "CX2609 - 49-75186", "Defender (10-30-1981) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e10bf1af6bf3b4a253c5bef6577fe923", "Rob Kudla", "", "Space Invaders (1978) (Atari) [h1]", "Hack of Space Invaders (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e10d2c785aadb42c06390fae0d92f282", "Parker Brothers, Dawn Stockbridge", "PB5910", "Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1143b72a30d4d3fee385eec38b4aa4d", "", "", "Word Zapper (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e12e32dee68201b6765fcd0ed54d6646", "Atari, Larry Kaplan", "CX2612, CX2612P", "Street Racer (1977) (Atari) (PAL)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "AUTO 75", "", "", "", "", "", "", "", "" }, - { "e13818a5c0cb2f84dd84368070e9f099", "CCE", "C-839", "Misterious Thief, A (1983) (CCE)", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e13c7627b2e136b9c449d9e8925b4547", "Atari, Alan Miller - Sears", "CX2624 - 6-99826, 49-75113", "Basketball (1978) (Atari) (4K)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1486c7822c07117b4f94a32e5ed68c1", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (06-14-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e14dc36b24fe22c04fa076e298f2e15f", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (16K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "e14feddeb82f5160ed5cf9ca4078e58d", "", "", "SpaceMaster X-7 (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e150f0d14f013a104b032305c0ce23ef", "Spectravision - Spectravideo", "SA-205", "China Syndrome (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e15b5525cf8f77297b322838df8d999c", "", "", "Sprite Demo 0 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e171558c51bb3bac97bfa79fa2c1a19c", "", "", "Warring Worms (Tim Strauss Edition) (20-12-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e17699a54c90f3a56ae4820f779f72c4", "Rainbow Vision - Suntek", "SS-020", "Tuby Bird (1983) (Rainbow Vision) (PAL)", "AKA Dolphin", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e18abe87035379c56b435bfe8175077b", "Grimlock", "", "Rumble 2600 (Grimlock) (Hack)", "Hack of Mario Bros.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1a51690792838c5c687da80cd764d78", "20th Century Fox, John Russell", "", "Alligator People (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1b90f1e01b1a316d7bbf141525cc00e", "", "", "Sky Jinks (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1d5c8213e82820128fa9c4775f1e166", "Jess Ragan", "", "Jungle King (2003) (Jess Ragan) (Hack)", "Hack of Jungle Hunt", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1d79e4e7c150f3861256c541ec715a1", "", "", "Space Jockey (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1e09e2f280e8e142121a377d0dc1b46", "Thomas Jentzsch", "", "Thrust (V1.21) (2000) (TJ)", "Bugfixed", "New Release", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1efe2ef7664bb6758b1a22ff8ea16a1", "Dynacom", "", "Enduro (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e1f88da6da8a7d521ca1dcbf2bc6978b", "Activision, Bob Whitehead - Ariola", "EAG-005, PAG-005, EAG-005-04B - 711 005-715", "Skiing (1980) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e21ee3541ebd2c23e817ffb449939c37", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001", "King Kong (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e227be19f572f6900e314213ae9a4deb", "Atari, Dan Hitchens, Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) (Prototype)", "AKA Adventure I, SwordQuest I - EarthWorld", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e237ee91514d5ed535c95a14fc608c11", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2389c0be5b5b84e0d3ca36ec7e67514", "Retroactive", "", "Qb (V2.09) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e24d7d879281ffec0641e9c3f52e505a", "Parker Brothers, Mark Lesser", "PB5950", "Lord of the Rings (1983) (Parker Bros) (Prototype)", "Journey to Rivendell (The Lord of the Rings I)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e25e173740f7ecc0e23025445c4591f3", "Greg Zumwalt", "", "Comitoid (Greg Zumwalt)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e275cbe7d4e11e62c3bfcfb38fca3d49", "M Network - INTV - APh Technological Consulting, Ken Smith", "MT5658", "Super Challenge Football (1982) (M Network)", "AKA Pro Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e27d518993b0a010f16e92b971ecdcdd", "Manuel Polik", "", "Star Fire (2003) (XYPE) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e28113d10c0c14cc3b5f430b0d142fcb", "CCE", "C-816", "Keystone Kappers (1983) (CCE) [a]", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2846af3e4d172b251ab77cbdd01761e", "Steve Engelhardt", "", "Adventure Plus (2003) (Steve Engelhardt) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2904748da63dfefc8816652b924b642", "Jone Yuan Telephonic Enterprise Co", "", "Catch Time (Jone Yuan)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2b682f6e6d76b35c180c7d847e93b4f", "", "", "Dodge Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2c1b60eaa8eda131632d73e4e0c146b", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2c89f270f72cd256ed667507fa038a2", "Starpath Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e2ca84a2bb63d1a210ebb659929747a9", "Telesys, Don 'Donyo' Ruffcorn", "1002", "Cosmic Creeps (1982) (Telesys) (PAL)", "AKA Space Maze, Spaze Maze", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e2eccbbe963f80f291cb1f18803bf557", "Atari, Joe Decuir, Steve Mayer, Larry Wagner", "CX26163P", "Combat (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e30f3a37032da52d7815b5a409f6d4b4", "SEGA, Fred Mack", "", "Bear Game Demo (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e314b42761cd13c03def744b4afc7b1b", "Activision, David Crane, Dan Kitchen", "AZ-108-04", "Ghostbusters (1985) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e34c236630c945089fcdef088c4b6e06", "Activision, Steve Cartwright, David Crane - Ariola", "EAB-035-04 - 711 035-721", "Pitfall II (1984) (Activision) (PAL)", "Lost Caverns", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e3533684a7ef930a7fbd0c4dd8ec4847", "CCE", "C-856", "Pimball (1983) (CCE)", "AKA Video Pinball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e3600be9eb98146adafdc12d91323d0f", "Atari, Carol Shaw", "CX2618, CX2618P", "3-D Tic-Tac-Toe (1980) (Atari) (PAL)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e363e467f605537f3777ad33e74e113a", "Atari, Bob Whitehead - Sears", "CX2603 - 99803, 49-75601", "Star Ship (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e377c3af4f54a51b85efe37d4b7029e6", "20th Century Fox Video Games, Beck-Tech, Steve Beck", "11035", "Save the Whales (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e37c8055d70979af354251ebe9f1b7dd", "HES", "", "Mega Funpak - Gorf, P. Patrol, Pacman, Skeet Shoot (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e38dc1f81a02e325562cd285123f579b", "Atari - GCC, Mike Feinstein", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e39843c56b7a4a08b18fa7949ec3ee6b", "", "", "Joshua Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e39a13b13dc82c5fdbfbbfd55ba1230e", "", "", "Analog Clock (Additional Frame Info) (V0.0) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e3c0451d29dad724231bc5818ec4bae0", "", "", "Single-Scanline Positioning Demo 1 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e3c35eac234537396a865d23bafb1c84", "TechnoVision - Video Technology", "TVS1001", "Nuts (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e3ed4ba3361756970f076e46e9cad1d2", "", "", "Tennis (Unknown) (PAL) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e40a818dac4dd851f3b4aafbe2f1e0c1", "Atari, Bill Aspromonte, Dr. Lee Salk", "CX26135", "Peek-A-Boo (1984) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e42b937c30c617241ca9e01e4510c3f6", "", "", "Pitfall! (No Walls Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e434c0e161dd3c3fb435eb6bad2e182c", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (05-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e48d3a4056ede9393586421996db1ae8", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "e49ac0ec879a0d7820bc2598fc2cfcd4", "CCE", "", "Kaboom! (CCE) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "e4a0b28befaaa2915df1fa01238b1e29", "", "", "Gunfight 2600 - Red River (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4afe157c09962cf39cdb25845d83d47", "Activision, David Crane - Ariola", "EAG-009, PAG-009 - 711 009-720", "Freeway (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4b12deaafd1dbf5ac31afe4b8e9c233", "Adam Thornton", "", "Lord of the Rings (Adam Thornton) (Hack) [a]", "Hack of Dark Mage", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e4bff1d5df70163c0428a1ead309c22d", "Atari, Robert C. Polaro, Alan J. Murphy", "CX2609, CX2609P", "Defender (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4c00beb17fdc5881757855f2838c816", "20th Century Fox Video Games - Sirius, Ed Hodapp", "11004", "Deadly Duck (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4c2077a18e3c27f4819aa7757903aa0", "", "", "Many Blue Bars Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4c666ca0c36928b95b13d33474dbb44", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Arcadia)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e4d41f2d59a56a9d917038682b8e0b8c", "Cody Pittman", "", "Kiss Meets Pacman (Cody Pittman) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e4e9125a8741977583776729359614e1", "SnailSoft", "", "Comitoid beta 4 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e505bd8e59e31aaed20718d47b15c61b", "Funvision - Fund. Int'l Co.", "", "Space War (1982) (Funvision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e51030251e440cffaab1ac63438b44ae", "Parker Brothers - On-Time Software, Joe Gaucher, Louis Marbel", "PB5110", "James Bond 007 (1984) (Parker Bros)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e51c23389e43ab328ccfb05be7d451da", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5359cbbbff9c6d7fe8aeff5fb471b46", "CCE", "C-849", "Boom Bang (1983) (CCE)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e549f1178e038fa88dc6d657dc441146", "Atari, Bob Whitehead - Sears", "CX2625 - 6-99827, 49-75114", "Football (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e556e07cc06c803f2955986f53ef63ed", "Coleco - Individeo, Ed Temple", "2665", "Front Line (1984) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e558be88eef569f33716e8e330d2f5bc", "Shock Vision", "", "Keystone Kapers (Shock Vision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e56da674188ba2f02c7a0a343a01236f", "", "", "This Planet Sucks Demo 4 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e59d022d524d05acc19515598c831e4d", "Alessandro Ciceri", "", "MagiCard+ (alex_79) WIP_20150118 (PAL)", "MagiCard hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5a6e0bb7d56e2f08b237e15076e5699", "", "", "Color Table Display Helper (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5bacf526036d3c8c99db5b030cf00e7", "", "", "Starmaster (Genesis)", "Genesis controller (C switches to map mode)", "Hack of Starmaster", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5d5085123a98c1e61818caa2971e999", "", "", "Euchre (PAL) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5d72ff8bab4450be57785cc9e83f3c0", "Telegames", "6082 A145", "Kung Fu Superkicks (1988) (Telegames) (PAL)", "AKA Chuck Norris Superkicks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5ecd78edd24326a968809decbc7b916", "Imagic, Bob Smith", "720020-1A, IA3611", "Cheese (Dragonfire Beta) (05-21-1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e5f17b3e62a21d0df1ca9aee1aa8c7c5", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid)", "AKA Termite", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e5f360226dc552aba3e7e9b202330f48", "Supercat", "", "Mega Bitmap Demo (2007) (Supercat)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e5f84930aa468db33c0d0f7b26dd8293", "CCE", "C-826", "Grand Prix (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e5fcc62e1d73706be7b895e887e90f84", "", "", "Air-Sea Battle (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e600f5e98a20fafa47676198efe6834d", "Parker Brothers - Roklan, Joe Gaucher", "PB5080", "Gyruss (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e609e8a007127b8fcff79ffc380da6b1", "", "", "Multi-Sprite Game V2.3 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e61210293b14c9c4ecc91705072c6a7e", "Gameworld", "133-005", "Bugs (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, - { "e62e60a3e6cb5563f72982fcd83de25a", "Jone Yuan Telephonic Enterprise Co", "", "End of the World (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e63a87c231ee9a506f9599aa4ef7dfb9", "Tigervision, Warren Schwader", "7-003", "Threshold (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e63efdfda9a4003dcd77a854a781a06a", "Paul Slocum", "", "Combat Rock (PD) (Hack) [a]", "Hack of Combat", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e643aaec9a9e1c8ab7fe1eae90bc77d7", "Roger Williams", "", "Asymmetric Playfield (Roger Williams)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e64a8008812327853877a37befeb6465", "Answer Software Corporation - TY Associates, Mike Wentz", "ASC1002", "Gauntlet (1983) (Answer Software)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e6508b878145187b87b9cded097293e7", "", "", "Oystron (V2.8) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e66e5af5dea661d58420088368e4ef0d", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e67b0ed32fd9d28d12ab3775d52e8c3a", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "AUTO 60", "", "", "", "", "", "", "", "" }, - { "e6d5948f451a24994dfaaca51dfdb4e1", "Jone Yuan Telephonic Enterprise Co", "", "Football (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e6de4ef9ab62e2196962aa6b0dedac59", "Imagic, Wilfredo Aguilar, Michael Becker, Dennis Koble", "720113-2A, 13206", "Solar Storm (1983) (Imagic) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "e6e5bb0e4f4350da573023256268313d", "Thomas Jentzsch", "", "Missile Control (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e6f49a1053c79211f82be4d90dc9fe3d", "", "", "Gunfight 2600 - Little progress... (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e723ad8f406cb258b89681ef4cef0eff", "Thomas Jentzsch", "", "Sadoom (TJ) (PAL) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "e72eb8d4410152bdcb69e7fba327b420", "Atari, Douglas Neubauer, Mimi Nyden", "CX26136", "Solaris (1986) (Atari)", "AKA Universe, Star Raiders II, The Last Starfighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e72ee2d6e501f07ec5e8a0efbe520bee", "Imagic, Dave Johnson", "720119-2A, 13211, EIX-004-04I", "Quick Step! (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e73838c43040bcbc83e4204a3e72eef4", "CCE", "", "Apples and Dolls (CCE)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e74022cfe31ec8908844718dfbdedf7a", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e77ec259e1387bc308b0534647a89198", "Parker Brothers, David Lamkins, Laura Nikolich", "931503", "Spider-Man (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e77f332b71f13884c84771e7a121182d", "Jone Yuan Telephonic Enterprise Co", "", "Hey! Stop! (Jone Yuan)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e784a9d26707cfcd170a4c1c60422a72", "Quelle", "147.443 6", "Gefecht im All (1983) (Quelle) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e7864caaf9ec49ed67b1904ce8602690", "", "", "Donkey Kong 2K3 Pic (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e7a758bb0b43d0f7004e92b9abf4bc83", "", "", "Troll's Adventure (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e7dd8c2e6c100044002c1086d02b366e", "Activision, Steve Cartwright - Ariola", "EAX-013, PAX-013, 711 013-720", "Barnstorming (1982) (Activision) (PAL)", "AKA Die tollkeuhnen Flieger", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e7f005ddb6902c648de098511f6ae2e5", "Spectravideo - Universum", "SV-010", "CompuMate (1983) (Spectravideo) (PAL)", "", "", "", "", "CM", "", "", "", "", "COMPUMATE", "COMPUMATE", "", "", "", "", "YES", "80", "", "", "", "" }, - { "e800e4aec7c6c54c9cf3db0d1d030058", "", "", "Qb (2.06) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e80a4026d29777c3c7993fbfaee8920f", "", "", "Frisco (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e823b13751e4388f1f2a375d3560a8d7", "Arcadia Corporation, Stephen Harland Landrum", "AR-4105", "Official Frogger (Preview) (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e879b7093ac4cfad74c88d636ca97d00", "", "", "Poker Squares (V0.0f) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e88340f5bd2f03e2e9ce5ecfa9c644f5", "", "", "Lock 'n' Chase (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e8a3473bf786cf796d1336d2d03a0008", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-05-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e8aa36e3d49e9bfa654c25dcc19c74e6", "Atari, Joe Decuir, Larry Caplan, Steve Mayer, Larry Wagner", "CX2601, CX2601P", "Combat (1977) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e8e7b9bdf4bf04930c2bcaa0278ee637", "", "", "Boring Taz (Hack)", "Hack of Taz", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e8f7679359c4f532f5d5e93af7d8a985", "", "", "Hangman Invader Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9034b41741dcee64ab6605aba9de455", "Digivision", "", "Phanton Tank (Digivision)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e908611d99890733be31733a979c62d8", "Atari, Dan Hitchens, Mimi Nyden", "CX2697", "Mario Bros. (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e91d2ecf8803ae52b55bbf105af04d4b", "Atari, Howard Scott Warshaw", "CX2655, CX2655P", "Yars' Revenge (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e923001015bedd7901569f035d9c592c", "", "", "Adventure II (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e927ecf80f3784d745abd8368d78f2f3", "", "", "Space Instigators (V1.8) (19-10-2002) (CT) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e932f44fad2a66b6d5faec9addec208e", "", "", "Atari Logo Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e94632b0d863dd76459d689a9865bb33", "Jone Yuan Telephonic Enterprise Co", "", "Combat (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e957eb4612d6bd5940d3492dfa749668", "", "", "Tunnel Demo (27-03-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e959b5a2c882ccaacb43c32790957c2d", "", "", "Phantom II & Pirate (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e97eafd0635651d3999cece953c06bd5", "", "", "M.A.S.H (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9be3e8e4a7e73dd63ed4235a3a1a25f", "", "", "MMetall (Hack)", "Hack of Miniature Golf", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9c5d04643855949a23ff29349af74ea", "", "", "SCSIcide (Score Hack 2) (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9c71f8cdba6037521c9a3c70819d171", "Action Hi Tech - Hi-Score", "", "Bank Heist (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9cb18770a41a16de63b124c1e8bd493", "Parker Brothers - Roklan, Joe Gaucher", "931519", "Popeye (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "e9db2f91efe6ff7ea3546e2c2578fb09", "Omegamatrix", "", "Millipede (Atari Mouse) v6.5 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "e9e646f730b8400cd5da08c849ef3e3b", "Tron", "", "Enduro (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9e6ad30549a6e2cd89fe93b7691d447", "Atari - Bobco, Robert C. Polaro", "CX26140, CX26140P", "Desert Falcon (05-27-1987) (Atari) (Prototype) (PAL)", "AKA Nile Flyer, Sphinx", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "e9f25c7af4f27c9e1b5b8f6fe6141e8c", "Champ Games", "CG-03-N", "Scramble (NTSC)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ea38fcfc06ad87a0aed1a3d1588744e4", "Atari, Lou Harp", "CX26122", "Sinistar (01-XX-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ea6d40db5498d6386571a76df448aa4c", "", "", "Vertical Playfield Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ea7e25ade3fe68f5b786ee0aa82b1fe5", "", "", "Galatic (208 in 1) (Unknown) (PAL)", "AKA Challenge of.... Nexar, The", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ea832e2cb6aae6f525f07452c381fa48", "", "", "Polar to Cartesian and VV (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ea86176b27ab0da8cce8f0179884bfaa", "", "", "Demo Image Series #10 - It's Art (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eaacfcdc1d4ee1258429b7ae7f084125", "Telegames", "6057 A227", "Quest for Quintana Roo (1989) (Telegames)", "Genesis controller (B is action button, C chooses tool or weapon)", "Hack of Quest for Quintana Roo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ead60451c28635b55ca8fea198444e16", "Sancho - Tang's Electronic Co.", "TEC004", "Nightmare (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eada0dd61ce13f8317de774dc1e68604", "", "", "2600 Digital Clock (Demo 1) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eae0c06ee61c63b81cd016096fc901b0", "Joe Grand", "", "SCSIcide (v1.0) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eae6a5510055341d3abeb45667bb3e9b", "HES", "", "Wall Defender (HES) (PAL)", "AKA Wall Break (Planet Patrol if right difficulty = 'A')", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eaf744185d5e8def899950ba7c6e7bb5", "Atari", "CX26172", "Xenophobe (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eafe8b40313a65792e88ff9f2fe2655c", "Eric Ball", "ELB004", "Skeleton+ (NTSC)", "Stereo sound", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb3d680699f8762f71f38e28e321234d", "", "", "Fu Kung! (V0.01) (08-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb4252faff7a4f2ba5284a98b8f78d1a", "", "", "John K Harvey's Equalizer (NTSC) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "eb46e99ec15858f8cd8c91cef384ce09", "Goliath - Hot Shot", "83-113", "Ground Zero (1983) (Goliath) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb503cc64c3560cd78b7051188b7ba56", "Star Game", "043", "Moto Laser (Star Game)", "AKA Mega Force", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb634650c3912132092b7aee540bbce3", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "eb6d6e22a16f30687ade526d7a6f05c5", "Atari", "CX26150P", "Q-bert (1987) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb71743c6c7ccce5b108fad70a326ad9", "", "", "Euchre (25-11-2001) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eb7934360658a29c50aeaff20bfda23b", "Activision, John Van Ryzin", "EAZ-036-04", "H.E.R.O. (1984) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "SECAM", "", "", "", "", "", "", "" }, - { "eb92193f06b645df0b2a15d077ce435f", "Starpath Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Starpath) (PAL)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "eb9712e423b57f0b07ccd315bb9abf61", "Retroactive", "", "Qb (V2.04) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "eb9f8b84c193d9d93a58fca112aa39ed", "", "", "Register Twiddler Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebcb084a91d41865b2c1915779001ca7", "JVP", "", "Bob Is Going Home (JVP)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebcbc8a181a738e13df6216e5c329230", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebd2488dcace40474c1a78fa53ebfadf", "Skill Screen Games, Herman Quast", "SSG001", "Extra Terrestrials (1984) (SSG)", "The only Canadian-designed and manufactured Atari 2600 game from the 1980's", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebdc5716b85c4ff44fa357cb697d6cef", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebf2dff78a08733251bf3838f02f7938", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a2]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ebf9038e927e6a0db3e0d170c59911e6", "", "", "Pac-2600 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ec3beb6d8b5689e867bafb5d5f507491", "U.S. Games Corporation - Vidtec - JWDA, Todd Marshall, Henry Will IV", "VC1003", "Word Zapper (1982) (U.S. Games)", "AKA Word Grabber", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ec407a206b718a0a9f69b03e920a0185", "Quelle", "876.482 1", "Landung in der Normandie (1983) (Quelle) (PAL)", "AKA Commando Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ec5c861b487a5075876ab01155e74c6c", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2001", "Spacechase (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ece463abde92e8b89bcd867ec71751b8", "Puzzy - Bit Corporation", "PG205", "Dancing Plate (1982) (Puzzy) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ece908d77ab944f7bac84322b9973549", "", "", "Tom Boy (Unknown) (PAL60)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "ecf51385384b468834611d44a8429c03", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11105", "Mega Force (1982) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ecfa04523dde82fe42cdc7315a8f61b6", "Activision, David Crane - Ariola", "EAG-004, PAG-004 - 711 004-715", "Fishing Derby (1980) (Activision) (PAL) (4K)", "AKA Schneller als der Hai", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed014beeeb77dbb2bbcf9b5f6850b2f4", "", "", "Green Bar Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed0451010d022b96a464febcba70b9c4", "PlayAround - J.H.M.", "203", "Knight on the Town (1982) (PlayAround) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ed0ab909cf7b30aff6fc28c3a4660b8e", "Panda", "105", "Stunt Man (1983) (Panda)", "AKA Nightmare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed1306436ce237afc5a7ed3f77134202", "HES", "771-341", "2 Pak Special - Dolphin, Pigs n' Wolf (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed1492d4cafd7ebf064f0c933249f5b0", "CCE", "", "Video Cube (CCE)", "AKA Atari Video Cube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed1a784875538c7871d035b7a98c2433", "Bit Corporation", "R320", "Save Our Ship (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed2218b3075d15eaa34e3356025ccca3", "Atari, Richard Maurer", "CX2635, CX2635P", "Maze Craze (1980) (Atari) (PAL)", "AKA A Game of Cops 'n Robbers", "", "", "", "", "", "", "", "", "", "", "", "", "PAL", "", "", "", "", "", "", "" }, - { "ed5ccfc93ad4561075436ee42a15438a", "Atari, Tom Reuterdahl", "CX2626, CX2626P", "Miniature Golf (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ed8f319e82d355832195eb7715644795", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (8K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "eddef10fdc0029301064115ae0cd41d4", "CCE", "", "Freeway (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ede4ab11ca346bd023b2c21d941e0c50", "Activision, David Crane", "EAZ-030", "Decathlon (1983) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "SECAM", "", "", "", "", "", "", "" }, - { "ede7e8bf865b0afb4744f86d13624f9a", "", "", "Demo Image Series #2 - Clown (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "edf69b123e06eaf8663cc78d8aeba06e", "SpkSoft 98", "", "River Raid (SpkSoft 98) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee28424af389a7f3672182009472500c", "Atari, Carol Shaw - Ralph Lauren", "", "Polo (1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee456542b93fa8d7e6a8c689b5a0413c", "", "", "Chronocolor Donkey Kong Clean (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee4c186123d31a279ed7a84d3578df23", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner", "CX2608", "Super Breakout (1982 - 1981) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, - { "ee659ae50e9df886ac4f8d7ad10d046a", "Exus Corporation", "", "Video Reflex (1983) (Exus)", "AKA Foot Craz", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee6665683ebdb539e89ba620981cb0f6", "Coleco", "2658", "Berenstain Bears (1983) (Coleco)", "Uses the KidVid Controller", "Unbelievably Rare", "", "", "", "A", "", "", "", "", "KIDVID", "", "", "", "", "", "", "", "", "", "" }, - { "ee67dc0b01746372d2b983d88f48e24f", "", "", "Scroller Demo (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee681f566aad6c07c61bbbfc66d74a27", "Activision", "", "Unknown Activision Game (10-29-1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee6cbedf6c0aac90faa0a8dbc093ffbe", "CCE", "", "My Golf (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee8027d554d14c8d0b86f94737d2fdcc", "Canal 3 - Intellivision", "", "Yars' Revenge (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "ee84bdc5dae268e227e407c7b5e6b6b7", "", "", "Marilyn Monroe Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ee9caee4eb958284fb10c277b14537f1", "Carrere Video, Garry Kitchen - Teldec", "USC1001", "Space Jockey (1983) (Carrere Video) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eea0da9b987d661264cce69a7c13c3bd", "Coleco", "2454", "Zaxxon (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eeb92f3f46df841487d1504f2896d61a", "Cody Pittman", "", "Corys Adventure (Cody Pittman) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eec61cc4250df70939d48fe02d7122ac", "Activision, Bob Whitehead - Ariola", "EAG-005, PAG-005, EAG-005-04B - 711 005-715", "Skiing (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eed9eaf1a0b6a2b9bc4c8032cb43e3fb", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "eee7695ae3eea7818321df0b790b31f3", "", "", "Sound Paddle V2 (Dennis Caswell & Jim Nitchals) (PD)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "ef263d40a23483ab339cac44d9515a56", "Thomas Jentzsch", "", "Fatal Run (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ef3a4f64b6494ba770862768caf04b86", "Activision, Bob Whitehead", "AG-034-04", "Private Eye (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ef60b06fddb675b0d783afbfa5fc5232", "", "", "Many Blue Bars and Text Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ef66af190840871409fe1702d2483554", "Andrew Davie, Paul Slocum, Christopher Tumber", "", "DiscoTech (12-02-2003) (Andrew Davie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ef71e9fb0d8d477226d8d42261fbf0a7", "Piero Cavina", "", "Multi-Sprite Demo V2.0 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ef76ea05655a0b62cb1018c92b9b4b7d", "Gakken", "010", "Strategy X (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "efa1098c7d091b940c2543abe372f036", "Scott Stilphen", "", "E.T. The Extra-Terrestrial (Scott Stilphen) (Hack)", "Hack of E.T. The Extra-Terrestrial", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "efb47d70b2965ce689e2c5757616b286", "", "", "Time Test Demo (Eckhard Stolberg) (PAL) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "efd387430a35a659ff569a9a0ec22209", "Atari - GCC", "CX26118", "Millipede (1984) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "efefc02bbc5258815457f7a5b8d8750a", "CBS Electronics, Richard K. Balaska Jr.", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "effa3a7ce078c6d83bf43174a7bfdb1f", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "efffafc17b7cb01b9ca35324aa767364", "", "", "Circus Atari (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f02ba8b5292bf3017d10553c9b7b2861", "Atari", "CX26172", "Xenophobe (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f032b2f2d8323404a6b4541f92dd1825", "", "", "Many Blue Bars and Text Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f047df70d3d08e331122cd2de61d6af8", "Dave Neuman", "", "Space Battle (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f04ee80011d95798006378643650aaa7", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0510abbfbe24ead552e92e3841f63f3", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0536303f49006806bac3aec15738336", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (4 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0541d2f7cda5ec7bab6d62b6128b823", "Atari, Paul Donaldson", "", "Bionic Breakthrough (1984) (Atari) (Prototype)", "Uses Mindlink Controller (left only)", "Prototype", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "", "" }, - { "f060826626aac9e0d8cda0282f4b7fc3", "Atari, David Crane - Sears", "CX2605 - 6-99822, 49-75109", "Outlaw (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0631c6675033428238408885d7e4fde", "Paul Slocum", "", "Test Cart (2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f066bea7ab0a37b83c83c924a87c5b67", "", "", "Air Raiders (1982) (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0a6e99f5875891246c3dbecbf2d2cea", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0b7db930ca0e548c41a97160b9f6275", "Atari, Larry Wagner, Bob Whitehead - Sears", "CX2645 - 49-75181", "Video Chess (1979) (Atari)", "AKA Computer Chess", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0cacae1d1b79ee92f0dc035f42e0560", "", "", "Boring Donkey Kong (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0d393dbf4164a688b2346770c9bbd12", "", "", "Racquetball (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f0daaa966199ef2b49403e9a29d12c50", "", "", "Mr. Postman (Unknown)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0de4f49e95d529569e8788d5a7b4d30", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, - { "f0e0addc07971561ab80d9abe1b8d333", "Imagic, Rob Fulop", "720000-200, 720101-1B, 720101-1C, IA3200, IA3200C, IX-006-04", "Demon Attack (1982) (Imagic)", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f0ef9a1e5d4027a157636d7f19952bb5", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a5]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f10e3f45fb01416c87e5835ab270b53a", "Suntek", "SS-024", "Ski Run (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1127ade54037236e75a133b1dfc389d", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (Preview) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f11cfab087fcbd930ab8b0becc5b2e5a", "Canal 3 - Intellivision", "", "River Raid (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f12afbffa080dd3b2801dd14d4837cf6", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f137211537438b1fce3d811baef25457", "", "", "Incoming (02-10-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1489e27a4539a0c6c8529262f9f7e18", "Champ Games", "CG-01-P", "Lady Bug (PAL60)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "f14d5e96ec3380aef57a4b70132c6677", "Goliath - Hot Shot", "83-414", "Pac Kong (1983) (Goliath) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1554569321dc933c87981cf5c239c43", "Atari - Glenn Axworthy", "CX26129", "Midnight Magic (1986) (Atari)", "AKA Pinball Wizard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f16c709df0a6c52f47ff52b9d95b7d8d", "Atari, Alan Miller - Sears", "CX2662 - 6-99811", "Hangman (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f16ef574d2042ed8fe877d6541f4dba4", "Spectravision - Spectravideo", "SA-201", "Gangster Alley (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1929bb9b5db22d98dd992aa3fe72920", "", "", "Cube Conquest (Improved Interlace) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f19aba18f86e415812480ad2be221425", "Chris Larkin", "", "Solaris Trainer (2002) (Chris Larkin) (Hack)", "Hack of Solaris", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1a0a23e6464d954e3a9579c4ccd01c8", "20th Century Fox, Douglas 'Dallas North' Neubauer", "11006", "Alien (1982) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f1ae6305fa33a948e36deb0ef12af852", "Andreas Dietrich", "", "Donkey Kong VCS (2017) (1.0)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f1b2ea568b3e156e3f2849dac83591f6", "", "", "Sprite Demo (1997) (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1b7edff81ceef5af7ae1fa76c8590fc", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1beca5a198cf08190487e5c27b8e540", "", "", "Fu Kung! (V0.16) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1e375d921858467166e53bcec05803f", "Jeffry Johnston", "", "Radial Pong - Version 3 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f1eeeccc4bba6999345a2575ae96508e", "Video Gems", "VG-03", "Steeplechase (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f1fe06ebe2900eac4cdd17799389a102", "Atari, Jim Huether", "CX26163P", "Sky Diver (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f20675c8b98518367b9f5b8ee6f7c8ea", "Atari", "CX26163P", "Stampede (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f20bd756f3990e06c492f53cd0168e68", "", "", "Skeleton+ (03-05-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f21813aa050437f0dbc8479864acec6d", "", "", "Sneak 'n Peek (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f23d19b73dac50cc6149316912b8ee53", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (PAL) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f240ba9f8092d2e8a4c7d82c554bf509", "Quelle", "463.860 7", "Strahlen der Teufelsvoegel (1983) (Quelle) (PAL)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f280976d69d6e27a48506bd6bad11dcd", "Atari, Larry Kaplan", "CX2664, CX2664P", "Brain Games (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "f283cc294ece520c2badf9da20cfc025", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (1983) (Atari) (PAL)", "Uses Kids/Keypad Controllers", "Rare", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "f28c07767b3e90a2689ade5b5e305874", "Canal 3 - Intellivision", "C 3014", "Keystone Kapers (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f2d40c70cf3e1d03bc112796315888d9", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari) (PAL)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f2d4d6187903cac2d5ea8ed90dad120d", "Digimax", "", "River Raid II (Digimax)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f2e4fb2d3600c0f76d05864e658cc57b", "", "", "Marble Craze (Kernel) (17-02-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f2f2cb35fdef063c966c1f5481050ea2", "", "", "Ram It (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f2f59629d7341c97644405daeac08845", "Jone Yuan Telephonic Enterprise Co", "", "Bobby Is Going Home (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f303630a2d7316787aecd67fff6b2e33", "AtariAge - Fred Quimby", "", "Gingerbread Man (Fred Quimby)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3213a8a702b0646d2eaf9ee0722b51c", "Atari, Carol Shaw - Sears", "CX2618 - 49-75123", "3-D Tic-Tac-Toe (1980) (Atari) (4K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f33f1d0f7819c74148dacb48cbf1c597", "Retroactive", "", "Qb (2.00) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f344ac1279152157d63e64aa39479599", "Tigervision", "7-012", "Espial (1984) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f34dd3b8156aaf113cb621b2e51d90b8", "Joe Grand", "", "SCSIcide Pre-release 5 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f34f08e5eb96e500e851a80be3277a56", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, - { "f367e58667a30e7482175809e3cec4d4", "ZiMAG - Emag - Vidco", "708-111 - GN-040", "Cosmic Corridor (1983) (ZiMAG)", "AKA Space Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f38358cd8f5ecfedffd5aca1aa939f18", "Universal Gamex Corporation, Alan Roberts", "1005", "X-Man (1983) (Universal) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f39e4bc99845edd8621b0f3c7b8c4fd9", "AtariAge", "", "Toyshop Trouble (AtariAge)", "F8 Emulator Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3c431930e035a457fe370ed4d230659", "", "", "Crackpots (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3cd0f886201d1376f3abab2df53b1b9", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3dfae774f3bd005a026e29894db40d3", "Otto Versand", "649635", "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3f5f72bfdd67f3d0e45d097e11b8091", "Sears Tele-Games, Marilyn Churchill, Matthew L. Hubbard", "CX2647 - 49-75142", "Submarine Commander (1982) (Sears)", "AKA Seawolf 3", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f3f92aad3a335f0a1ead24a0214ff446", "", "", "Spectrum Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f40e437a9ebf0bdfe26204152f74f868", "Bit Corporation", "R320", "Jawbreaker (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4204fc92d17ed4cb567c40361ad58f1", "Inky", "", "Beanie Baby Bash (Inky) (Hack)", "Hack of Beany Bopper", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4469178cd8998cb437fa110a228eaca", "Digitel", "", "Frostbite (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f45644ff82b533a781a1ee50f2e95f3c", "", "", "Overhead Adventure Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f457674cef449cfd85f21db2b4f631a7", "U.S. Games Corporation - JWDA, Todd Marshall, Wes Trager, Henry Will IV", "VC1004", "Commando Raid (1982) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f473f99e47d4026a7a571184922ebf04", "Philip R. Frey", "", "Donkey Claus (Philip R. Frey) (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f48022230bb774a7f22184b48a3385af", "Atari, Rob Fulop - Sears", "CX2633 - 49-75119", "Night Driver (1980) (Atari) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "f48735115ec302ba8bb2d2f3a442e814", "", "", "Dancing Plate (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f49a34f1fdd7dc147cbf96ce2ce71b76", "", "", "Qb (Special Edition) (PAL) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f4a09f906cc37be31224433f576d77d3", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4ab6bd5f80d8988141edde4c84b23b5", "Atari, Alan Miller", "CX2624, CX2624P", "Basketball (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4b8a47a95b61895e671c3ec86ffd461", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (01-03-1984) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f4c2e50b01dff99bddbe037b3489511c", "", "", "Hypnotic (V0.04) (2001) (Inkling) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4c6621f1a0b4d27081123c08d7d1497", "CCE", "C-838", "Immies & Aggies (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4cf6881b65c424095dc25dc987f151f", "", "", "128 in 1 Game Select ROM (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f4dabd5bcc603e8464a478208037d423", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (08-21-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f526d0c519f5001adb1fc7948bfbb3ce", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1003", "Star Fox (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f52f40299fd238c6ffd9e6107050dc76", "Activision, Bob Whitehead - Ariola", "EAG-011, PAG-011 - 711 011-715", "Stampede (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f539e32bf6ce39c8ca47cb0cdd2c5cb8", "Control Video Corporation", "", "GameLine Master Module ROM (1983) (Control Video)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f542b5d0193a3959b54f3c4c803ba242", "Atari, Tom Rudadahl - Sears", "CX2634 - 49-75121", "Golf (1980) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f5445b52999e229e3789c39e7ee99947", "Atari, Jim Huether", "CX26163P", "Flag Capture (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f5a2f6efa33a3e5541bc680e9dc31d5b", "Suntek", "SS-022", "Motocross (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f5a3e051730d45fea518f2e8b926565b", "Robby", "", "Keystone Kapers (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f5aa6bd10f662199c42e43863a30106c", "", "", "Music Kit (V1.0) - Song Player (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f5d103a9ae36d1d4ee7eef657b75d2b3", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (Preview) (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f613aad84d2163d6b197b220bfec1b7e", "", "", "X-Doom V.27 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f661f129644f338b13d9f4510d816c03", "Atari, David Crane", "CX26163P", "Outlaw (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6676e3fe901eb8515fc7ae310302c3c", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f67181b3a01b9c9159840b15449b87b0", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (08-27-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f687ec4b69611a7f78bd69b8a567937a", "Activision, Alan Miller - Ariola", "EAZ-028 - 711 028-725", "Robot Tank (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f69a39b215852a0c2764d2a923c1e463", "", "", "Move a Blue Blob Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f69bb58b815a6bdca548fa4d5e0d5a75", "Atari, Larry Kaplan", "CX26163P", "Bowling (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f69d4fcf76942fcd9bdf3fd8fde790fb", "CCE", "", "Aquaventure (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6a282374441012b01714e19699fc62a", "ZiMAG - Emag - Vidco", "710-111 - GN-010", "I Want My Mommy (1983) (ZiMAG)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f6a9ea814d15b85bffe980c927df606b", "", "", "Missile Command (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f6b5ebb65cbb2981af4d546c470629d7", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype) [a]", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6c13e816e58c8c62f82b2c8b91a2d67", "", "", "Scrolling Playfield 2 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6d512bef1bf253dc935d0e13c3d1462", "", "", "Slot Racers (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6daebc0424fa0f8d9aaf26c86df50f4", "Brian Watson", "", "Color Tweaker (V1.0) (2001) (B. Watson)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6efa00ae99aaf33e427b674bcfd834d", "", "", "2600 Digital Clock (Demo 3) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f6f1b27efc247a0e8d473ddb4269ff9e", "Rainbow Vision - Suntek", "SS-015", "Catch Time (1983) (Rainbow Vision) (PAL)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f70e3f3bb2d19ec2aaec8f78dc43744f", "Jone Yuan Telephonic Enterprise Co", "", "Pooyan (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f714a223954c28eccf459295517dcae6", "", "", "Big - Move This Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7154add27b95cd90464dbed8cfd7557", "Fabrizio Zavagli", "", "Space Treat Deluxe (2003) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f724d3dd2471ed4cf5f191dbb724b69f", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (1982) (Atari)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f736864442164b29235e8872013180cd", "Telegames - VSS", "6057 A227", "Quest for Quintana Roo (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f73d2d0eff548e8fc66996f27acf2b4b", "CCE", "C-813", "Pitfall (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7424985bac41067502b4a05b64cb75a", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision)", "Genesis controller (B is fire up, C is fire down)", "Hack of Plaque Attack", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "f74ad642552385c3daa203a2a6fc2291", "Eckhard Stolberg", "", "Cubis (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f750b5d613796963acecab1690f554ae", "Manuel Polik", "", "Gunfight 2600 (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f75872946e82ad74d48eae5bc28f5f0e", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (04-15-1980) (Sears) (Prototype)", "Uses the Paddle Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f777444fc21a5925e066b68b1d350575", "", "", "Marble Craze (Kernel Works) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f77f5fc3893da5d00198e4cd96544aad", "Canal 3 - Intellivision", "", "Stampede (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7856e324bc56f45b9c8e6ff062ec033", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari) [no opening tune]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f78c125b5da483c41e51522947d6c4ce", "", "", "Sound Paddle V1 (Dennis Caswell & Jim Nitchals) (PD)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "", "01", "", "", "", "", "", "", "", "" }, - { "f7a138eed69665b5cd1bfa796a550b01", "Tigervision - Teldec", "7-012 - 3.60016 VC", "Espial (1984) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7a651972d78f9ba485b14690452d4be", "Paul Slocum", "", "Homestar Runner Demo #2 (2004-03-29)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f7af41a87533524d9a478575b0d873d0", "Quelle", "495.663 7", "Spiderman (1983) (Quelle) (PAL)", "AKA Spider-Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7d6592dcb773c81c278140ed4d01669", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7e07080ed8396b68f2e5788a5c245e2", "Video Game Cartridge - Ariola", "TP-617", "Farmyard Fun (Ariola)", "AKA Play Farm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7f50d9c9d28bcc9f7d3075668b7ac89", "Activision, David Crane - Ariola", "EAG-008, PAG-008, EAG-008-04I - 711 008-720", "Laser Blast (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f7fac15cf54b55c5597718b6742dbec2", "Spiceware", "SW-01", "Medieval Mayhem (NTSC)", "", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, - { "f802fa61011dd9eb6f80b271bac479d0", "Suntek", "SS-023", "Mole Hunter (1983) (Suntek) (PAL)", "AKA Topy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f80cf77164079d774b9b0fae33dffca9", "", "", "Fu Kung! (V0.15) (Negative Version) (05-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8240e62d8c0a64a61e19388414e3104", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f825c538481f9a7a46d1e9bc06200aaf", "Atari, Richard Maurer - Sears", "CX2635 - 49-75157", "Maze Craze (1980) (Atari)", "AKA A Game of Cops 'n Robbers", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC", "", "", "", "", "", "", "" }, - { "f844f4c6f3baaaf5322657442d6f29eb", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f847fb8dba6c6d66d13724dbe5d95c4d", "Absolute Entertainment, David Crane", "AG-042-02, AG-042-04", "Skate Boardin' (1987) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8582bc6ca7046adb8e18164e8cecdbc", "", "", "Panda Chase (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8648d0c6ad1266434f6c485ff69ec40", "CCE", "", "Oink! (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8811d45a9935cca90c62f924712f8e6", "Jone Yuan Telephonic Enterprise Co", "", "Chopper Command (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8b2a6a4d73ebff10d805a9b59041986", "Activision, Larry Kaplan - Ariola", "EAX-006, PAX-006 - 771 006-720", "Bridge (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8bfd99163d2c4ec688357786e6fba28", "", "", "Eckhard Stolberg's Scrolling Text Demo 2 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8c1c4a41303bd40b0d6c81bfaf8573b", "HES", "773-891", "2 Pak Special - Dungeon Master, Creature Strike (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8fbe2b07345086fc867bceeaf38dc48", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f8ff34b53d86f55bd52d7a520af6d1dc", "", "", "Big Dig (04-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f90b5da189f24d7e1a2117d8c8abc952", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f91fb8da3223b79f1c9a07b77ebfa0b2", "Atari, Alan J. Murphy, Nick 'Sandy Maiwald' Turner - Sears", "CX2615 - 49-75140", "Demons to Diamonds (1982) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "10 57", "", "", "", "", "", "", "", "" }, - { "f93d7fee92717e161e6763a88a293ffa", "20th Century Fox Video Games - Lazer Micro Systems - Dunhill Electronics, B. Winston Hendrickson, Randall Hyde, Mark V. Rhoads, John Simonds", "11013", "Porky's (1983) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9420173efcb4b9f2b01c2a7b595cca7", "CCE", "", "Laser Blast (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f954381f9e0f2009d1ac40dedd777b1a", "Thomas Jentzsch", "", "Robot City (V0.18) (01-09-2002) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9655ed51462ecfc690c7b97cec649f9", "Andrew Wallace", "", "Laseresal 2002 (PAL) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f965cc981cbb0822f955641f8d84e774", "Answer Software Corporation - TY Associates, Kim Ellis", "ASC2001", "Confrontation (1983) (Answer) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "f9660ebed66fee8bdfdf07b4faa22941", "VGS", "", "Vanguard (VGS)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9677b2ec8728a703eb710274474613d", "Atari, Ian Shepard", "CX2604, CX2604P", "Space War (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f97dee1aa2629911f30f225ca31789d4", "Avalon Hill, Jean Baer, Bill 'Rebecca Ann' Heineman, Jim Jacob", "5005002", "Out of Control (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f98d2276d4a25b286135566255aea9d0", "Digitel", "", "Name This Game (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f98d869f287d2ce4f8fb36e0686929d9", "", "", "Skeleton+ (17-04-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f991e0670b5f67faa6b6211e9bd81b91", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) (PAL) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f992a39b46aa48188fab12ad3809ae4a", "", "", "Sky Jinks (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9967369943209b4788d4e92cefc0795", "Atari", "CX26163P", "Fishing (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9cef637ea8e905a10e324e582dd39c2", "CCE", "", "Private Eye (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9d51a4e5f8b48f68770c89ffd495ed1", "Atari, Tod Frye, Mimi Nyden", "CX2657", "SwordQuest - FireWorld (1982) (Atari)", "AKA Adventure II, SwordQuest II - FireWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9da42f91a1c5cfa344d2ff440c6f8d4", "ZUT", "", "Pac Invaders (ZUT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9de91d868d6ebfb0076af9063d7195e", "", "", "Maze Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "f9e99596345a84358bc5d1fbe877134b", "Activision, Larry Kaplan, David Crane - Ariola", "EAG-010, PAG-010 - 711 010-720", "Kaboom! (1981) (Activision) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, - { "fa0570561aa80896f0ead05c46351389", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa1b060fd8e0bca0c2a097dcffce93d3", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (1984) (Atari)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "" }, - { "fa2be8125c3c60ab83e1c0fe56922fcb", "Camelot - DSD, Michael Doherty, Clyde Hager - Johnson & Johnson", "", "Tooth Protectors (1983) (Camelot)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fa3de71841c0841db6a741884a6b6b2f", "", "", "Warring Worms (17-02-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa4404fabc094e3a31fcd7b559cdd029", "Atari, Alan J. Murphy, Robert C. Polaro", "CX26100", "Bugs Bunny (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa529ec88eca679f6d5fd0ccb2120e46", "", "", "20 Sprites at Once Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa6fe97a10efb9e74c0b5a816e6e1958", "ZiMAG - Emag - Vidco", "707-111 - GN-030", "Tanks But No Tanks (1983) (ZiMAG)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa7ce62e7fd77e02b3e2198d70742f80", "Atari, Peter C. Niday", "CX26108", "Donald Duck's Speedboat (04-18-1983) (Atari) (Prototype) (PAL)", "AKA Donald Duck's Regatta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa7e11a3dbea4365975cd2f094e61d25", "Tim Snider", "", "Mystery Science Theater 2600 (1999) (Tim Snider) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fa98d48cd609c9babc819e0a1bd8d598", "AtariAge (Chris Walton)", "", "Juno First (2009) (PAL60)", "AtariVox supported", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "PAL60", "", "YES", "", "", "", "", "" }, - { "fab7b04b9f42df761eb6f2bc445eaa99", "20th Century Fox Video Games - Sirius Software, David Lubar", "11008", "Fantastic Voyage (11-04-1982) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fabca526d57de46768b392f758f1a008", "", "", "Laseresal 2600 (16-12-2001) (Andrew Wallace) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fac28963307b6e85082ccd77c88325e7", "CCE", "", "Berzerk (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fadb89f9b23beb4d43a7895c532757e2", "Galaga Games", "", "River Raid (1984) (Galaga Games) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fae0b86934a7c5a362281dffebdb43a0", "Retroactive", "", "Qb (2.07) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "faebcb2ef1f3831b2fc1dbd39d36517c", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1984) (Atari) (PAL)", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "faed2ef6b44894f8c83f2b50891c35c6", "CCE", "", "Super Baseball (CCE)", "AKA RealSports Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "faffd84f3a8eceee2fa5ea5b0a3e6678", "Suntek", "SS-025", "Spectracube Invasion (1983) (Suntek) (PAL)", "AKA Immies & Aggies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb09ee4ccd47ae74a3c314f0d8a40344", "", "", "Titans (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb0c32ef7af5b45486db663510094be8", "", "", "Demo Image Series #15 - Three Marios (NTSC) (Non-Interleave) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb0e84cee4c108d24253bcb7e382cffd", "", "", "Interleaved ChronoColour Demo (SECAM) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb27afe896e7c928089307b32e5642ee", "M Network - INTV - APh Technological Consulting, Jeff Ronne, Brett Stutz", "MT5662", "TRON - Deadly Discs (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb4ca865abc02d66e39651bd9ade140a", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb531febf8e155328ec0cd39ef77a122", "", "", "Worm War I (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fb5c8af97bd8ffe88323656f462645a7", "", "", "Interlace Demo (Glenn Saunders)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fb833ed50c865a9a505a125fc9d79a7e", "ITT Family Games", "", "Pumuckl I (1983) (ITT Family Games) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb884ffd89013331a6f01ae3f6abd214", "Activision, David Crane", "", "Venetian Blinds Demo (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb88baa01afd34e0e4b601e1d29bc806", "Manuel Polik", "", "Star Fire (2003) (XYPE)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb88c400d602fe759ae74ef1716ee84e", "20th Century Fox Video Games, Bill Aspromonte", "11031", "Crash Dive (1983) (20th Century Fox)", "AKA Voyage to the Bottom of the Sea", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb91da78455d9b1606913fbf8c859772", "", "", "Split Screen (Ballblazer) Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fb91dfc36cddaa54b09924ae8fd96199", "Parker Brothers, Mark Lesser", "PB5590", "Frogger II (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fb978f1c053e8061cc37a726639f43f7", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fbac6476e7b2b20d246202af81662c88", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (Preview) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fbb0151ea2108e33b2dbaae14a1831dd", "Thomas Jentzsch", "", "Robot Tank TV (Thomas Jentzsch) (Hack)", "Uses two simultaneous Joystick Controllers, Hack of Robot Tank", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fbb4f3debf48dc961b559384467f2057", "Digitel", "", "River Raid III (1985) (Digitel)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fbe554aa8f759226d251ba6b64a9cce4", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fbfebee9c14694719e3eda4854dc42ee", "Jake Patterson", "", "Baubles 3 (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc2104dd2dadf9a6176c1c1c8f87ced9", "Coleco - Woodside Design Associates, Harley H. Puthuff Jr.", "2663", "Time Pilot (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc2233fc116faef0d3c31541717ca2db", "Atari, Tod Frye", "CX2646", "Pac-Man (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc24a94d4371c69bc58f5245ada43c44", "Atari - Axlon, Steve DeFrisco", "CX26170", "Secret Quest (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc6052438f339aea373bbc999433388a", "Atari, David Crane", "CX2653P", "Slot Machine (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc668a2251dd79cbd903d4fa0e558f96", "Thomas Jentzsch", "", "Thrust (V1.1) (2000) (TJ) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc92d74f073a44bc6e46a3b3fa8256a2", "", "", "Megademo (19xx) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fc9c1652fe3a2cade6188f4d3692481f", "Andrew Davies", "", "Andrew Davies early notBoulderDash demo (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fca4a5be1251927027f2c24774a02160", "Activision, John Van Ryzin", "AZ-036-04", "H.E.R.O. (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fcbbd0a407d3ff7bf857b8a399280ea1", "ZiMAG - Emag - Vidco", "GN-070", "Mysterious Thief, A (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fcbdf405f0fc2027b0ea45bb5af94c1a", "Amiga - Video Soft, Michael K. Glass, Jerry Lawson", "", "3-D Ghost Attack (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fcea12625c071ddc49f4e409f4038c60", "Fabrizio Zavagli", "", "Balls! (16-09-2002) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, - { "fcf8e306f6615f74feba5cb25550038c", "", "", "Blue Dot Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd0e5148162e8ec6719445d559f018a9", "Activision, Steve Cartwright - Ariola", "EAX-022, EAX-022-04I - 711 022-720", "Seaquest (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd10915633aea4f9cd8b518a25d62b55", "Atari, John Dunn", "CX2631, CX2631P", "Superman (1979) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd16949913aaab5beaefed73bf2ca67c", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (02-03-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd4f5536fd80f35c64d365df85873418", "Atari - Bobco, Robert C. Polaro", "CX26140", "Desert Falcon (1987) (Atari)", "AKA Nile Flyer, Sphinx", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd6e507b5df68beeeddeaf696b6828fa", "", "", "Boxing (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd7464edaa8cc264b97ba0d13e7f0678", "HES", "771-333", "2 Pak Special - Challenge, Surfing (1990) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd78f186bdff83fbad7f97cb583812fe", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) [a2]", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd8b4ee0d57605b35e236e814f706ff1", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673, CX2673P", "Phoenix (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fd9b321cee5fbb32c39ba3ca5d9ec7cf", "Jeffry Johnston", "", "Radial Pong - Version 5 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fdd4995a50395db14f518f63c2d63438", "", "", "Oh No! (Version 3) (18-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fde42e39710e75e9e4d4d75440f8e4e5", "Thomas Jentzsch", "", "Coke Zero (v1.0) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fdf0de38517e0cf7f0885f98ccc95836", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (2 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fdf6680b2b1e8054293a39700a765692", "", "", "Alpha Demo - The Beta Demo 2 (2000) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe0b7f27e3ad50bbf9ff468ee56d553d", "", "", "Lines Demo (Eckhard Stolberg) (PAL) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe0bc4bb92c1c4de7d5706aaa8d8c10d", "", "", "Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe3b461d4c8b179fe68bc77760294c25", "Atari, Joe Decuir", "CX2621, CX2621P", "Video Olympics (1977) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "", "", "", "", "", "", "", "", "" }, - { "fe641247a4ab9bee970e19ab55f23b25", "20th Century Fox Video Games, Beck-Tech, Steve Beck", "11035", "Save the Whales (02-07-1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe67087f9c22655ce519616fc6c6ef4d", "Atari - Zip Technology, Randy Bowker, Bruce Williams", "CX26142", "Crack'ed (11-28-1988) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe6abc0f63e31e2646c9c600926b5b7f", "Atari", "CX26137", "4 in 1 (02-19-1987) (Atari) (Prototype)", "Home Run, Canyon Bomber, Sky Diver, Night Driver", "Prototype", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe870018332a0221eb59fb18b0c6bccc", "", "", "Incoming (08-11-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fe9ae625d924b54c9f8a14ac9a0f6c6d", "BG Dodson", "", "High Bid! (BG Dodson) (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "feba8686fd0376015258d1152923958a", "", "", "Super Circus (Unknown) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fec0c2e2ab0588ed20c750b58cf3baa3", "Activision - Cheshire Engineering, David Rolfe, Larry Zwick", "EAZ-037-04, EAZ-037-04I", "Beamrider (1984) (Activision) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "fece458a8023a809a5006867feca40e8", "", "", "SCSIcide (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "feec54aac911887940b47fe8c9f80b11", "Atari, Rob Fulop", "CX2633, CX2633P", "Night Driver (1980) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, - { "feedcc20bc3ca34851cd5d9e38aa2ca6", "Atari, David Crane - Sears", "CX2607 - 6-99828, 49-75115", "Canyon Bomber (1979) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "10", "", "", "", "", "", "", "", "" }, - { "ff1523783e0e76a3b0d1f7f0d1cb3050", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (PAL) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ff3bd0c684f7144aeaa18758d8281a78", "Atari, Bob Whitehead", "CX2651", "Blackjack (1977) (Atari) (PAL)", "Uses the Paddle Controllers", "Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "ff5a9e340d96df6f5a5b6eb038e923bd", "", "", "Space Shuttle (1983) (Activision) [t1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ff7627207e8aa03730c35c735a82c26c", "Atari, Bob Whitehead", "CX26163P", "Blackjack (32 in 1) (1988) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "" }, - { "ff86fc8ffa717bb095e8471638c1c31c", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, - { "ff87d58125ae517eb7b09a0475a1ccdc", "", "", "SCSIcide (Score Hack 1) (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ffb1cd548563158ce33f9d10268187e7", "Erik Eid", "", "Euchre (Beta) (NTSC) (12-09-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ffc0ff4305dd46b4b459885bd1818e2e", "Barry Laws Jr.", "", "Star Wars - The Battle of Alderaan (Star Strike Hack)", "Hack of Star Strike (Mattel)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ffdc0eb3543404eb4c353fbdddfa33b6", "CCE", "C-827", "Chopper Command (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ffe51989ba6da2c6ae5a12d277862e16", "Atari - Sears", "CX2627 - 6-99841", "Human Cannonball (1979) (Atari) (4K)", "AKA Cannon Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, - { "ffebb0070689b9d322687edd9c0a2bae", "", "", "Spitfire Attack (1983) (Milton Bradley) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" } +static const BSPF::array2D DefProps = {{ + { "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0060a89b4c956b9c703a59b181cb3018", "CommaVid, Irwin Gaines - Ariola", "CM-008 - 712 008-720", "Cakewalk (1983) (CommaVid) (PAL)", "AKA Alarm in der Backstube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "007d18dedc1f0565f09c42aa61a6f585", "CCE", "C-843", "Worm War I (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "008543ae43497af015e9428a5e3e874e", "Retroactive", "", "Qb (V2.09) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "00b7b4cbec81570642283e7fc1ef17af", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "006-01", "Congo Bongo (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00ce0bdd43aed84a983bef38fe7f5ee3", "20th Century Fox, Bill Aspromonte", "11012", "Bank Heist (1983) (20th Century Fox)", "AKA Bonnie and Clyde, Cops 'n' Robbers, Holdup, Rooring 20's", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00ce76ad69cdc2fa36ada01ae092d5a6", "Bit Corporation", "PGP214", "Cosmic Avenger (4 Game in One) (1983) (BitCorp) (PAL)", "AKA StarMaster", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00dc28b881989c39a6cf87a892bd3c6b", "CCE", "", "Krull (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00e19ebf9d0817ccfb057e262be1e5af", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL) [no grid markers]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00e55b27fe2e96354cd21b8b698d1e31", "", "", "Phoenix (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00eaee22034aff602f899b684c107d77", "Rainbow Vision - Suntek - Sunteck Corp", "SS-001", "Time Race (1983) (Rainbow Vision) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "00f7985c20b8bdf3c557fac4d3f26775", "Aaron Curtis", "", "AStar (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "012020625a3227815e47b37fd025e480", "Rob Kudla", "", "Better Space Invaders (1999) (Rob Kudla) (Hack) [a]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01293bd90a4579abb7aed2f7d440681f", "Century", "", "Snoopy (1983) (Century) (PAL)", "AKA Snoopy and the Red Baron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01297d9b450455dd716db9658efb2fae", "TechnoVision - Video Technology", "TVS1002", "Save Our Ship (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "012b8e6ef3b5fd5aabc94075c527709d", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (1983) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, + { "0164f26f6b38a34208cd4a2d0212afc3", "Coleco, Ed English", "2656", "Mr. Do! (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0173675d40a8d975763ee493377ca87d", "CBS Electronics, Ed English", "4L1751", "Roc 'n Rope (1984) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01abcc1d2d3cba87a3aa0eb97a9d7b9c", "Jone Yuan Telephonic Enterprise Co", "", "Topy (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01b09872dcd9556427761f0ed64aa42a", "Galaga Games", "", "River Raid (1984) (Galaga Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01cb3e8dfab7203a9c62ba3b94b4e59f", "Atari, Mimi Nyden, Scott Smith, Robert Vieira", "CX26127", "Gremlins (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01e5c81258860dd82f77339d58bc5f5c", "CCE", "", "Corrida da Matematica (CCE)", "AKA Math Gran Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01e60a109a6a67c70d3c0528381d0187", "ITT Family Games, Perry Rhodan-Serie", "554-33 383", "Fire Birds (1983) (ITT Family Games) (PAL)", "AKA Sky Alien", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "01f584bf67b0e464014a8c8b5ea470e3", "Arcadia Corporation, Dennis Caswell", "5 AR-4200", "Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02066b17f29082412c6754c1a2d6302e", "", "", "Demo Image Series #3 - Baboon (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "024365007a87f213cbe8ef5f2e8e1333", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "025668e36a788e8af8ac4f1be7e72043", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (06-14-82) (Atari) (Prototype)", "Console ports are swapped", "Prototype", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "026180bf641ff17d8577c33facf0edea", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0277c449fae63f6f1c8f94dedfcf0058", "", "", "Laser Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "027a59a575b78860aed780b2ae7d001d", "CCE", "", "Pressure Cooker (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "028024fb8e5e5f18ea586652f9799c96", "Coleco - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "2468", "Carnival (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02811151906e477d47c135db5b1699c6", "", "", "FlickerSort Demo (Updated) (20-04-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02a5fc90a0d183f870e8eebac1f16591", "HES", "771-422", "2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02ab2c47bc21e7feafa015f90d7df776", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02ced7ea2b7cb509748db6bfa227ebec", "Parker Brothers, Ed English, David Lamkins", "931502", "Frogger (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02cee0b140d2f1a1efcfb1d482a5c392", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02dcba28c614fec7ca25955327128abb", "Andrew Wallace", "", "Laseresal 2002 (PAL) (PD) [a]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "02e3f4ba156fb578bef7d7a0bf3400c1", "", "", "Booster (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "033e21521e0bf4e54e8816873943406d", "20th Century Fox Video Games - Sirius Software, Dan Thompson", "11020", "Earth Dies Screaming, The (1983) (20th Century Fox)", "The Day the Earth Stood Still", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "034c1434280b0f2c9f229777d790d1e1", "Telegames", "5665 A016", "Baseball (1988) (Telegames) (PAL)", "AKA Super Challenge Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0375f589f7da06d2d2be532e0d4d4b94", "", "", "Push (V0.04) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0383dc02cb82302da3d155fd108bfe3a", "AtariAge, Chris Spry", "CX26200", "Princess Rescue (2013) (Sprybug) (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "038e1e79c3d4410defde4bfe0b99cc32", "Atari, Tod Frye, Gary Shannon", "", "Aquaventure (08-12-1983) (Atari) (Prototype)", "AKA Sea Sentinel", "Unbelievably Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "039cf18b459d33b8a8fca31d06c4c244", "", "", "Demo Image Series #0 (12-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "03b1051c9374678363c899914412cfc5", "", "", "Incoming (30-10-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "03c3f7ba4585e349dd12bfa7b34b7729", "SEGA, Jeff Lorenz", "004-01", "Star Trek - Strategic Operations Simulator (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "03fbcee0bc80e31f27254aea3d920510", "Bit Corporation", "R320", "Trick Shot (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "03ff9e8a7af437f16447fe88cea3226c", "Bomb - Onbase", "CA285", "Wall-Defender (1983) (Bomb)", "AKA Wall Break", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04014d563b094e79ac8974366f616308", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "041b5e56bbc650db574bd8db3fae2696", "Thomas Jentzsch", "", "Thrust (V1.0) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "043f165f384fbea3ea89393597951512", "Spectravision - Spectravideo", "SA-202", "Planet Patrol (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0443cfa9872cdb49069186413275fa21", "M Network - INTV, Patricia Lewis Du Long, Ron Surratt", "MT4518", "BurgerTime (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "045035f995272eb2deb8820111745a07", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia)", "AKA Jungle Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "047ac3b9faea64522b7a23c4465a7aa8", "", "", "Defender (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04856e3006a4f5f7b4638da71dad3d88", "Atari, Douglas Neubauer", "CX26176", "Radar Lock (1989) (Atari) (PAL)", "AKA Dog Fight", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "049626cbfb1a5f7a5dc885a0c4bb758e", "", "", "MegaMania (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04b488d4eef622d022a0021375e7e339", "Home Vision - Gem International Corp. - VDI", "VCS83107", "Tennis (1983) (Home Vision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04cf9e6898007024622ed6a0b295961f", "Bit Corporation", "R320", "Tennis (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04dfb4acac1d0909e4c360fd2ac04480", "Thomas Jentzsch", "", "Jammed (2001) (XYPE) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04e737c9d53cd84bfd5ee679954e4706", "Jone Yuan Telephonic Enterprise Co", "", "Checkers (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "04fccc7735155a6c1373d453b110c640", "HES - Imagineering, David Lubar", "535", "My Golf (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0519f395d5f7d76be813b834aa51c0be", "Atari, Ian Shepard", "CX2604", "Space War (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0546f4e6b946f38956799dd00caab3b1", "Thomas Jentzsch", "", "My Golf (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "056f5d886a4e7e6fdd83650554997d0d", "Parker Brothers, Ed Temple", "931504", "Amidar (1982) (Parker Bros) (PAL)", "", "Uncommon", "", "", "", "A", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "056ff67dd9715fafa91fb8b0ddcc4a46", "", "", "Frisco (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05824fcbe615dbca836d061a140a50e0", "Jeffry Johnston", "", "Radial Pong - Version 9 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05aedf04803c43eb5e09dfd098d3fd01", "", "", "Keystone Kapers (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05aff8f626ef870432ae3b3d9d5aa301", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05b45ba09c05befa75ac70476829eda0", "Parker Brothers, Rex Bradford", "931507", "Star Wars - Jedi Arena (1983) (Parker Bros) (PAL)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 50", "", "", "", "", "", "", "", "" }, + { "05c60458ec69e7fe8b1be973852d84f1", "", "", "Test (1996) (J.V. Matthews) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05c765a63e61882abd1c2d627b652225", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (NTSC) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05ccf96247af12eef59698f1a060a54f", "Otto Versand", "600273", "King Arthur (1983) (Otto Versand) (PAL)", "AKA Dragonfire (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "05d61b925d3d2474bab83f0a79bb5df1", "Eckhard Stolberg", "", "Cosmic Ark Stars (1997) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05eb4347f0ec8f4783983ca35ffd8d1b", "", "", "Qb (2.06) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "05ebd183ea854c0a1b56c218246fbbae", "Atari, Dan Hitchens", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "05f11fb2e45c4e47424d3cb25414d278", "", "", "Boring (NTSC) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "060c865c782debb047e6fd101c8923fc", "Atari", "CX26163P", "Freeway Rabbit (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0614ed51acd027d531e7c85c4f435292", "", "", "Narnia (Glenn Saunders) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0619e1c3286bbfbace040b8c3ec5add2", "Omegamatrix", "", "Millipede (Atari Trak-Ball) v6.5 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, + { "0651216c4a4a9c9ac5ada3013a317c72", "Jone Yuan Telephonic Enterprise Co", "", "Fishing Derby (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06742cf522f23797157f215a1dc8a1a9", "", "", "Healthbars (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0685bd0bcb975ceef7041749a5454a48", "Piero Cavina", "", "11 Sprite Demo (Piero Cavina) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "069c17beb1e8e0557adb8539fdcf6cba", "", "", "Phantom II & Pirate (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06b0194ce992584c365278e0d7323279", "Activision", "", "Unknown Activision Game #2 (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06b6c5031b8353f3a424a5b86b8fe409", "Activision, Mike Lorenzen - Ariola", "EAX-023 - 711 023-720", "Oink! (1983) (Activision) (PAL)", "AKA Das Schweinchen und der Wolf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06cfd57f0559f38b9293adae9128ff88", "Telegames", "4317 A009", "Adventures on GX-12 (1988) (Telegames) (PAL)", "AKA Adventures of Tron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06d2f7674cea977607f74c464ce600a2", "CBS Electronics, Alex Nevelson", "4L 2737 0000", "Omega Race (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06db908011065e5ebb37f4e253c2a0b0", "", "", "Gopher (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "06e5dc181a8eda1c31cc7c581c68b6ef", "", "", "Tac-Scan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "071f84d10b343c7c05ce3e32af631687", "Rainbow Vision - Suntek", "SS-019", "Curtiss (1983) (Rainbow Vision) (PAL)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "072a6ea2181ca0df88ac0dedc67b239d", "", "", "Multiple Missiles Demo (19-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "073cb76b006af034fd150be3f5e0e7e6", "", "", "Mobile 48 Sprite Kernel (Bug Fixed) (10-01-2003) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "073d7aff37b7601431e4f742c36c0dc1", "", "", "Bermuda (Unknown) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "074ec425ec20579e64a7ded592155d48", "Atari - Sculptured Software, Steve Aguirre", "CX26162", "Fatal Run (Ultimate Driving) (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "075069ad80cde15eca69e3c98bd66714", "CCE", "C-803", "Bobby Is Going Home (1983) (CCE)", "AKA Bobby Vai Para Casa", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0751f342ee4cf28f2c9a6e8467c901be", "Atari, Mimi Nyden, Joseph Tung", "CX26152", "Super Baseball (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07973be3ecfd55235bf59aa56bdef28c", "Suntek", "SS-036", "Criminal Pursuit (1983) (Suntek) (PAL)", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "079fe9103515d15bc108577e234a484d", "", "", "Multi-Color Demo 0 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07a3af1e18b63765b6807876366f5e8a", "Joe Grand", "", "SCSIcide Pre-release 2 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07c76f2d88552d20ad2c0ed7aef406c6", "Cody Pittman", "", "Blob (Cody Pittman) (Hack)", "Hack of Halloween", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07f42847a79e4f5ae55cc03304b18c25", "Zellers", "", "Sea Hawk (Zellers)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07f84db31e97ef8d08dc9fa8a5250755", "Supergame", "", "Enduro (1984) (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "07f91e33e76f53bb9d2731fd5d8a35a5", "Atari", "CX2632", "Space Invaders (1978) (Atari) [t1]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0805366f1b165a64b6d4df20d2c39d25", "Atari, Dan Hitchens", "CX2650", "Berzerk (1982) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08188785e2b8300983529946dbeff4d2", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari) (4K)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "081e2c114c9c20b61acf25fc95c71bf4", "Parker Brothers, Ed English, David Lamkins", "PB5300", "Frogger (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "082fdc8bd47fef01482ce5883c4ffdb8", "Charles Morgan", "", "Tanks DX (Charles Morgan) (Hack)", "Hack of Tanks But No Tanks", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0832fb2ee654bf9382bc57d2b16d2ffc", "Apollo - Games by Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "083e7cae41a874b2f9b61736c37d2ffe", "Imagic, Rob Fulop, Bob Smith", "720106-2A, IA3600P, EIX-009-04I", "Riddle of the Sphinx (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "085322bae40d904f53bdcc56df0593fc", "Parker Brothers, Dave Engman, Dawn Stockbridge", "PB5340", "Tutankham (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0856f202b18cd46e44fd1dc3b42e9bfb", "", "", "Frame Counter 1 (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0866e22f6f56f92ea1a14c8d8d01d29c", "Androbot - Western Technologies, Michael Case, Lenny Carlson", "", "AndroMan on the Moon (1984) (Western Tech) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0891252ee4e307689febccf3cfd8a8ab", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0894aa7be77521f9df562be8d9555fe6", "CBS Electronics, Dan Kitchen, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1982) (CBS Electronics) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08989fa4ff537f5dbd611aff4019521a", "Atari, Gary Palmer", "CX26163P", "Fun with Numbers (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08bd4c1dcc843f6a0b563d9fd80b3b11", "Quelle", "343.273 9", "Phantompanzer II (1983) (Quelle) (PAL)", "AKA Thunderground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08bf437d012db07b05ff57a0c745c49e", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Meteoroids (1982) (Arcadia) (Prototype)", "Suicide Mission Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "08d1b6d75206edb999252caf542a2c7f", "Larry Petit", "", "Super Home Run (2003) (Larry Petit) (Hack)", "Hack of Home Run", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08d60a58a691c7f690162850302dc0e1", "", "", "Poker Squares (V0.27) (PAL) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08e5960bb52d9a3e2c9954677b5e4472", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (10-20-1982) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08ea2fdaa22e5802c839ee7dfb0483dc", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "08f4dc6f118f7c98e2406c180c08e78e", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Tug of War (2 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "02", "", "", "", "", "", "", "", "" }, + { "08f853e8e01e711919e734d85349220d", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0906c6e0e4bda9c10cfa4c5fc64d2f4b", "Retroactive", "", "Qb (V0.12) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "090f0a7ef8a3f885048d213faa59b2f8", "Carrere Video - Western Technologies, John Hall - Teldec - Prism", "USC1012", "M.A.D. (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "09274c3fc1c43bf1e362fda436651fd8", "Thomas Jentzsch", "", "Acid Drop (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "09388bf390cd9a86dc0849697b96c7dc", "Absolute Entertainment, Alex DeMeo", "AG-045-04, AK-045-04", "Pete Rose Baseball (1988) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0945081a6bd00345ff3d58eb7a07330a", "", "", "Stampede (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0956285e24a18efa10c68a33846ca84d", "Dismac", "", "Viagem Espacial (Dismac)", "AKA Star Voyager", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0963aa9f7f6cf5a36ff700001583624e", "Franklin Cruz", "", "Space Invaders 2 (Hack) [o1]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "096649575e451508006b17e0353259a5", "Justin J. Scott", "", "Yar Vs. Yar (2002) (Justin J. Scott) (Hack)", "Hack of Yars' Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "097074f24cde141fe6a0f26a10333265", "", "", "Marble Craze (V0.90) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "097936b07e0e0117b9026ae6835eb168", "Imagic, Dennis Koble", "720100-2B, IA3000P", "Trick Shot (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "09abfe9a312ce7c9f661582fdf12eab6", "Atari, Douglas Neubauer", "CX26154", "Super Football (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "09e1ecf9bd2a3030d5670dba7a65e78d", "Atari, James Andreasen", "CX2654", "Haunted House (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "09e9ba0762fd0c3cf3c2e072cff79cac", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "09f89bbfa2ab00f1964d200e12d7ced0", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0a1b98937911d621b004b1617446d124", "", "", "Hangman Pac-Man Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0a981c03204ac2b278ba392674682560", "Atari, Bob Whitehead - Sears", "CX2651 - 99805, 49-75602", "Blackjack (1977) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0aa208060d7c140f20571e3341f5a3f8", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Tom Sloper", "VC1009", "Towering Inferno (1982) (U.S. Games)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0abf64ca504a116adca80f77f85e00fb", "", "", "Cube Conquest (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0ac0d491763153fac75f5337ce32a9d6", "", "", "SPAM Image Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0acaf71e60b89f6b6eab63db6ab84510", "", "", "This Planet Sucks (Greg Troutman) [a2]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0aceb7c3bd13fe048b77a1928ed4267d", "Imagic, Bob Smith", "720102-2B, IA3201P, EIX-011-04I", "Star Voyager (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0ad9a358e361256b94f3fb4f2fa5a3b1", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner - Sears", "CX2608 - 49-75165", "Super Breakout (1982 - 1981) (Atari) [a]", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "0adb21206de92e8aec5ef295805ebb90", "", "", "Solaris (Genesis)", "Genesis controller (C switches to map mode)", "Hack of Solaris", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0ae3497e731ca0bf6a77b23441d9d9f9", "", "", "Analog Clock (V0.0) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0af51ceb4aecc7a8fc89781ac44a1973", "Barry Laws Jr.", "", "Face Invaders Deluxe (Barry Laws Jr.) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0afe6ae18966795b89314c3797dd2b1e", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692, CX2692P", "Moon Patrol (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b01909ba84512fdaf224d3c3fd0cf8d", "", "", "Revenge of the Apes (Hack)", "Hack of Planet of the Apes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b1056f1091cfdc5eb0e2301f47ac6c3", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001 - 3.60001 VE", "King Kong (1982) (Tigervision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b17ed42984000da8b727ca46143f87a", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (05-17-1983) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b24658714f8dff110a693a2052cc207", "CCE", "C-815", "Seaquest (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b33252b680b65001e91a411e56e72e9", "CCE", "C-832", "Atlantis (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b4e793c9425175498f5a65a3e960086", "CCE", "", "Kung Fu Master (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b55399cf640a2a00ba72dd155a0c140", "Imagic, Wilfredo Aguilar, Michael Becker, Rob Fulop", "720111-1A, 03205", "Fathom (1983) (Imagic)", "AKA Scuba", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0b577e63b0c64f9779f315dca8967587", "Videospielkassette - Ariola", "PGP236", "Raketen-Angriff (Ariola) (PAL)", "AKA Missile Control", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0b8d3002d8f744a753ba434a4d39249a", "Sears Tele-Games, Robert Zdybel", "CX2619 - 49-75159", "Stellar Track (1981) (Sears)", "AKA Stella Trak", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0bf19e40d5cd8aa5afb33b16569313e6", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0bf1e354304f46c0caf8fc0f6f5e9525", "Arcadia Corporation, Stephen Harland Landrum", "AR-4105", "Official Frogger (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0bfabf1e98bdb180643f35f2165995d0", "Atari, Bob Whitehead - Sears", "CX2623 - 6-99819, 49-75108, 49-75125", "Home Run (1978) (Atari)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c0392db94a20e4d006d885abbe60d8e", "", "", "Dodge Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c336f83b0e6e3bc86c77f368448e77b", "Bit Corporation", "R320", "Circus Atari (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c35806ff0019a270a7acae68de89d28", "Froggo", "FG1003", "Task Force (1987) (Froggo)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c48e820301251fbb6bcdc89bd3555d9", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Stargate (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c54811cf3b1f1573c9164d5f19eca65", "Activision, David Crane - Ariola", "EAG-001, PAG-001, EAG-001-04B, EAG-001-04I - 711 001-715", "Dragster (1980) (Activision) (PAL)", "AKA Dragster Rennen, Drag Strip", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c72cc3a6658c1abd4b735ef55fa72e4", "Dion Olsthoorn", "v1.3", "Amoeba Jump (2018) (Dionoid) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c7926d660f903a2d6910c254660c32c", "Atari, Larry Kaplan", "CX2602, CX2602P", "Air-Sea Battle (1977) (Atari) (PAL)", "AKA Anti-Aircraft", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0c7bd935d9a7f2522155e48315f44fa0", "Carrere Video - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Tom Sloper - Teldec - Prism", "USC1009", "Infernal Tower (1983) (Carrere Video) (PAL)", "AKA Towering Inferno", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0c80751f6f7a3b370cc9e9f39ad533a7", "Atari, Carla Meninsky", "CX2610", "Warlords (1981) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "0cb7af80fd0ddef84844481d85e5d29b", "", "", "Mr. Pac-Man (El Destructo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0cc8224ff1edfe458e8629e9e5fe3f5b", "Thomas Jentzsch", "", "Trick 12 (2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0cdd9cc692e8b04ba8eb31fc31d72e5e", "Thomas Jentzsch", "", "Wing War (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0cebb0bb45a856b23f56d21ce7d1bc34", "20th Century Fox Video Games, Bill Aspromonte", "11131", "Crash Dive (1983) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0cec9e46a25d338bf595a29aa2606516", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (PAL60) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0cfdd2f3b243cac21f38a0f09f54bead", "", "", "Overhead Adventure Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d07d2c1be1a5eaaea235a533bcda781", "", "", "Scrolling Playfield 1 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d08558f34a47e4eaa39d01c8efb81f0", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (NTSC) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d09cff0d28033c02c3290edfc3a5cea", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d1b3abf681a2fc9a6aa31a9b0e8b445", "Atari", "CX26163P", "Laser Blast (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d27c7f5db349b592f70f68daf5e8f3b", "", "", "Space Instigators (21-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d35618b6d76ddd46d2626e9e3e40db5", "", "", "X-Doom V.26 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d5af65ad3f19558e6f8e29bf2a9d0f8", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dark Chambers (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0d6b974fe58a1bdd453600401c407856", "Atari", "", "128-in-1 Junior Console (Chip 3 or 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d786a41695e5fc8cffd05a6dbb3f659", "", "", "Scrolling Playfield With Score (10-02-2003) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d7e630a14856f4d52c9666040961d4d", "", "", "Wavy Line Test (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0d90a0ee73d55539b7def24c88caa651", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0db4f4150fecf77e4ce72ca4d04c052f", "Atari, Carol Shaw - Sears", "CX2618 - 49-75123", "3-D Tic-Tac-Toe (1980) (Atari)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0dd4c69b5f9a7ae96a7a08329496779a", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001 - 3.60001 VE", "King Kong (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0de53160a8b54c3aa5aed8d68c970b62", "Quelle", "806.174 9", "Fuchs & Schweinchen Schlau (1983) (Quelle) (PAL)", "AKA Oink!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0dfbdadf8f1bc718e7e1bb3ccd5fef3d", "", "", "Mr. Pac-Man (New start tune) (El Destructo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e0808227ef41f6825c06f25082c2e56", "", "", "Candi (Hack) [a]", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e08cd2c5bcf11c6a7e5a009a7715b6a", "", "", "Boing! (PD) [a1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e224ea74310da4e7e2103400eb1b4bf", "Atari, Peter C. Niday, Gary Shannon, Howard Scott Warshaw", "", "Mind Maze (10-10-1984) (Atari) (Prototype)", "Uses the MindLink controller", "Prototype", "", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e23d0ed4c33b2011ab4cc93a7619683", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e4b2b6e014a93ef8be896823da0d4ec", "", "", "Skiing (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e713d4e272ea7322c5b27d645f56dd0", "Home Vision - Gem International Corp. - VDI", "VCS83105", "Panda Chase (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0e7e73421606873b544e858c59dc283e", "Digivision", "", "Super Soccer (Digivision)", "AKA RealSports Soccer", "", "", "", "F8", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0e86470791b26292abe1c64545c47985", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Down on the Line (3 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "01 70", "", "", "", "", "", "", "", "" }, + { "0ec93f519bb769e0d9f80e61f6cc8023", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (02-25-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0ecdb07bf9b36ef18f3780ef48e6c709", "Bit Corporation", "PG209", "Mr. Postman (1983) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0eebfb60d437796d536039701ec43845", "Fabrizio Zavagli", "", "Cakewalk (Fabrizio Zavagli)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0eecb5f58f55de9db4eedb3a0f6b74a8", "Xonox - Beck-Tech", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0ef64cdbecccb7049752a3de0b7ade14", "Atari, Joe Decuir, Larry Caplan, Steve Mayer, Larry Wagner", "CX26163P", "Combat (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0efc91e45f61023cda9d086a7d3c402f", "B.J. Best (aka bjbest60)", "", "Space Cactus Canyon (2017)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0effef4a341f8eebab65621c60c48787", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f14c03050b35d6b1d8850b07578722d", "Jeffry Johnston", "", "Radial Pong - Version 10 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f24ca5668b4ab5dfaf217933c505926", "", "", "Fantastic Voyage (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f2e09c71cc216f79d22a804152ba24b", "Bob Colbert", "", "Scroller Demo (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0f341d1f4e144e3163d9a5fc5a662b79", "", "", "RUN Platform Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "0f39fc03d579d0d93a6b729a3746843e", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (05-27-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f604cd4c9d2795cf5746e8af7948064", "Champ Games", "CG-02-N", "Conquest Of Mars (2010) (NTSC)", "Rev 2 release", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f643c34e40e3f1daafd9c524d3ffe64", "Atari, Robert C. Polaro, Alan J. Murphy - Sears", "CX2609 - 49-75186", "Defender (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f6676b05621f80c670966e2995b227a", "", "", "Globe Trotter Demo 1 (24-03-2003) (Weston)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f738dc44437557624eb277ed7ad91c9", "", "", "Grand Prix (Unknown) (PAL)", "AKA Grand Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f8043715d66a4bbed394ef801d99862", "Quelle", "684.733 9", "Robin Hood (1983) (Quelle) (PAL)", "AKA Save Our Ship", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0f95264089c99fc2a839a19872552004", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fba7d8c3520bdb681f75494e498ec36", "", "", "Gunfight 2600 - Final Run (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fbf618be43d4396856d4244126fe7dc", "Quelle", "805.784 6", "Labyrinth (1983) (Quelle) (PAL)", "AKA Maze Craze", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fc161704c46e16f7483f92b06c1558d", "CCE", "C-853", "Spider Fighter (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fcff6fe3b0769ad5d0cf82814d2a6d9", "Suntek", "SS-027", "Zoo Fun (1983) (Suntek) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fd72a13b3b6103fc825a692c71963b4", "Imagic, Rob Fulop", "720104-2A, IA3204P, EIX-008-04I", "Cosmic Ark (1982) (Imagic) (PAL) [selectable starfield]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "0fee596b974c9d3e70b367a3671599b6", "Bit Corporation", "R320", "Name This Game (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "101ab60f4000a5d13792ef0abad5f74b", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "102672bbd7e25cd79f4384dd7214c32b", "Atari, Alan Miller - Sears", "CX2642 - 6-99814", "Hunt & Score - Memory Match (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "103e9d616328969f5d7b4e0a381b25d5", "", "", "Playfield Illustration and Logo Demo (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "103f1756d9dc0dd2b16b53ad0f0f1859", "Home Vision, Gem International Corp.", "", "Go Go Home Monster (1983) (Home Vision) (PAL)", "AKA Go Go Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "104468e44898b8e9fa4a1500fde8d4cb", "AtariAge, Chris Spry", "CX26200", "Princess Rescue (2013) (Sprybug)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "106326c262dfd3e8eaeabd961d2a0519", "", "", "PAL-NTSC Detector (15-11-2002) (CT)[a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "106855474c69d08c8ffa308d47337269", "Atari - Sculptured Software, Adam Clayton", "CX26151", "Dark Chambers (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "107cc025334211e6d29da0b6be46aec7", "Atari, Bob Smith - Sears", "CX2648 - 49-75161", "Video Pinball (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1086ff69f82b68d6776634f336fb4857", "Activision, David Crane", "AG-009", "Bloody Human Freeway (1981) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10958cd0a1a81d599005f1797ab0e51d", "", "", "Centipede 2k (2000) (PD) (Hack)", "Hack of Centipede", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10a3cd14e5dcfdde6ff216a14ce7b7dd", "Atari", "CX262, CX2627P", "Human Cannonball (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10af8728f975aa35a99d0965de8f714c", "Dinatronic", "", "Seaquest (Dinatronic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10c47acca2ecd212b900ad3cf6942dbb", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a4]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10c8cfd8c37522f11d47540ff024e5f9", "Canal 3 - Intellivision", "C 3016", "Demon Attack (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10eae73a07b3da044b72473d8d366267", "Funvision - Fund. Int'l Co.", "", "Karate (1982) (Funvision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10f0ecaf962aef1fc28abed870b01b65", "Atari, Paul Donaldson", "", "Bionic Breakthrough (06-22-1984) (Atari) (Prototype)", "Uses the Mindlink Controller", "Prototype", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "10f62443f1ae087dc588a77f9e8f43e9", "Atari, Carla Meninsky", "CX2637, CX2637P", "Dodge 'Em (1980) (Atari) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "110ac8ecaf1b69f41bc94c59dfcb8b2d", "", "", "Demon Attack (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "111029770226b319524134193886a10e", "Hozer Video Games", "", "Gunfight 2600 - One Limit Reached! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "11330eaa5dd2629052fac37cfe1a0b7d", "128-in-1 Junior Console", "", "Human Cannonball (128-in-1 Junior Console) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "113cd09c9771ac278544b7e90efe7df2", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari) [no grid markers]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "114c599454d32f74c728a6e1f71012ba", "Activision, Bob Whitehead - Ariola", "EAX-015, EAX-015-04I - 711 015-725", "Chopper Command (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "11bcf5c752088b5aaf86d6c7a6a11e8d", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "11e7e0d9437ec98fa085284cf16d0eb4", "", "", "Bowling (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "11f9532557e4c9569f4b242164006161", "Chris Walton, Justin Hairgrove, Tony Morse", "", "Hunchy II (2005) (PAL)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1201c18cf00d2c236f42e4d7d8c86aa1", "", "", "Nick Bensema Demo (Nick Bensema)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "12080205f669b8e7783b976f8cf3d8bb", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "12123b534bdee79ed7563b9ad74f1cbd", "Absolute Entertainment, Alex DeMeo", "AG-041-04", "Title Match Pro Wrestling (1987) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1228c01cd3c4b9c477540c5adb306d2a", "Atari, Alan Miller", "CX26163P", "Basketball (32 in 1) (1988) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1266b3fd632c981f3ef9bdbf9f86ce9a", "Activision, Bob Whitehead", "EAZ-034-04, EAZ-034-04I", "Private Eye (1984) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1267e3c6ca951ff1df6f222c8f813d97", "", "", "Dragonfire (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "126f7f64b7b00e25dcf5e3710b4cf8b8", "Atari - GCC", "CX2676", "Centipede (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1278f74ca1dfaa9122df3eca3c5bcaad", "Rainbow Vision - Suntek", "SS-013", "Bi! Bi! (Rainbow Vision) (PAL)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1287535256bf5dff404839ac9e25c3e7", "PacManPlus", "Rev 2", "Alien Pac-Man (PacManPlus) (Hack)", "Hack of Alien", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "12937db3d4a80da5c4452b752891252d", "Digitel", "", "Megamania (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "12bca8305d5ab8ea51fe1cfd95d7ab0e", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00250", "Summer Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "12d7e0d6b187889f8d150bf7034d1db2", "", "", "Poker Squares (V0.0e) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "130c5742cd6cbe4877704d733d5b08ca", "Home Vision - Gem International Corp. - VDI", "VCS83109", "World End (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1323c45d660f5a5b6d5ea45c6c4cbe4a", "Canal 3 - Intellivision", "", "Enduro (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "133456269a03e3fdae6cddd65754c50d", "Tigervision - Software Electronics Corporation - Teldec", "7-006 - 3.60008 VG", "Springer (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "133a4234512e8c4e9e8c5651469d4a09", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "133b56de011d562cbab665968bde352b", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1343de49c2a50d99176255f99f0d0234", "Gray Games & AtariAge", "", "E.T. Book Cart (PAL)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "55", "", "", "", "" }, + { "13448eb5ba575e8d7b8d5b280ea6788f", "Digivision", "", "Crackpots (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1345e972dbe08ea3e70850902e20e1a5", "Greg Troutman", "", "Dark Mage (rough beta) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1351c67b42770c1bd758c3e42f553fea", "Digivision", "", "Keystone Kapers (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "135708b9a7dd20576c1b66ab2a41860d", "", "", "Hangman Man Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13584411da0a8d431991035423fdc0dc", "Jone Yuan Telephonic Enterprise Co", "", "Skiing (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1367e41858be525710eb04d0dab53505", "Kyle Pittman", "", "Zelda (2003) (Kyle Pittman) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "136f75c4dd02c29283752b7e5799f978", "Atari, Dan Hitchens - Sears", "CX2650 - 49-75168", "Berzerk (1982) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13895ef15610af0d0f89d588f376b3fe", "Tigervision, Rorke Weigandt", "7-005", "Marauder (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13a37cf8170a3a34ce311b89bde82032", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13a991bc9c2ff03753aeb322d3e3e2e5", "Funvision - Fund. International Co.", "", "Galactic (Funvision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13aa1f9ac4249947e4af61319d9a08f2", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13abc32f803165c458bb086fa57195fb", "Christian Samuel", "", "E.T. The Extra-Testical (Christian Samuel) (Hack)", "Hack of E.T. The Extra-Terrestrial", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13ccc692f111d52fec75d83df16192e2", "Canal 3 - Intellivision", "", "Fishing Derby (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13d8326bf5648db4dafce45d25e62ddd", "", "", "Atari Logo Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "13dfb095e519a555a5b60b7d9d7169f9", "", "", "Red Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "140909d204abd6841c64cdad4d7765b4", "", "", "Moving Blue Ladder Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "14163eb2a3ddd35576bd8527eae3b45e", "", "", "Multi-Color Demo 6 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1423f560062c4f3c669d55891a2bcbe7", "CCE", "C-859", "MASH (1983) (CCE) [a]", "AKA M.A.S.H", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1428029e762797069ad795ce7c6a1a93", "", "", "Thunderground (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "143918368f4f4dfff90999188c0197c9", "", "", "Unknown Title (bin00016 (200110)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1442d1b35a6478fba22ae7dd1fcb5634", "Thomas Jentzsch", "", "Thrust (V0.2) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "148471144ccebd7f6aa9aa9215896533", "Parker Brothers - JWDA, Todd Marshall", "PB5550", "Q-bert's Qubes (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "149b543c917c180a1b02d33c12415206", "CCE", "C-857", "Superman (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "14a56b493a8d9d10e94a3e100362e3a2", "Hozer Video Games", "", "Gunfight 2600 - Early Play-kernel (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "14b1e30982962c72f426e2e763eb4274", "Atari, Carol Shaw - Ralph Lauren", "", "Polo (1978) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "14c2548712099c220964d7f044c59fd9", "First Star Software, Alex Leavens, Shirley Ann Russell", "", "Boing! (1983) (First Star Software)", "AKA Bubbles, Soap Suds, The Emphysema Game", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "14d365bbfaac3d20c6119591f57acca4", "", "", "Video Life (Unknown) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "14dbb3686dd31964332dc2ef0c55cad0", "", "", "Demo Image Series #15 - Three Marios (PAL) (Non-Interleave) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "151c33a71b99e6bcffb34b43c6f0ec23", "Parker Brothers, Laura Nikolich", "", "Care Bears (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "151fa3218d8d7600114eb5bcd79c85cb", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (05-02-1983) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "152c253478b009c275e18cd731b48561", "", "", "Quest (11-10-2002) (Chris Larkin)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "153f40e335e5cb90f5ce02e54934ab62", "Absolute Entertainment, Alex DeMeo", "EAZ-041-04I", "Title Match Pro Wrestling (1987) (Absolute) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1542662f665d2ffaa77b4b897dd2e2af", "", "", "Starfield (V1.0) (2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "155fa7f479dcba3b10b1494e236d6010", "Skyworks", "", "Tomcat (2002) (Skyworks) (PAL)", "AKA The F-14 Flight Simulator", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "157356f80c709ab675961d8b8b207e20", "", "", "Multi-Sprite Game V2.5 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "157bddb7192754a45372be196797f284", "Atari, Warren Robinett - Sears", "CX2613, 49-75154", "Adventure (1980) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "159e5cd6ccb968015f49aed5adbc91eb", "Justin J. Scott", "", "Yar's Defeat (2002) (Justin J. Scott) (Hack)", "Hack of Yars' Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "15a0d59304dece2c7d0580f3ea3527f0", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (04-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15b498199ed0ed28057bf0dbdce9b8d8", "Thomas Jentzsch", "", "Jammed (V0.2) (Demo) (2001) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15b9f5e2439bfaa08874b5184261c777", "Bit Corporation", "R320", "Space Invaders (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15bcd74f2f1f2a63e1aa93e90d2c0555", "", "", "Incoming (22-08-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15bf2ef7583bfcbbba630847a1dc5539", "Erik Eid", "", "Euchre (Jul 15) (2002) (Eric Eid) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15c11ab6e4502b2010b18366133fc322", "Atari - Axlon, Tod Frye - Heuristica, Augustin Ortiz", "CX26169", "Shooting Arcade (09-19-1989) (Atari) (Prototype)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15dd21c2608e0d7d9f54c0d3f08cca1f", "Data Age, J. Ray Dettling", "112-008", "Frankenstein's Monster (1983) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "15fe28d0c8893be9223e8cb2d032e557", "", "", "Towering Inferno (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1619bc27632f9148d8480cd813aa74c3", "Thomas Jentzsch", "", "Steeple Chase (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "161ded4a85d3c78e44fffd40426f537f", "Thomas Jentzsch", "", "JtzBall (Alpha) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16229d61d7b0c89b01853660a8da22bb", "", "", "spin4a50", "", "", "", "", "4A50", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "163e7e757e2dc44469123ff0e5daec5e", "", "", "Many Blue Bars and Text Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "169d4c7bd3a4d09e184a3b993823d048", "", "", "Superman (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16cb43492987d2f32b423817cdaaf7c4", "Atari, Larry Kaplan - Sears", "CX2602 - 99802, 6-99802, 49-75102", "Air-Sea Battle (1977) (Atari)", "AKA Target Fun (Anti-Aircraft)", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16cc6d1b4ddce51c767a1ba8e5ff196c", "", "", "Big - Move This Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "16d69f71bf5846639be5ff16483f0498", "Bit Corporation", "R320", "Golf (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16e04823887c547dc24bc70dff693df4", "Atari", "CX26163P", "Tennis (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16ee443c990215f61f7dd1e55a0d2256", "Spectravideo, David Lubar", "SA-218, SA-218C", "Bumper Bash (1983) (Spectravideo) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "PADDLES", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "16f494f20af5dc803bc35939ef924020", "Mark De Smet", "", "Video Simon (Mark De Smet)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "170e7589a48739cfb9cc782cbb0fe25a", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5666", "Astroblast (1982) (M Network) [fixed]", "Can also use left joystick", "Uncommon", "", "", "", "", "", "", "", "PADDLES", "", "YES", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "171cd6b55267573e6a9c2921fb720794", "Kurt Howe", "", "Adventure 34 (Kurt Howe) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "171ebf135b13ba907f462c10d88a2c25", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (PAL60) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1733772165d7b886a94e2b4ed0f74ccd", "", "", "Boring Journey Escape (Hack)", "Hack of Journey - Escape", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1738b2e3f25ab3eef3cecb95e1d0d957", "", "", "Hangman Monkey Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17512d0c38f448712f49f36f9d185c4e", "Retroactive", "", "Qb (Release Candidate #1) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "17515a4d0b7ea5029ffff7dfa8456671", "Piero Cavina", "", "Multi-Sprite Demo V1.1 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "176d3fba7d687f2b23158098e103c34a", "Zach Matley", "", "Combat AI (16-02-2003) (Zach Matley)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "177504abd4260c4265e1338955e9fa47", "HCC Software", "", "Pitfall! (Steroids Hack)", "Hack of Pitfall! (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1782929e1c214b70fb6884f77c207a55", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17ba72433dd41383065d4aa6dedb3d91", "", "", "SCSIcide (09-06-2001) (Joe Grand)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17badbb3f54d1fc01ee68726882f26a6", "M Network - INTV - APh Technological Consulting, Hal Finney, Bruce Pedersen", "MT5659", "Space Attack (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17bbe288c3855c235950fea91c9504e9", "Dismac", "", "Pega Ladrao (Dismac)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17c0a63f9a680e7a61beba81692d9297", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, David Johnson, Tom Sloper", "VC2004", "Picnic (1983) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "17d000a2882f9fdaa8b4a391ad367f00", "Atari - GCC", "CX2676", "Centipede (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "17ee158d15e4a34f57a837bc1ce2b0ce", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691, CX2691P", "Joust (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "17ee23e5da931be82f733917adcb6386", "Salu, Dennis M. Kiss", "460758", "Acid Drop (1992) (Salu) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1802cc46b879b229272501998c5de04f", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (1983) (Atari)", "Uses Kids/Keypad Controllers", "Rare", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "183020a80848e06a1238a1ab74079d52", "Thomas Jentzsch", "", "Missile Command (Amiga Mouse) (2002) (TJ) (PAL)", "Uses Amiga Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1862fca4f98e66f363308b859b5863af", "Atari", "", "128-in-1 Junior Console (Chip 1 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18a970bea7ac4d29707c8d5cd559d03a", "", "", "Bridge (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18b28b386abdadb3a700ac8fb68e639a", "Manuel Polik", "", "Gunfight 2600 (MP) (PAL)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18b476a34ce5e6db2c032029873ac39b", "Bit Corporation", "R320", "Atlantis (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18be8981b8201638f3ed8ae92bb4c215", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (PAL60) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18bebbbd41c234f82b1717b1905e6027", "", "", "Space Instigators (Public Release) (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18d26111cef66dff0c8af8cf0e117843", "", "", "Tunnel Demo (Cycling Colours 2) (29-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18dc28bc22402f21e1c9b81344b3b8c5", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "18ed63e3ce5bc3dd2d8bd188b807f1a2", "", "", "Stell-A-Sketch (Bob Colbert) (PD) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "18f299edb5ba709a64c80c8c9cec24f2", "Home Vision - Gem International Corp. - VDI", "VCS83111", "Asteroid Fire (1983) (Home Vision) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19098c46da0640f2b5763167dea6c716", "Andrew Wallace", "", "Laseresal 2002 (NTSC) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "191449e40b0c56411c70772706f79224", "", "", "Multi-Color Demo 2 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19162393786098d50587827588198a86", "Jone Yuan Telephonic Enterprise Co", "", "Flag Capture (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "191ac4eec767358ee3ec3756c120423a", "", "", "Checkers (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "192aa2e8c795c9e10a7913e5d41feb81", "Atari - GCC, Jaques Hugon, Seth Lipkin", "CX26125", "Los Angeles 1984 Games (1984) (Atari) (Prototype) (PAL)", "AKA Track and Field (Uses Track & Field Controller)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "193f060553ba0a2a2676f91d9ec0c555", "Atari, Carol Shaw", "CX2636, CX2636P", "Video Checkers (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1942bdb7abc75e412068330a9082b0ff", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (PAL) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "1986f864e32e3e8d198b5becf3022257", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "199985cae1c0123ab1aef921daace8be", "", "", "Euchre (Release Candidate 2) (PAL) (01-10-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "199eb0b8dce1408f3f7d46411b715ca9", "Parker Brothers, David Lamkins, Laura Nikolich", "PB5900", "Spider-Man (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19a9d3f9fa1b1358fb53009444247aaf", "", "", "Blackjack (Unknown) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19abaf2144b6a7b281c4112cff154904", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "19b3b807507653516985ba95da92499d", "Joe Gaucher", "", "VCS Draw Demo (Joe Gaucher)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19d6956ff17a959c48fcd8f4706a848d", "PlayAround - J.H.M.", "202", "Burning Desire (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "19d9b5f8428947eae6f8e97c7f33bf44", "", "", "Fortress (Dual Version) (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19e739c2764a5ab9ed08f9095aa2af0b", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "19e761e53e5ec8e9f2fceea62715ca06", "Panda", "104", "Scuba Diver (1983) (Panda)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1a23540d91f87584a04f184304a00648", "", "", "Race Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1a613ce60fc834d4970e1e674b9196b3", "Home Vision - Gem International Corp. - VDI", "VCS83135", "Tanks War (1983) (Home Vision) (PAL)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1a624e236526c4c8f31175e9c89b2a22", "Rainbow Vision - Suntek", "SS-007", "Space Raid (1983) (Rainbow Vision) (PAL) [a]", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1a8204a2bcd793f539168773d9ad6230", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari) [no initials]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1aa7344b563c597eecfbfcf8e7093c27", "David Marli", "", "Slot Invaders (David Marli) (Hack)", "Hack of Slot Machine", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b0f3d7af668eeea38ddd6182d8f48fb", "Jone Yuan Telephonic Enterprise Co", "", "Cosmic Swarm (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1b1daaa9aa5cded3d633bfcbeb06479c", "", "", "Ship Demo (V 1502) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b22a3d79ddd79335b69c94dd9b3e44e", "Tron", "", "Moon Patrol (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b4b06c2a14ed3ee73b7d0fd61b6aaf5", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b5a8da0622bffcee4c5b42aed4e0ef0", "Akor", "", "TV Boy II (1992) (Akor)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b8c3c0bfb815b2a1010bba95998b66e", "Telegames", "", "Frogs and Flies (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1b8d35d93697450ea26ebf7ff17bd4d1", "Quelle - Otto Versand", "176.764 9 - 781644", "Marineflieger (1983) (Quelle) (PAL)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1bb91bae919ddbd655fa25c54ea6f532", "Suntek", "SS-026", "Treasure Island (1983) (Suntek) (PAL)", "AKA Treasure Discovery", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1bc2427ac9b032a52fe527c7b26ce22c", "Intellivision Productions - M Network - APh Technological Consulting, Bruce Pedersen, Larry Zwick", "MT5860", "Sea Battle (1983) (M Network)", "High Seas", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1bef389e3dd2d4ca4f2f60d42c932509", "Dimax - Sinmax", "SM8001", "Space Robot (1983) (Dimax - Sinmax) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1bf503c724001b09be79c515ecfcbd03", "", "", "Bumper Bash (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1bfae770e089fa81412d04eb299f4c3f", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (NTSC) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c3f3133a3e5b023c77ecba94fd65995", "CCE", "C-830", "Planet Patrol (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c5796d277d9e4df3f6648f7012884c4", "Rainbow Vision - Suntek", "SS-012", "Hey! Stop! (1983) (Rainbow Vision) (PAL)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c666ba5aac19b81671357e76062989b", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) (PAL60) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c6eb740d3c485766cade566abab8208", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c85c0fc480bbd69dc301591b6ecb422", "CCE", "", "Super Box (CCE)", "AKA RealSports Boxing", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1c8c42d1aee5010b30e7f1992d69216e", "PlayAround - J.H.M.", "205", "Gigolo (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1cad3b56cc0e6e858554e46d08952861", "Jone Yuan Telephonic Enterprise Co", "", "Chopper Command (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1cafa9f3f9a2fce4af6e4b85a2bbd254", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (1982) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1cca2197d95c5a41f2add49a13738055", "Atari, Larry Kaplan - Sears", "CX2664 - 6-99818", "Brain Games (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1cf59fc7b11cdbcefe931e41641772f6", "SEGA", "005-01", "Buck Rogers - Planet of Zoom (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1d1d2603ec139867c1d1f5ddf83093f1", "Atari, Larry Kaplan - Sears", "CX2602 - 99802, 6-99802, 49-75102", "Air-Sea Battle (1977) (Atari) (4K)", "AKA Target Fun (Anti-Aircraft)", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d284d6a3f850bafb25635a12b316f3d", "CCE", "", "H.E.R.O. (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d2a28eb8c95da0d6d6b18294211839f", "", "", "Fishing Derby (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d4e0a034ad1275bc4d75165ae236105", "20th Century Fox Video Games, Mark Klein", "11034", "Pick Up (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d5eac85e67b8cff1377c8dba1136929", "", "", "Chronocolor Donkey Kong Sideways (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d6ed6fe9dfbde32708e8353548cbb80", "Jone Yuan Telephonic Enterprise Co", "", "Super Challenge Baseball (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1d72cc6ee466a4af1b27587b900ed430", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1da2da7974d2ca73a823523f82f517b3", "Spectravision - Spectravideo - Sirius Software, David Lubar", "SA-206", "Challenge of.... Nexar, The (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1db3bc4601f22cf43be7ce015d74f59a", "", "", "Ship Demo (V 10) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e060a8025512ad2127e3da11e212ccc", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (3 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e0ef01e330e5b91387f75f700ccaf8f", "Quelle - Otto Versand", "686.561 2 - 781627", "Mein Weg (1983) (Quelle) (PAL)", "AKA Challenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1e1290ea102e12d7ac52820961457e2b", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-15-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1e272d09c0e55f5ef14fcb76a735f6d7", "Atari, David Crane", "CX26163P", "Slot Machine (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e31b3a48865ba98d4d1aa5205115983", "Atari - Roklan, Bob Curtiss", "", "Firefox (1983) (Atari) (Prototype)", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e587ca91518a47753a28217cd4fd586", "Telesys, Jim Rupp, Jack Woodman", "1001", "Coco Nuts (1982) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e750000af77cc76232f4d040f4ab060", "Jone Yuan Telephonic Enterprise Co", "", "Raft Rider (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e85f8bccb4b866d4daa9fcf89306474", "Atari, Lou Harp", "CX26122", "Sinistar (02-13-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1e89f722494608d6ea15a00d99f81337", "", "", "River Raid (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC50", "", "", "", "", "", "", "" }, + { "1ea1abcd2d3d3d628f59a99a9d41b13b", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ea980574416bfd504f62575ba524005", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ec57bbd27bdbd08b60c391c4895c1cf", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (09-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ec5bef77b91e59313cba205f15b06d7", "", "", "Overhead Adventure Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ede4f365ce1386d58f121b15a775e24", "Parker Brothers, Dave Hampton, Tom Sloper", "931517", "Q-bert (1983) (Parker Bros) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ee2cfc7d0333b96bd11f7f3ec8ce8bc", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (4 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ee9c1ba95cef2cf987d63f176c54ac3", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675, CX2675P", "Ms. Pac-Man (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1ef04e7e508296a8d9eb61cc7dae2e5d", "SOLID Corp. (D. Scott Williamson)", "CX2655-069", "Star Castle 2600 (SolidCorp) [069]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1f21666b8f78b65051b7a609f1d48608", "K-Tel Vision", "", "Vulture Attack (1982) (K-Tel Vision)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f2ae0c70a04c980c838c2cdc412cf45", "Atari - GCC", "CX2698", "Rubik's Cube (1984) (Atari)", "AKA Atari Video Cube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f349dd41c3f93c4214e5e308dccb056", "", "", "Virtual Pet Demo 2 (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f40eefc7447336ae6cd8ffa5eb325be", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f562b89d081e36d58e6fc943512ec05", "", "", "Hangman Man Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f5a2927a0b2faf87540b01d9d7d7fd1", "Pet Boat", "", "Tennis (Pet Boat) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1f60e48ad98b659a05ce0c1a8e999ad9", "", "", "Mondo Pong V2 (Piero Cavina) (PD)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "1f773a94d919b2a3c647172bbb97f6b4", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (07-11-1983) (Atari) (Prototype) (PAL)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1fa58679d4a39052bd9db059e8cda4ad", "Imagic, Dan Oliver", "720118-1A, 03208", "Laser Gates (1983) (Imagic)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1fa7a42c2c7d6b7a0c6a05d38c7508f4", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-04-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "1fa86282403fa35d103ab88a9d603c31", "SpiceWare - Darrell Spice Jr.", "", "Stay Frosty (SpiceWare) (PAL60)", "Part of Stella's Stocking 2007 Xmas compilation", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "1fab68fd67fe5a86b2c0a9227a59bb95", "20th Century Fox Video Games - Videa, Lee Actor", "", "Lasercade (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "200309c8fba0f248c13751ed4fc69bab", "Jeffry Johnston", "", "Radial Pong - Version 1 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2008c76deba5953201ef75a09b2ff7dc", "", "", "Fortress (21-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "200a9d2a7cb4441ce4f002df6aa47e38", "", "", "Doomzerk (PD) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2016726db38ad6a68b4c48ba6fe51557", "Piero Cavina, Erik Mooney", "", "INV 2 (Piero Cavina, Erik Mooney)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "203049f4d8290bb4521cc4402415e737", "Tigervision, Robert H. O'Neil - Teldec", "7-007 - 3.60005 VG", "Polaris (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "203abb713c00b0884206dcc656caa48f", "Imagic, Bob Smith", "720114-1A, 03207, IZ-001-04", "Moonsweeper (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "203b1efc6101d4b9d83bb6cc1c71f67f", "Quelle", "685.996 1", "Teller-Jonglieren! (1983) (Quelle) (PAL)", "AKA Dancing Plate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "205070b6a0d454961dd9196a8e81d877", "", "", "Hangman Monkey Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2058cf3fefad4d2bc03ed817cedddcd4", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2091af29b4e7b86914d79d9aaa4cbd20", "CBS Electronics - Woodside Design Associates, Harley H. Puthuff Jr.", "4L1802", "Donkey Kong Junior (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "20ae62fb69c6cc6e8098cca8cd080487", "Zirok", "", "Tennis (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "20d4457ba22517253fcb62967af11b37", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "20dca534b997bf607d658e77fbb3c0ee", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1002", "Fire Fly (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "20edcc3aa6c189259fa7e2f044a99c49", "Spectravision - Spectravideo", "SA-201", "Gangster Alley (1982) (Spectravision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "211774f4c5739042618be8ff67351177", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "211f76dff0b7dad3f6fcac9d938ee61a", "JSK", "", "Custer's Viagra (JSK) (Hack) [a]", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "211fbbdbbca1102dc5b43dc8157c09b3", "Apollo", "AP-2009", "Final Approach (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2124cf92978c46684b6c39ccc2e33713", "", "", "Sea Monster (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "21299c8c3ac1d54f8289d88702a738fd", "K-Tel Vision", "", "Spider Maze (1982) (K-Tel Vision)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "212d0b200ed8b45d8795ad899734d7d7", "Atari, Richard Maurer, Christopher H. Omarzu - Coca Cola", "", "Pepsi Invaders (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "213e5e82ecb42af237cfed8612c128ac", "Sancho - Tang's Electronic Co.", "TEC006", "Forest (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2162266b906c939b35c84ff9a0f50ad1", "Atari, Larry Kaplan", "CX2664, CX2664P", "Brain Games (1978) (Atari) (PAL) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2179dfd7edee76efafe698c1bc763735", "", "", "Yellow Submarine (Cody Pittman) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "217b1452881264ac75126bf77b8d0db8", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "218b76f5a4142dc2ea9051a768583d70", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2684, CX2684P", "Galaxian (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "218c0fe53dfaaa37f3c823f66eafd3fc", "Atari, Alan Miller", "CX2624, CX2624P", "Basketball (1978) (Atari) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "21a96301bb0df27fde2e7eefa49e0397", "Data Age", "DA1003", "Sssnake (1982) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "21b09c40295c2d7074a83ae040f22edf", "", "", "Marble Craze (V0.90) (Easy Version) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "21d2c435bcccde7792d82844b3cf60f4", "Atari - GCC, Doug Macrae", "CX2677, CX2677P", "Dig Dug (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "21d7334e406c2407e69dbddd7cec3583", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2228c67d25e507603d4873d3934f0757", "", "", "Fu Kung! (V0.10) (28-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "22319be7a640af5314ec3c482cceb676", "", "", "Joustpong (05-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2240655247d6de1c585564004a853ab7", "", "", "Fu Kung! (V0.17) (07-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "225522777dc7155627808bde0c1d0ef0", "", "", "This Planet Sucks Demo 1 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "22675cacd9b71dea21800cbf8597f000", "Atari, David Crane", "CX2605, CX2605P", "Outlaw (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "227532d82505c3c185a878273c285d5f", "", "", "Hangman Man Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "22abbdcb094d014388d529352abe9b4b", "Apollo", "AP-2012", "Squoosh (1983) (Apollo) (Prototype) [a]", "AKA Vat's Incredible!, The Grape Escape", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "22b22c4ce240303012e8a9596ae8d189", "", "", "Skeleton+ (03-05-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "22f6b40fc82110d68e50a1208ae0bb97", "", "", "Purple Bar Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2319922df4d0c820b3e5f15faa870cc3", "Atari - GCC, Mike Feinstein", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2327456f86d7e0deda94758c518d05b3", "Digitel", "", "Mr. Postman (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2351d26d0bfdee3095bec9c05cbcf7b0", "", "", "Warring Worms (19-01-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2353725ec98e0f0073462109e886efd7", "Champ Games", "CG-03-P", "Scramble (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "235436ab0832370e73677c9c6f0c8b06", "", "", "Beast Invaders (Double Shot) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2365e1534d67f94d8670394ab99150ce", "Thomas Jentzsch", "", "Missile Command (Atari Mouse) (2002) (TJ)", "Uses Atari ST Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "ATARIMOUSE", "ATARIMOUSE", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "23d445ea19a18fb78d5035878d9fb649", "CBS Electronics - JWDA, Sylvia Day, Todd Marshall, Henry Will IV", "4L1818, 4L1819, 4L1820, 4L1821", "Mouse Trap (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "23e4ca038aba11982e1694559f3be10f", "", "", "Big Dig (V3) (20-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "23fad5a125bcd4463701c8ad8a0043a9", "CCE", "C-840", "Stone Age (1983) (CCE)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "A", "A", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "240bfbac5163af4df5ae713985386f92", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2432f33fd278dea5fe6ae94073627fcc", "CBS Electronics, Tom DiDomenico", "4L2477, 4L2482, 4L2485, 4L4171", "Blueprint (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2434102f30eeb47792cf0825e368229b", "Sparrow - Enter-Tech, Paul Walters, Rick Harris, George Hefner, Barbara Ultis", "", "Arkyology (1983) (Sparrow) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24385ba7f5109fbe76aadc0a375de573", "CCE", "", "Xevious (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2447e17a4e18e6b609de498fe4ab52ba", "CCE", "", "Super Futebol (CCE)", "AKA RealSports Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "244c6de27faff527886fc7699a41c3be", "", "", "Matt Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2450dfa1df70d12b60683185775efed8", "Jeffry Johnston", "", "Radial Pong - Version 7 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24544ee5d76f579992d9522e9b238955", "Carrere Video - Western Technologies, Jeff Corsiglia, David Johnson, Tom Sloper - Teldec - Prism", "USC2004", "Picnic (1983) (Carrere Video) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "245f07c8603077a0caf5f83ee6cf8b43", "Home Vision - Thomas Jentzsch", "", "Parachute (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24759be31e8fe55d2829fd86bdf3181f", "Hozer Video Games", "", "Gunfight 2600 - Worst Nightmare... (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "247fa1a29ad90e64069ee13d96fea6d6", "CCE", "C-867", "Radar (1983) (CCE)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "248668b364514de590382a7eda2c9834", "CBS Electronics, Richard K. Balaska Jr., Bob Curtiss, Alex Leavens, Alex Nevelson", "", "Kick-Man (01-08-82) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2496d404bfc561a40a80bea6a69695c3", "CCE", "C-1007", "Jungle Hunt (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24ad538291eb5f5cac4b9998f3b851c3", "", "", "Gunfight 2600 - This time it's your decission! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24aff972d58990f9b88a6d787c796f1e", "CBS Electronics", "4L1767, 4L1768, 4L1769, 4L1770", "Smurf (1982) (CBS Electronics) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24b5f4bbdb853eca38ea0cae2dfe73a1", "", "", "Home Run (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24b9adac1b4f85b0bac9bf9b9e180906", "Angelino", "", "Space 2002 (Angelino) (Hack)", "Hack of Space Jockey", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24d018c4a6de7e5bd19a36f2b879b335", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "24d9a55d8f0633e886a1b33ee1e0e797", "Thomas Jentzsch", "", "Dragon Defender (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "24df052902aa9de21c2b2525eb84a255", "Imagic, Dennis Koble", "720000-100, 720100-1B, IA3000, IA3000C", "Trick Shot (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "24fbf8250a71611e40ef18552e61b009", "", "", "Movable Grid Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2516f4f4b811ede4ecf6fbeb5d54a299", "Quelle", "701.134 9", "Schiessbude (1983) (Quelle) (PAL)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2517827950fee41a3b9de60275c8aa6a", "Atari", "CX26163P", "Fishing (32 in 1) (1988) (Atari) (PAL)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25265d0e7f88b3026003809f25ee025e", "Atari - GCC, Ava-Robin Cohen", "CX26123", "Jr. Pac-Man (1984) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25472dfdeef6a42581a231d631d6b04d", "", "", "Gunfight 2600 - Design thoughts (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25710bde8fa181b0c5cf0846b983bec1", "", "", "Demo Image Series #15 - Three Marios (NTSC) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "257bc3b72a6b5db3fd0d47619125b387", "CBS Electronics", "4L 2737 0000", "Omega Race (1983) (CBS Electronics) [a]", "Set right difficulty to 'A' for BoosterGrip in both ports", "", "", "", "", "", "", "", "", "BOOSTERGRIP", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25a21c47afe925a3ca0806876a2b4f3f", "Quelle", "685.640 5", "Der kleine Baer (1983) (Quelle) (PAL)", "AKA Frostbite", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25b52bf8dd215bcbd59c9abdb55c44f8", "Atari - GCC, Betty Ryan Tylko, Doug Macrae", "CX2694, CX2694P", "Pole Position (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25b6dc012cdba63704ea9535c6987beb", "Avalon Hill, Jean Baer, Bill Hood", "5004002", "Shuttle Orbiter (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25bb080457351be724aac8a02021aa92", "CBS Electronics", "4L1784, 4L1786, 4L1787, 4L2277", "Zaxxon (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25d4be3309b89583c6b39d9f93bf654f", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25e73efb9a6edf119114718bd2f646ba", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (1983) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25f2e760cd7f56b88aac88d63757d41b", "Activision, Bob Whitehead - Ariola", "EAG-002, EAG-002-04I, PAG-002 - 711 002-715", "Boxing (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25f879ff678130fea615ac418e7943f1", "Activision, Garry Kitchen", "EAX-025", "Keystone Kapers (1983) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "25f9cf703575c5d63048c222f5463758", "", "", "Multi-Sprite Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "260c787e8925bf3649c8aeae5b97dcc0", "Thomas Jentzsch", "", "Hell Driver (Thomas Jentzsch)", "NTSC Conversion, joystick ports swapped", "Homebrew", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "262ccb882ff617d9b4b51f24aee02cbe", "Atari, Douglas Neubauer", "CX26154, CX26154P", "Super Football (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "265a85f66544eaf95fda06c3d9e48abf", "", "", "Tunnel Demo (Cycling Colours) (29-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "265c74a956500bd31efd24adc6d5ccf6", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2683d29a282dd059535ac3bb250f540d", "", "", "Space Treat (12-01-2003) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "268f46038e29301568fa9e443e16e960", "Atarius Maximum", "", "Pitfall Unlimited (Atarius Maximus) (Hack)", "Hack of Pitfall", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "26bc2bdf447a17376aea7ef187ff6e44", "", "", "Amanda Invaders (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "26f4f8b098609164effef7809e0121e1", "", "", "Oystron (V2.7) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "270229c6d5578446e6a588492e4e5910", "", "", "Space Invaders 2 (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2712e91f6f1dc55e90e2b14b27c042ac", "Omegamatrix", "", "SpaceMaster X-7 (Amiga Mouse) (PAL60) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "271bfd5dc2673d382019f1fb6cab9332", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (Preview) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "273ce50db5a0d6da7ea827a54f44dee9", "", "", "Island Flyer Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "274d17ccd825ef9c728d68394b4569d2", "Playaround - J.H.M.", "202", "Bachelorette Party (1982) (Playaround)", "AKA Bachelor Party, Uses the paddle controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "277c7281ac945b8331e2e6fcad560c11", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (2 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "277cca62014fceebb46c549bac25a2e3", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "277fa4b9a6bb7a8dcea2c5f38a4c25f0", "Atari, Alan J. Murphy, Robert Zdybel", "CX2668", "RealSports Football (1982) (Atari) (Prototype)", "AKA Football II", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "278155fc9956e9b6ef2359eb238f7c7f", "", "", "Donkey Kong Junior (Unknown) (Hack)", "Hack of Donkey Kong Junior", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2783006ee6519f15cbc96adae031c9a9", "Telegames", "", "Night Stalker (1989) (Telegames) (PAL) [a]", "AKA Dark Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "278531cc31915747018d22145823d2c9", "", "", "Defender MegaDrive (PAL) (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "278f14887d601b5e5b620f1870bc09f6", "Thomas Jentzsch", "", "SWOOPS! (v0.96) (TJ)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "27a5d2d0c74c8e4b2c05b94c9f098eea", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (PAL60) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "27baecd618e7e53dc11f2a9c559f529d", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "27c4c2af4b46394bb98638af8e0f6e9d", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "27c6a2ca16ad7d814626ceea62fa8fb4", "Parker Brothers, Mark Lesser", "PB5590", "Frogger II (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "27f9e2e1b92af9dc17c6155605c38e49", "CCE", "", "Nightmare (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2808dc745ff4321dc5c8122abef6711f", "Retroactive", "", "Qb (2.11) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "28148a52b1955ce12c7a74d3a3e620a4", "CCE", "", "Freeway (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "281ff9bd0470643853de5cbd6d9e17f5", "Eckhard Stolberg", "", "Cubis (EM) (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2823364702595feea24a3fbee138a243", "Bit Corporation", "PG206", "Bobby Is Going Home (1983) (BitCorp) (PAL)", "AKA Bobby geht Heim", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2825f4d068feba6973e61c84649489fe", "", "", "Boom Bang (Unknown) (PAL)", "AKA Crackpots", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "282a77841cb3d33af5b56151acba770e", "Otto Versand", "311388", "Black Hole (1983) (Otto Versand) (PAL)", "AKA Cosmic Ark (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "283cb03ee031c842beabdad1aa4e7dbc", "Bit Corporation", "R320", "Demon Attack (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "283dee88f295834c4c077d788f151125", "Retroactive", "", "Qb (2.11) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "284ca61b2407bdba3938048b0a559015", "Atari, Tod Frye", "CX2695", "Xevious (05-25-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2854e5dfb84173fafc5bf485c3e69d5a", "Canal 3 - Intellivision", "C 3004", "Moon Patrol (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2880c6b59bd54b153174676e465167c7", "Tron", "", "Donkey Kong Jr. (Tron)", "AKA Donkey Kong Junior", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "28a2bea8f84936cb2e063f857414cda0", "Thiago Paiva", "", "Mega Mania Raid (1999) (Thiago Paiva) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "28a4cd87fb9de4ee91693a38611cb53c", "", "", "Skeleton (V1.1) (NTSC) (24-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "28d5df3ed036ed63d33a31d0d8b85c47", "Bit Corporation", "PG204", "Open, Sesame! (1983) (BitCorp) (PAL)", "AKA Sesam, Offne Dich", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2903896d88a341511586d69fcfc20f7d", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "291bcdb05f2b37cdf9452d2bf08e0321", "Atari", "CX26163P", "32 in 1 Game Cartridge (1988) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "32IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "291cc37604bc899e8e065c30153fc4b9", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "291dd47588b9158beebe4accc3a093a6", "Atari", "", "32 in 1 Console ROM (02-10-1989) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "32IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "292a0bb975b2587f9ac784c960e1b453", "", "", "Qb (05-02-2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "292f2446a0325b7b423e88a2ebfeb5a0", "", "", "Cube Conquest (Non Interlaced) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "29396db58406084e416032c372734a3e", "", "", "Gunfight 2600 - Fixed Beta Release! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2942680c47beb9bf713a910706ffabfe", "", "", "Blue Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "294762000e853b4319f9991c1ced5dfc", "", "", "T.F. Space Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "295f3679bdf91ca5e37da3f787b29997", "", "", "Exorcise (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "29630a20d356fb58685b150bfa8f00c3", "M Network, Kevin Miller", "MT5687", "International Soccer (1982) (Mattel) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "297236cb9156be35679f83c4e38ee169", "Exus Corporation", "", "Video Reflex (1983) (Exus) [no roman numbers]", "AKA Foot Craz (no roman numbers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "297c405afd01f3ac48cdb67b00d273fe", "Atari - GCC, Ava-Robin Cohen", "CX26123, CX26123P", "Jr. Pac-Man (1986) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2982e655dffc89d218a0a3072cfc6811", "", "", "Mini Golf 812631 (Hack)", "Hack of Miniature Golf", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "298387b0637173d2002770a649b4fbca", "", "", "S.I.PLIX 2 (Hack) [a]", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "29843f43b81f3736bf35c00b1bb88fb2", "Gray Games & AtariAge", "", "E.T. Book Cart (NTSC)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "55", "", "", "", "" }, + { "29949f893ef6cb9e8ecb368b9e99eee4", "Erik Eid", "", "Euchre (Alpha) (NTSC) (31-08-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "29dfa26b7988af9984d617708e4fc6e2", "", "", "Boulderdash Demo (05-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2a0ba55e56e7a596146fa729acf0e109", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2a10053fd08664c7cfbbb104386ed77f", "", "", "Alpha Demo - The Beta Demo (2000) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2a1b454a5c3832b0240111e7fd73de8a", "Tigervision, Bill Hogue", "7-011", "Miner 2049er Volume II (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2a2f46b3f4000495239cbdad70f17c59", "CommaVid, John Bronstein - Ariola", "CM-003 - 712 003-720", "Cosmic Swarm (1982) (CommaVid) (PAL)", "AKA Angriff der Termiten", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2a33e21447bf9e13dcfed85077ff6b40", "", "", "Backwards Cannonball v2 (Hack)", "Hack of Human Cannonball", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2a360bc85bf22de438651cf92ffda1de", "Bit Corporation", "PGP213", "Spy Vs. Spy (4 Game in One) (1983) (BitCorp) (PAL)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2a9f9001540c55a302befd8e9d54b47b", "Atari, Dan Hitchens", "CX2697, CX2697P", "Mario Bros. (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2aa5e56d36c2e58b6f2856109f2099a9", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2aba6a1b01a5859e96d6a66d2286772f", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2abc3d46b3f2140160759e2e10bc86d9", "", "", "Gunfight 2600 - Beta Release! (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2ac3a08cfbf1942ba169c3e9e6c47e09", "Activision, Dan Kitchen", "EAK-046-04B", "Fighter Pilot (1988) (Activision) (PAL)", "AKA Tomcat - The F-14 Fighter Simulator", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2ae700c9dba843a68dfdca40d7d86bd6", "TechnoVision - Thomas Jentzsch", "", "Pharaoh's Curse (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2aeedcc6eb1602efb77161b0cef832ab", "SOLID Corp. (D. Scott Williamson)", "CX2655-025", "Star Castle 2600 (SolidCorp) [025]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2b1589c7e1f394ae6a1c046944f06688", "Carrere Video - JWDA, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV - Teldec - Prism", "USC2003", "Eggomania (1983) (Carrere Video) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "2b27eb194e13f3b38d23c879cc1e3abf", "Quelle", "402.272 9", "Super-Ferrari (1983) (Quelle) (PAL)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2b42da79a682ed6e2d735facbf70107e", "", "", "DKjr Improved (Hack)", "Hack of Donkey Kong Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2b430c00dc79e495762ac59b2f9b4fcd", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2b71a59a53be5883399917bf582b7772", "Greg Troutman", "", "Dark Mage (final beta) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2ba02f509a4991aa176ba8d9e540df3d", "Atari, Mark R. Hahn", "CX2678", "Dukes of Hazzard (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bb0a1f1dee5226de648eb5f1c97f067", "Robby", "", "Enduro (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bb9f4686f7e08c5fcc69ec1a1c66fe7", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bc26619e31710a9884c110d8430c1da", "Atari, Bob Whitehead", "CX2652, CX2652P", "Casino (1979) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bc6c53b19e0097a242f22375a6a60ff", "", "", "Droid Demo 2 (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bee7f226d506c217163bad4ab1768c0", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2bf34b6ad7d2317a2d0808b3fb93571b", "", "", "Easy Playfield Graphics (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c0dc885d5ede94aa664bf3081add34e", "", "", "Earth Dies Screaming, The (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c29182edf0965a7f56fe0897d2f84ba", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (08-18-1990) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c2aea31b01c6126c1a43e10cacbfd58", "Paul Slocum", "", "Synthcart (2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2c3b2843295c9d6b16996971180a3fe9", "HES - Activision", "", "Sports Action Pak - Enduro, Ice Hockey, Fishing Derby, Dragster (1988) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c3b9c171e214e9e46bbaa12bdf8977e", "Bit Corporation", "R320", "Othello (32 in 1) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c45c3eb819a797237820a1816c532eb", "Atari", "CX26163P", "Boxing (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c8835aed7f52a0da9ade5226ee5aa75", "Arcadia Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c8c11295d8613f875b7bcf5253ab9bb", "Fabrizio Zavagli", "", "Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) (PAL60)", "PAL60 Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2c9fadd510509cc7f28f1ccba931855f", "", "", "Hangman Invader Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2ca6445204ffb7686ddee3e33ba64d5b", "Alex Herbert", "", "AtariVox Test ROM", "Uses the AtariVox controller", "", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2cb42cf62b2f25f59f909b5447821b14", "Atari, Christopher H. Omarzu - Children's Computer Workshop", "CX26104", "Big Bird's Egg Catch (1983) (Atari) (PAL) [a]", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2cc3049b7feb8e92f1870f1972629757", "Video Soft", "", "Atom Smasher (1984) (Video Soft) (Prototype) [stack pointer fix]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2cccc079c15e9af94246f867ffc7e9bf", "PlayAround - J.H.M.", "203", "Jungle Fever (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2cefa695df2ed020899a7df7bb1e3a95", "Manuel Polik, Fabrizio Zavagli", "", "A-Team (2002) (Manuel Polik) (Hack)", "Hack of A-Team", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2cf20f82abcae2decff88db99331e071", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2cfb188c1091cc7ec2a7e60064d2a758", "", "", "Space Invaders Hack Demo (2003) (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d15b092e8350912ec4b2e5e750fa1c6", "Wizard Video Games, Bob Davis, Robert H. O'Neil", "", "Texas Chainsaw Massacre, The (1982) (Wizard Video Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d16a8b59a225ea551667be45f554652", "Quelle", "802.744 3", "Der Geheimkurier (1983) (Quelle) (PAL)", "AKA Mr. Postman", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d1cf85fbc732856bf76470cd4060f4a", "", "", "Daredevil (V1) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d2c5f0761e609e3c5228766f446f7f8", "Atari - Axlon, Steve DeFrisco", "CX26170, CX26170P", "Secret Quest (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d33a44e82f88d05f6c50577218c0cae", "AtariAge - Michael Haas", "RC2", "Flappy (2014) (AtariAge)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d38a96f92952b301eefdf25a5e6976b", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) (Y_Inverted) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d405da70af82b20a6b3ecc3d1d2c4ec", "Genus", "", "Pitfall (Genus)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d6388a8389f1d59108fd169c3356d79", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d63b452f897818c52b3fceeb080a4d0", "HES - Absolute Entertainment", "", "Pete Rose Baseball (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d6741cda3000230f6bbdd5e31941c01", "CBS Electronics - VSS", "80110", "Targ (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d69a5f23784f1c2230143292a073b53", "", "", "Qb (Fixed background animation) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2d6da0eb85eabc93270e5bb8a466ca51", "", "", "Sprite Demo 7 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d76c5d1aad506442b9e9fb67765e051", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo", "AP-2004", "Lost Luggage (1982) (Apollo) [no opening scene]", "AKA Airport Mayhem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d9e5d8d083b6367eda880e80dfdfaeb", "QDI, Mike Montana, Rich Montana - Selchow & Righter", "87", "Glib (1983) (QDI)", "AKA Video Word Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2d9e65959808a6098c16c82a59c9d9dc", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2dbc92688f9ba92a7e086d62be9df79d", "", "", "How to Draw a Playfield (1997) (Jim Crawford) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2dbdca3058035d2b40c734dcf06a86d9", "Thomas Jentzsch", "", "Asteroids DC+ (Thomas Jentzsch) (Hack)", "Uses the Joystick (left) or Driving (right) Controller", "Hack", "", "", "", "", "", "", "", "", "DRIVING", "", "", "", "58", "", "", "YES", "", "", "", "", "" }, + { "2dcf9ce486393cd36ca0928cd53b96cb", "Atari - GCC, Mike Feinstein, John Allred", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2de41a11c6767e54a5ee9ebaffec72af", "Gray Games & AtariAge", "", "E.T. Book Cart (PAL60)", "Charles F. Gray & Michael Rideout", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "55", "", "", "", "" }, + { "2dfec1615c49501fefc02165c81955e6", "", "", "Song (05-11-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2e0aed5bb619edcefa3fafb4fbe7c551", "", "", "Qb (2.06) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2e2acef8513edcca991e7e5149412e11", "Parker Brothers, Larry Gelberg, Gary Goltz", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (16K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e3728f3086dc3e71047ffd6b2d9f015", "Atari, David Crane", "CX26163P", "Outlaw (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e5b184da8a27c4d362b5a81f0b4a68f", "Atari", "", "Rabbit Transit (08-29-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e663eaa0d6b723b645e643750b942fd", "Atari, Tom Rudadahl - Sears", "CX2634 - 49-75121", "Golf (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e7e9c6dcfcceaffc6fa73f0d08a402a", "CCE", "C-818", "Star Voyager (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e82a1628ef6c735c0ab8fa92927e9b0", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2e842c2ee22e9dad9df16eed091315c4", "HES", "701-157", "2 Pak Special - Moto-cross, Boom Bang (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2eaf8fa9e9fdf1fcfc896926a4bdbf85", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur Version 39 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2ec6b045cfd7bc52d9cdfd1b1447d1e5", "Activision, David Crane - Ariola", "EAG-009, PAG-009 - 711 009-720", "Freeway (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2eda6a49a49fcb2b674ea9e160b6a617", "Kyle Pittman", "", "Rambo in Afghanistan (Kyle Pittman) (Hack)", "Hack of Riddle of the Sphinx", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2ef36341d1bf42e02c7ea2f71e024982", "", "", "Space Invaders (Explosion Hack)", "Hack of Space Invaders (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f0546c4d238551c7d64d884b618100c", "SEGA, Jeff Lorenz", "", "Ixion (1984) (SEGA) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f0a8bb4e18839f9b1dcaa2f5d02fd1d", "CCE", "", "Super Futebol (CCE) [a]", "AKA RealSports Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2f11ba54609777e2c6a5da9b302c98e8", "Atari - GCC", "CX2676", "Centipede (1982) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f16663b01591539624d0ef52934a17d", "M Network", "", "Rocky and Bullwinkle", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f2f9061398a74c80420b99ddecf6448", "Rentacom - Brazil", "", "Bobby Is Going Home (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f66ebf037321ed0442ac4b89ce22633", "Baroque Gaming (Brian Eno)", "", "Warring Worms (Beta 2) (2002) (Baroque Gaming)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f7772879a1ed04f660aa9d77a86a4bd", "", "", "Yars' Revenge (Genesis)", "Genesis controller (C is zorlon cannon)", "Hack of Yars' Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "2f77f015fc880b05f28e84156f989a0c", "", "", "Plane Demo (Gonzalo) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2f7949f71076db42480d3f5036b4a332", "", "", "Name This Game (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "2facd460a6828e0e476d3ac4b8c5f4f7", "Sancho - Tang's Electronic Co.", "", "Words-Attack (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3025bdc30b5aec9fb40668787f67d24c", "", "", "Demo Image Series #14 - Two Marios (4K Interleaved Chronocolour Vertical Movement) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "303242c239474f2d7763b843de58c1c3", "CCE", "", "Laser Blast (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "304512528a5530a9361e8a231ed9a6de", "Thomas Jentzsch", "", "River Raid Plus (Thomas Jentzsch) (Hack)", "Hack of River Raid", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "30512e0e83903fc05541d2f6a6a62654", "Atari, Jim Huether - Sears", "CX2644 - 6-99824", "Flag Capture (1978) (Atari)", "AKA Capture the Flag", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "30516cfbaa1bc3b5335ee53ad811f17a", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3051b6071cb26377cd428af155e1bfc4", "Atari, David Crane - Sears", "CX2607 - 6-99828, 49-75115", "Canyon Bomber (1979) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "", "", "10", "", "", "", "", "", "", "", "" }, + { "30685b9b6ebd9ba71536dd7632a1e3b6", "Dactari - Milmar", "", "Tennis (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3091af0ef1a61e801f4867783c21d45c", "CCE", "C-862", "Crackpots (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "30997031b668e37168d4d0e299ccc46f", "", "", "John K Harvey's Equalizer (PAL) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "30c92c685224dc7a72b9bbe5eb62d004", "", "", "Hangman Monkey Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "30e012e8d50330c8972f126b8e913bc4", "", "", "Indy 500 (Hack) [a2]", "Hack of Indy 500", "Hack", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "30e0ab8be713208ae9a978b34e9e8e8c", "Atari, Mike Lorenzen", "CX2630, CX2630P", "Circus Atari (1980) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, + { "30f0b49661cfcfd4ec63395fab837dc3", "SEGA, Jeff Lorenz - Teldec", "004-01", "Star Trek - Strategic Operations Simulator (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3105967f7222cc36a5ac6e5f6e89a0b4", "SEGA, Jeff Lorenz", "011-01, 011-02", "Spy Hunter (1984) (SEGA)", "Uses Joystick Coupler (Dual Control Module)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "310ba30e25ea8957e58180b663503c0c", "Ed Federmeyer", "", "Sound X6 (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31235a27b065c2863048fa84db330dc6", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (PAL) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "313243fc41e49ef6bd3aa9ebc0d372dd", "", "", "Fast Food (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31512cdfadfd82bfb6f196e3b0fd83cd", "Tigervision", "7-004", "River Patrol (1984) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3177cc5c04c1a4080a927dfa4099482b", "Atari - Imagineering, Alex DeMeo", "CX26135", "RealSports Boxing (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "317a4cdbab090dcc996833d07cb40165", "Goliath - Hot Shot", "83-312", "Missile War (1983) (Goliath) (PAL)", "AKA Astrowar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "318046ae3711c05fd16e479b298e5fcc", "Retroactive", "", "Qb (V2.08) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "318a9d6dda791268df92d72679914ac3", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "319a142aab6260842ab616382848c204", "", "", "Marble Craze (05-02-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31bb9b8ceed46cb3e506777a9e65f3ce", "Bit Corporation", "", "4 Game in One Light Green (1983) (BitCorp) (PAL)", "Phantom UFO, Ice Hockey, Cosmic Avenger, Spy Vs. Spy", "", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31c5fd55a39db5ff30a0da065f86c140", "Dactari - Milmar", "", "Enduro (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31d08cb465965f80d3541a57ec82c625", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31df1c50c4351e144c9a378adb8c10ba", "Quelle", "687.463 0", "Die Ratte und die Karotten (1983) (Quelle) (PAL)", "AKA Gopher", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31e518debba46df6226b535fa8bd2543", "Atari, Douglas 'Solaris' Neubauer, Mimi Nyden", "CX26134", "Last Starfighter (1984) (Atari) (Prototype)", "Solaris Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31f4692ee2ca07a7ce1f7a6a1dab4ac9", "Atari, Alan Miller", "CX2642", "Game of Concentration (1980) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "31fcbce1cfa6ec9f5b6de318e1f57647", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (1983) (Atari) (Prototype) (PAL)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32199271dc980eb31a2cc96e10a9e244", "", "", "Radial Pong - Version 12 (Jeffry Johnston) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "321c3451129357af42a375d12afd4450", "Atari - Imagineering, Dan Kitchen", "CX26177", "Ikari Warriors (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32244e55ce6ec6bfbd763f33384bdc2e", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3225676f5c0c577aeccfaa7e6bedd765", "CCE", "C-1002", "Pole Position (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "322b29e84455aa41e7cc9af463bffa89", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (06-25-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "324cb4a749bcac4f3db9da842b85d2f7", "Dennis Debro", "", "Climber 5 (01-05-2003) (Dennis Debro)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "327468d6c19697e65ab702f06502c7ed", "Charles Morgan", "", "Aster-Hawk (2002) (Charles Morgan) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3276c777cbe97cdd2b4a63ffc16b7151", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3278158e5c1f7eb5c5d28ccfd7285250", "Dactari - Milmar", "", "Megamania (Dactari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "327fe8cf94f3a45c35a840a453df1235", "", "", "Spice Girls Rule Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "328949872e454181223a80389d03c122", "", "", "Home Run (Unknown) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32ae78abbb5e677e2aabae5cc86cec29", "Atari, Christopher H. Omarzu, Courtney Granner", "CX26112", "Good Luck, Charlie Brown (04-18-1984) (Atari) (Prototype)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32d1260ea682e1bb10850fa94c04ec5f", "Atari, Alan Miller", "CX26163P", "Basketball (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32dcd1b535f564ee38143a70a8146efe", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox)", "AKA Thundarr the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32e65d1e4dfcbcd9b57fee72cafe074c", "", "", "Eckhard Stolberg's Scrolling Text Demo 3 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32ecb5a652eb73d287e883eea751d99c", "Dactar - Milmar", "", "Bowling (Dactar - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "32f4e47a71601ab06cfb59e1c6a0b846", "Ed Federmeyer", "", "Sound X (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3316ee2f887e9cb9b54dd23c5b98c3e2", "", "", "Texas Golf (miniature Gold Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "331938989f0f33ca39c10af4c09ff640", "Zach Matley", "", "Combat - Tank AI (19-04-2003) (Zach Matley)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "332f01fd18e99c6584f61aa45ee7791e", "", "", "X'Mission (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3347a6dd59049b15a38394aa2dafa585", "Parker Brothers - JWDA, Henry Will IV", "PB5760", "Montezuma's Revenge (1984) (Parker Bros)", "Featuring Panama Joe", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "335793736cbf6fc99c9359ed2a32a49d", "", "", "Analog Clock (V0.0) (20-01-2003) (AD) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "335a7c5cfa6fee0f35f5824d1fa09aed", "SEGA - Beck-Tech, Steve Beck, Phat Ho - Teldec", "006-01 - 3.60105 VG", "Congo Bongo (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3367eeba3269aa04720abe6169767502", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "336ea20d38f98926919d4b4651d1a03f", "Omegamatrix", "", "Omega Race (Genesis) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3391f7c4c656793f92299f4187e139f7", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a4]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "33cac5e767a534c95d292b04f439dc37", "Jone Yuan Telephonic Enterprise Co", "", "Tapeworm (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "33d68c3cd74e5bc4cf0df3716c5848bc", "CBS Electronics, Tom DiDomenico", "4L 2486 5000", "Blueprint (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "33ed6dfac4b9ea2f81f778ceddbb4a75", "Activision", "", "River Raid (1982) (SpkSoft) [t1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "340f546d59e72fb358c49ac2ca8482bb", "Sancho - Tang's Electronic Co.", "TEC003", "Skindiver (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34340c8eecd1e557314789cc6477e650", "Joe Grand", "", "SCSIcide Pre-release 4 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "345488d3b014b684a181108f0ef823cb", "CBS Electronics, Tom DiDomenico", "4L 2486 5000", "Blueprint (1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "345758747b893e4c9bdde8877de47788", "CBS Electronics, Joseph Biel", "4L1802, 4L1803, 4L1804, 4L2278", "Venture (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "345769d085113d57937198262af52298", "Rainbow Vision - Suntek", "SS-007", "Space Raid (1983) (Rainbow Vision) (PAL)", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "346555779a2d51b48833463b5433472f", "Thomas Jentzsch", "", "Thrust (V0.1) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "348615ffa30fab3cec1441b5a76e9460", "Activision, Alan Miller - Ariola", "EAX-016, PAX-016 - 711 016-725", "StarMaster (1982) (Activision) (PAL) [fixed]", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34b269387fa1aa5a396636f5ecdd63dd", "", "", "Marble Craze (mc7_23) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34c808ad6577dbfa46169b73171585a3", "Apollo", "AP-2012", "Squoosh (1983) (Apollo) (Prototype)", "AKA Vat's Incredible!, The Grape Escape", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34ca2fcbc8ba4a0b544acd94991cfb50", "Atari, Robert C. Polaro", "", "Dukes of Hazzard (1980) (Atari) (Prototype) (4K)", "AKA Stunt Cycle", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34e37eaffc0d34e05e40ed883f848b40", "Retroactive", "", "Qb (2.15) (Retroactive) (Stella)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "34f4b1d809aa705ace6e46b13253fd3b", "Aaron Bergstrom", "", "Nothern Alliance (Aaron Bergstrom) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "34fd4fcb40ff5babce67f8b806d5969c", "", "", "Boxing (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "350e0f7b562ec5e457b3f5af013648db", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (06-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "35156407e54f67eb1f625450d5c093e1", "", "", "Mouse Trap (Genesis)", "Genesis controller (C changes to dog)", "Hack of Mouse Trap", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "35163b56f4a692a232ae96ad3e23310f", "Retroactive", "", "Qb (2.12) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3545eb3b8b1e7dc19f87d231ab0b1d4c", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "M8774, M8794", "Wizard of Wor (1982) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3556e125681aea864e17b09f3f3b2a75", "", "", "Incoming (2 Player Demo) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3576037c9281656655fa114a835be553", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3577e19714921912685bb0e32ddf943c", "TechnoVision - Video Technology", "TVS1003", "Pharaoh's Curse (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "35ae903dff7389755ad4a07f2fb7400c", "", "", "Colored Wall Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "35b10a248a7e67493ec43aeb9743538c", "Dor-x", "", "Defender (Dor-x) (Hack)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "35b43b54e83403bb3d71f519739a9549", "Parker Brothers, Dave Engman, Isabel Garret", "", "McDonald's (06-06-1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "35be55426c1fec32dfb503b4f0651572", "Men-A-Vision", "", "Air Raid (Men-A-Vision) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "35fa32256982774a4f134c3347882dff", "Retroactive", "", "Qb (V0.05) (Macintosh) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "360ba640f6810ec902b01a09cc8ab556", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (06-15-1983) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "360c0dcb11506e73bd0b77207c81bc62", "Digitel", "", "Enduro (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3619786f6a32efc1e4a262d5aca8a070", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3624e5568368929fabb55d7f9df1022e", "Activision - Imagineering, Donald Hahn, Dan Kitchen", "EAK-050-04", "Double Dragon (1989) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36306070f0c90a72461551a7a4f3a209", "U.S. Games Corporation - JWDA, Roger Booth, Sylvia Day, Ron Dubren, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV", "VC1007", "Name This Game (1983) (U.S. Games)", "AKA Octopussy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36547bc6faa5132b87504e18d088e1d7", "", "", "Cosmic Swarm (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "367411b78119299234772c08df10e134", "Atari", "CX26163P", "Skiing (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3685060707df27d4091ba0ea2dc4b059", "", "", "PezZerk - PezMan in Ghost Manor (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "368d88a6c071caba60b4f778615aae94", "Atari, Matthew L. Hubbard", "CX26159", "Double Dunk (1989) (Atari)", "AKA Super Basketball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36a701c60a9f9768d057bc2a83526a80", "", "", "Cube Conquest (Interlaced) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "36b20c427975760cb9cf4a47e41369e4", "Coleco - Woodside Design Associates - Imaginative Systems Software, Garry Kitchen", "2451", "Donkey Kong (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36c29ceee2c151b23a1ad7aa04bd529d", "Atari - GCC, Ava-Robin Cohen", "CX26123", "Jr. Pac-Man (1986) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36c31bb5daeb103f488c66de67ac5075", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, + { "36c993dc328933e4dd6374a8ffe224f4", "Gameworld, J. Ray Dettling", "133-007", "Bermuda Triangle (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36e47ed74968c365121eab60f48c6517", "Quelle", "343.373 7", "Master Builder (1983) (Quelle) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36edef446ab4c2395666efc672b92ed0", "Atari - Axlon, John Vifian", "CX26168", "Off the Wall (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "36f9a953ebdd9a8be97ccf27a2041903", "", "", "Chinese Character Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37252757a79dc5b174e3c03d6ea0bdcb", "", "", "Sky Diver (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "372bddf113d088bc572f94e98d8249f5", "Bomb - Onbase", "CA285", "Wall-Defender (1983) (Bomb) (PAL)", "AKA Wall Break", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "373b8a081acd98a895db0cb02df35673", "", "", "Demo Image Series #5 - Boofly (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3750f2375252b6a20e4628692e94e8b1", "Dismac", "", "Ases do Ar (Dismac)", "AKA Sky Jinks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37527966823ee9243d34c7da8302774f", "", "", "Word Zapper (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "376944889dcfa96c73d3079f308e3d32", "Retroactive", "", "Qb (0.11) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3783f12821b88b08814da8adb1a9f220", "", "", "Mission Survive (PAL) (Genesis)", "Genesis controller (C is vertical fire)", "Hack of Mission Survive)", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "378a62af6e9c12a760795ff4fc939656", "Atari - Axlon, Steve DeFrisco", "CX26171", "MotoRodeo (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "378c118b3bda502c73e76190ca089eef", "Atari, Alan Miller", "CX2662P", "Hangman (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37ab3affc7987995784b59fcd3fcbd31", "", "", "Sprite Test (29-11-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37b98344c8e0746c486caf5aaeec892a", "K-Tel Vision", "6", "Spider Maze (1982) (K-Tel Vision) (PAL)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37e828675d556775ae8285c0caf7d11c", "AtariAge - Fred Quimby", "", "Gingerbread Man (Fred Quimby) (Genesis)", "Genesis controller (C throws cookie)", "New Release", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37f42ab50018497114f6b0f4f01aa9a1", "", "", "Droid Demo 2-M (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "37fd7fa52d358f66984948999f1213c5", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL) [a2]", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "384db97670817103dd8c0bbdef132445", "Atari - Sears", "CX2626 - 6-99829, 49-75116", "Miniature Golf (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "384f5fbf57b5e92ed708935ebf8a8610", "20th Century Fox Video Games, John W.S. Marvin", "11009", "Crypts of Chaos (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3856b9425cc0185ed770376a62af0282", "Kyle Pittman", "", "Yellow Submarine (Kyle Pittman) (Hack)", "Hack of Bermuda Triangle", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "386ff28ac5e254ba1b1bac6916bcc93a", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "3882224adbd0ca7c748b2a1c9b87263e", "Atari, Tod Frye", "CX2657", "SwordQuest - FireWorld (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3889351c6c2100b9f3aef817a7e17a7a", "CCE", "", "Dolphin (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3897744dd3c756ea4b1542e5e181e02a", "Atari, Jerome Domurat, Peter C. Niday", "CX26115", "Dumbo's Flying Circus (05-05-1983) (Atari) (Prototype)", "AKA Dumbo Flies Home", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "38bd172da8b2a3a176e517c213fcd5a6", "Atari", "MA017600", "Diagnostic Test Cartridge 2.6 (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "38c362dcd5cad5a62e73ae52631bd9d8", "Jake Patterson", "", "Baubles (14-11-2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "38cf93eacfb2fa9a2c5e39059ff35a74", "Greg Zumwalt", "", "WacMan (2003) (Greg Zumwalt) (Hack)", "Hack of Ms. Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "38de7b68379770b9bd3f7bf000136eb0", "Imagic, Mark Klein", "EIZ-003-04I", "Subterranea (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "391764720140c432aec454a468f77a40", "Video Game Program", "", "Miss Pack Man (Video Game Program) (PAL)", "AKA Ms. Pac-Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "392d34c0498075dd58df0ce7cd491ea2", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "392f00fd1a074a3c15bc96b0a57d52a1", "Atari, Rob Fulop - Sears", "CX2633 - 49-75119", "Night Driver (1980) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "393948436d1f4cc3192410bb918f9724", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "393e41ca8bdd35b52bf6256a968a9b89", "U.S. Games Corporation - Western Technologies, John Hall", "VC1012", "M.A.D. (1983) (U.S. Games)", "AKA Missile Intercept, Mutually Assured Destruction", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3947eb7305b0c904256cdbc5c5956c0f", "Jone Yuan Telephonic Enterprise Co", "", "Lilly Adventure (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "396f7bc90ab4fa4975f8c74abe4e81f0", "Atari, Larry Kaplan - Sears", "CX2612 - 99804, 49-75103", "Street Racer (1977) (Atari)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "3974e2d1f614fbd3a092533ecae2e84d", "Alessandro Ciceri", "", "MagiCard+ (alex_79) WIP_20150118", "MagiCard hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39790a2e9030751d7db414e13f1b6960", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39a6a5a2e1f6297cceaa48bb03af02e9", "", "", "Pitfall 2 Plus (Hack)", "Hack of Pitfall 2", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39b94d41bd3b01c12b4054c1a8733783", "SOLID Corp. (D. Scott Williamson)", "CX2655-016", "Star Castle 2600 (SolidCorp) [016]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "39c78d682516d79130b379fa9deb8d1c", "Apollo - Games by Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39d36366ae7e6dfd53393fb9ebab02a0", "CCE", "C-811", "River Raid (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39da69ff9833f8c143f03b6e0e7a996b", "Charles Morgan", "", "Ventrra Invaders 2002 (Charles Morgan) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "39fe316952134b1277b6a81af8e05776", "Robby", "18", "River Raid (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a10562937a766cbbb77203d029b00e1", "Carrere Video - JWDA, Garry Kitchen, Paul Willson - Teldec - Prism", "USC1002", "Sneak 'n Peek (1983) (Carrere Video) (PAL)", "AKA Der Unsichtbare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a2e2d0c6892aa14544083dfb7762782", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3a35d7f1dc2a33565c8dca52baa86bc4", "", "", "Rubik's Cube Demo 2 (23-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a51a6860848e36e6d06ffe01b71fb13", "Retroactive", "", "Qb (2.07) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3a521b7e29123b2d38e34e3ff8dc255c", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a526e6a1f9fe918af0f2ce997dfea73", "CBS Electronics, Dan Kitchen, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1982) (CBS Electronics) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a53963f053b22599db6ac9686f7722f", "", "", "Word Zapper (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3a771876e4b61d42e3a3892ad885d889", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Defender II (1987) (Atari)", "AKA Stargate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3aad0ef62885736a5b8c6ccac0dbe00c", "Dynacom", "", "Atlantis (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ab5d138e26d88c8190e7cc629a89493", "", "", "Phased Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3ac6c50a8e62d4ce71595134cbd8035e", "Absolute Entertainment, Dan Kitchen", "AK-046-04", "Tomcat (1988) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ad3dc799211ccd424d7c6d454401436", "Probe 2000 - NAP", "", "Power Lords (1983) (Probe) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ad58b53a1e972396890bd86c735e78d", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur Version 36 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b040ed7d1ef8acb4efdeebebdaa2052", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b097a7ed5bd2a84dc3d3ed361e9c31c", "", "", "Interleaved ChronoColour Demo (PAL) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b10106836565e5db28c7823c0898fbb", "Xonox - Beck-Tech", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b2c32fcd331664d037952bcaa62df94", "Xonox", "6230, 6250", "Super Kung-Fu (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b5751a8d20f7de41eb069f76fecd5d7", "", "", "Eckhard Stolberg's Scrolling Text Demo 4 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b64a00ce147c3c29f7f8f8e531d08d8", "", "", "This Planet Sucks (16K) (Greg Troutman)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b69f8929373598e1752f43f8da61aa4", "Apollo - Games by Apollo - RCA Video Jeux", "AP-2006", "Infiltrate (1921) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3b6dba1a24bb2893bd3bd0593f92016b", "CBS Electronics / Thomas Jentzsch", "", "Omega Race JS (TJ)", "Hack of Omega Race (CBS Electronics)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b76242691730b2dd22ec0ceab351bc6", "M Network - INTV, Connie Goldman, Joe King, Patricia Lewis Du Long, Gerald Moore, Mike Sanders, Jossef Wagner", "MT4319", "Masters of the Universe (1983) (M Network)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3b80b8f52a0939e16b5059f93a3fc19a", "V007", "", "Virtual Pet (V007) (after Demo 2) (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b86a27132fb74d9b35d4783605a1bcb", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b8aacf5f5638492b926b5124de19f18", "Atari, Tod Frye - Sears", "CX2646 - 49-75185", "Pac-Man (1981) (Atari) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b91c347d8e6427edbe942a7a405290d", "Parker Brothers", "PB5350", "Sky Skipper (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b9480bb6fb1e358c9c0a64e86945aee", "", "", "Title Match Pro Wrestling (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3b966bf3c2ca34ac6ca1de4cf6383582", "", "", "Double-Height 6-Digit Score Display (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3bb9793c60c92911895cf44530846136", "Jone Yuan Telephonic Enterprise Co", "", "Dragster (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c21a89bc38d8cd0b010a2916bcff5c2", "", "", "Colony 7 - CX-22 Hack v0.4 (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, + { "3c3a2bb776dec245c7d6678b5a56ac10", "", "", "Unknown Title (bin00003) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c4223316c835ceaad619651e25df0f9", "", "", "Defender (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c4a6f613ca8ba27ce9e43c6c92a3128", "", "", "Qb (V0.04) (Non-Lax Version) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3c57748c8286cf9e821ecd064f21aaa9", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118", "Millipede (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c72ddaf41158fdd66e4f1cb90d4fd29", "Dismac", "", "Comando Suicida (Dismac)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c7a7b3a0a7e6319b2fa0f923ef6c9af", "Atari - Roklan, Joe Gaucher", "", "Racer (1982) (Atari) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c7a96978f52b2b15426cdd50f2c4048", "", "", "Overhead Adventure Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c82e808fe0e6a006dc0c4e714d36209", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3c853d864a1d5534ed0d4b325347f131", "Telesys, Don 'Donyo' Ruffcorn", "1002", "Cosmic Creeps (1982) (Telesys)", "AKA Space Maze, Spaze Maze", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3c8e57a246742fa5d59e517134c0b4e6", "Parker Brothers, Rex Bradford, Sam Kjellman", "PB5050", "Star Wars - The Empire Strikes Back (1982) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ca51b5c08f5a0ecfb17d0c1ec6d0942", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (09-28-81) (Atari) (Prototype)", "AKA Mystery Mansion, Graves' Manor, Nightmare Manor", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3caa902ac0ce4509308990645876426a", "Atari - GCC, Dave Payne", "CX2669, CX2669P", "Vanguard (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3cbdf71bb9fd261fbc433717f547d738", "CCE", "C-803", "Bobby Is Going Home (1983) (CCE) (PAL)", "AKA Bobby Vai Para Casa", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3cdd91e1c28d28e856c0063d602da166", "", "", "Stell-A-Sketch (03-11-1997) (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3d1e83afdb4265fa2fb84819c9cfd39c", "Coleco - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "2465", "Smurf - Rescue in Gargamel's Castle (1983) (Coleco)", "AKA Smurf, Smurf Action", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d2367b2b09c28f1659c082bb46a7334", "Imagic, Dennis Koble", "720103-2A, IA3203P, EIX-010-04I", "Atlantis (1982) (Imagic) (PAL)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d2652cbea462a886a41791dd7c8d073", "", "", "Ritorno dei frattelli di Mario (Mario Bros Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d48b8b586a09bdbf49f1a016bf4d29a", "Video Game Cartridge - Ariola", "TP-606", "Hole Hunter (Video Game Cartridge)", "AKA Topy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d6fc7a19be76d808aa233415cb583fc", "CCE", "C-833", "Target Practice (1983) (CCE)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d7749fb9c2f91a276dfe494495234c5", "Jone Yuan Telephonic Enterprise Co", "", "Checkers (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d7aad37c55692814211c8b590a0334c", "Atari, Dan Oliver", "", "Telepathy (1983) (Atari) (Prototype)", "Uses both left joystick and right Mindlink controllers (press Fire on respective controller to begin)", "Prototype", "", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "78", "", "", "", "", "", "", "", "" }, + { "3d8a2d6493123a53ade45e3e2c5cafa0", "Atari, Jim Huether - Sears", "CX2629 - 6-99843, 49-75118", "Sky Diver (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d934bb980e2e63e1ead3e7756928ccd", "Activision, Steve Cartwright - Ariola", "EAX-017, EAX-017-04I - 711 017-720", "MegaMania (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3d9c2fccf8b11630762ff00811c19277", "", "", "Challenge of.... Nexar, The (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3da7cc7049d73d34920bb73817bd05a9", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3dfb7c1803f937fadc652a3e95ff7dc6", "Dimax - Sinmax", "SM8001", "Space Robot (Dimax - Sinmax)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3e03086da53ecc29d855d8edf10962cb", "CBS Electronics - Roklan, Joe Gaucher, Alex Leavens", "4L1751, 4L1752, 4L1753, 4L2275", "Gorf (1982) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3e1682ddaec486d8b6b90b527aaa0fc4", "Thomas Jentzsch", "", "Robot City (V0.12) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e22c7eaf6459b67388602e4bebbb3a8", "CommaVid, John Bronstein - Ariola", "CM-003 - 712 003-720", "Cosmic Swarm (1982) (CommaVid) (PAL) (4K)", "AKA Angriff der Termiten", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e33ac10dcf2dff014bc1decf8a9aea4", "Spectravideo - Video Games Industries Corporation, Michael Schwartz - Ralston Purina", "", "Chase the Chuckwagon (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3e49da621193d2611a4ea152d5d5ca3a", "", "", "Atari Logo Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e4b1137433cc1e617b5508619e13063", "", "", "Asteroids (Genesis)", "Genesis controller (C is hyperspace)", "Hack of Asteroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3e5ca1afaa27c5da3c54c9942fec528b", "", "", "2600 Digital Clock (Demo 2) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e6dab92009d6034618cb6b7844c5216", "", "", "Ed Invaders (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e7d10d0a911afc4b492d06c99863e65", "VGS", "", "Super Tenis (VGS)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e88cca5b860d0bd8947479e74c44284", "Atari, Lou Harp", "CX26122", "Sinistar (01-23-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3e899eba0ca8cd2972da1ae5479b4f0d", "Coleco, Joseph Biel", "2457", "Venture (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3e90cf23106f2e08b2781e41299de556", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3eae062a9b722bda1255d474a87eca5c", "Atari, David Crane", "CX2605, CX2605P", "Outlaw (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3eb1e34a4f0eec36f12e7336badcecf2", "Jake Patterson", "", "Baubles (V0.001) (2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3eb21313ea5d5764c5ed9160a5a55a83", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ec12372ca3e870b11ca70edc7ec26a4", "CommaVid, John Bronstein", "CM-002", "Video Life (1981) (CommaVid) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3eccf9f363f5c5de0c8b174a535dc83b", "", "", "Plaque Attack (Unknown) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ef9573536730dcd6d9c20b6822dbdc4", "Atari, Larry Wagner, Bob Whitehead", "CX2645, CX2645P", "Video Chess (1979) (Atari) (PAL)", "AKA Computer Chess", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f01bd6d059396f495a4cde7de0ab180", "", "", "Qb (Special Edition) (NTSC) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "3f039981255691d3859d04ef813a1264", "Xonox, John Perkins", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) [a]", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f251c50aa7237e61a38ab42315ebed4", "Thomas Jentzsch", "", "Ikari Warriors (1990) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f3ad2765c874ca13c015ca6a44a40a1", "CCE", "C-862", "Crackpots (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f540a30fdee0b20aed7288e4a5ea528", "Atari - GCC", "CX2670", "Atari Video Cube (1983) (Atari)", "AKA Atari Cube, Video Cube", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f58f972276d1e4e0e09582521ed7a5b", "Telegames", "6082 A145", "Kung Fu Superkicks (1988) (Telegames)", "AKA Chuck Norris Superkicks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f5a43602f960ede330cd2f43a25139e", "Activision, Alan Miller", "AG-003", "Checkers (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f6938aa6ce66e6f42e582c1eb19b18c", "Jone Yuan Telephonic Enterprise Co", "", "Laser Blast (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f6dbf448f25e2bd06dea44248eb122d", "", "5687 A279", "Soccer (1988) (Telegames)", "AKA International Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f75a5da3e40d486b21dfc1c8517adc0", "Atari, Jim Huether", "CX26163P", "Sky Diver (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f9431cc8c5e2f220b2ac14bbc8231f4", "", "", "Colors Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f96eb711928a6fac667c04ecd41f59f", "Bit Corporation", "PGP218", "Rodeo Champ (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3f9cb1aba8ec20e2c243ae642f9942bf", "", "", "New Questions (1998) (John K. Harvey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3fd1f9d66a418c9f787fc5799174ddb7", "Aaron Curtis", "", "AStar (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3fd53bfeee39064c945a769f17815a7f", "CCE", "", "Sea Hawk (CCE)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3fe43915e5655cf69485364e9f464097", "CCE", "C-863", "Fisher Price (1983) (CCE)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "3ff5165378213dab531ffa4f1a41ae45", "Otto Versand", "311377", "Pygmy (1983) (Otto Versand) (PAL)", "AKA Lock 'n' Chase (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4026ad38ba5ce486e88383dc27d7a46f", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "402b1ca3c230a60fb279d4a2a10fa677", "", "", "3-D Tic-Tac-Toe (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "402d876ec4a73f9e3133f8f7f7992a1e", "Alex Herbert", "", "Man Goes Down (2006) (A. Herbert) (Prototype)", "Uses AtariVox controller", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "405f8591b6941cff56c9b392c2d5e4e5", "Telegames", "", "Star Strike (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4066309eb3fa3e7a725585b9814bc375", "", "", "Multi Ball Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4066d7d88ec4a2c656127a67fa52dcf1", "", "", "Overhead Adventure Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "407a0c6cc0ff777f67b669440d68a242", "Erik Eid", "", "Euchre (Alpha) (PAL) (31-08-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4093382187f8387e6d011883e8ea519b", "", "", "Go Go Home (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40aa851e8d0f1c555176a5e209a5fabb", "", "", "Euchre (More for less) (NTSC) (22-08-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40b1832177c63ebf81e6c5b61aaffd3a", "Atari, Peter C. Niday", "", "Rubik's Cube 3-D (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40b59249e05135bca33861e383735e9e", "Atari", "CX26163P", "Skiing (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40d8ed6a5106245aa79f05642a961485", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 06002, 06004, 99002", "Ghost Manor (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40d9f5709877ecf3dd1184f9791dd35e", "Dactari - Milmar", "", "Skiing (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40e12c008037a323a1290c8fa4d2fe7f", "", "", "Skeleton (NTSC) (06-09-2002) (Eric Ball)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "40eb4e263581b3dfec6dd8920b68e00f", "Sears Tele-Games, Marilyn Churchill, Matthew L. Hubbard", "CX2647 - 49-75142", "Seawolf 3 (03-23-1981) (Sears) (Prototype) (PAL)", "Submarine Commander Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "413c925c5fdcea62842a63a4c671a5f2", "Activision, Larry Kaplan", "AX-006", "Bridge (1980) (Activision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4153dd2beed648e9dc082140ebe8e836", "Thomas Jentzsch", "", "Coke Zero (v1.0) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "415c11fcac66bbd2ace2096687774b5a", "", "", "Fu Kung! (V0.00) (07-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4181087389a79c7f59611fb51c263137", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (06-24-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "41810dd94bd0de1110bedc5092bef5b0", "Funvision - Fund. International Co.", "", "Dragon Treasure (Funvision)", "AKA Dragonfire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "41818738ab1745e879024a17784d71f5", "CCE", "C-832", "Atlantis (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4189adfc1b30c121248876e3a1a3ac7e", "Eric Ball", "", "Skeleton (Complete) (06-09-2002) (Eric Ball)", "", "New Release", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4191b671bcd8237fc8e297b4947f2990", "Exus Corporation", "", "Video Jogger (1983) (Exus)", "AKA Foot Craz", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "41b554c6970b18670acc7b6baef8ed2e", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "41c4e3d45a06df9d21b7aae6ae7e9912", "CCE", "C-826", "Grand Prix (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "41f252a66c6301f1e8ab3612c19bc5d4", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (1983) (Atari)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4209e9dcdf05614e290167a1c033cfd2", "CommaVid, John Bronstein", "CM-002", "Video Life (1984) (CommaVid) [higher sounds]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "42249ec8043a9a0203dde0b5bb46d8c4", "CCE", "", "Resgate Espacial (CCE)", "AKA Moonsweeper", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4233eb824c2b4811abef9b6d00355ae9", "Retroactive", "", "Qb (V0.10) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4251b4557ea6953e88afb22a3a868724", "Thomas Jentzsch", "", "Robot City (V1.1) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "425ee444a41d218598893d6b6e03431a", "Thomas Jentzsch", "", "Invaders Demo (2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4279485e922b34f127a88904b31ce9fa", "", "", "Enduro (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "428b2d36f5d716765460701f7016ac91", "Andrew Wallace", "", "Brooni (2001) (Andrew Wallace) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42ae81ae8ac51e5c238639f9f77d91ae", "", "", "Multi-Sprite Demo 2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42b2c3b4545f1499a083cfbc4a3b7640", "U.S. Games Corporation - JWDA, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV", "VC2003", "Eggomania (1982) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "42b3ab3cf661929bdc77b621a8c37574", "Robby", "", "Volleyball (Robby)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42b5e3a35b032f033809afb0ea28802d", "Atari, Mimi Nyden, Scott Smith, Robert Vieira", "CX26127", "Gremlins (03-12-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42cdd6a9e42a3639e190722b8ea3fc51", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42dcc02777b0bcfacd85aeb61d33558a", "", "", "Human Cannonball (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "42e0ec5ab8f5deba53e4169ff2a5efbe", "", "", "Atari Logo Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4311a4115fb7bc68477c96cf44cebacf", "", "", "Challenge (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4326edb70ff20d0ee5ba58fa5cb09d60", "Atari - GCC, Kevin Osborn", "CX2689", "Kangaroo (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "435fd469f088468c4d66be6b5204d887", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "438968a26b7cfe14a499f5bbbbf844db", "", "", "Raft Rider (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "43adf60ebdd6b5a0fae21594ecf17154", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "43c6cfffeddab6b3787357fed9d44529", "20th Century Fox Video Games, Frank Cohen, Douglas 'Dallas North' Neubauer", "11111", "M.A.S.H (1983) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "43f33c6dfdeaf5138ce6e6968ad7c5ce", "Jeffry Johnston", "", "Radial Pong - Version 11 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "43f8459d39fb4eddf9186d62722ff795", "", "", "Skeleton+ (17-04-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "442602713cb45b9321ee93c6ea28a5d0", "", "", "Demon Attack (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4427f06085bb4c22ff047027f7acecc2", "Parker Brothers, Rex Bradford", "PB5000", "Star Wars - Jedi Arena (1983) (Parker Bros) (Prototype)", "Uses the Paddle Controllers (swapped)", "Prototype", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 50", "", "", "", "", "", "", "", "" }, + { "442b7863683e5f084716fda050474feb", "Eckhard Stolberg", "", "Frame Timed Sound Effects-EM (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4431428a7500c96fc0e2798a5dbd36d6", "", "", "Kangaroo (Genesis)", "Genesis controller (B is punch, C is jump)", "Hack of Kangaroo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4474b3ad3bf6aabe719a2d7f1d1fb4cc", "Activision - Imagineering, Dan Kitchen, Garry Kitchen", "EAX-039-04B, EAX-039-04I", "Kung-Fu Master (1987) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4476c39736090dabac09f6caf835fc49", "", "", "Text Screen (25-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "448c2a175afc8df174d6ff4cce12c794", "Activision, David Crane", "AB-035-04", "Pitfall II (1983) (Activision) [a2]", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "44e9c4a047c348dbeb7ace60f45484b4", "", "", "Moon Patrol Arcade (Genesis)", "Genesis controller (C is jump)", "Hack of Moon Patrol", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "44f71e70b89dcc7cf39dfd622cfb9a27", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45027dde2be5bdd0cab522b80632717d", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00250", "Summer Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45040679d72b101189c298a864a5b5ba", "20th Century Fox Video Games - Sirius Software, David Lubar", "11022", "SpaceMaster X-7 (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4543b7691914dfd69c3755a5287a95e1", "CommaVid, Irwin Gaines", "CM-005", "Mines of Minos (1982) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "456453a54ca65191781aef316343ae00", "", "", "Full Screen Bitmap (3-D Green) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4565c1a7abce773e53c75b35414adefd", "Arcadia Corporation", "", "Supercharger BIOS (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "457b03cd48ff6d895795ef043c6b0f1e", "AtariAge, Chris Spry", "CX26201", "Zippy the Porcupine (2014) (Sprybug)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "457e7d4fcd56ebc47f5925dbea3ee427", "Carrere Video - JWDA, Garry Kitchen - Teldec - Prism", "USC1001", "Space Jockey (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "457f4ad2cda5f4803f122508bfbde3f5", "", "", "Canyon Bomber (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "458883f1d952cd772cf0057abca57497", "", "", "Fishing Derby (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45a095645696a217e416e4bd2baea723", "Digivision", "", "Snoopy (Digivision)", "AKA Snoopy and the Red Baron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45a4f55bb9a5083d470ad479afd8bca2", "CommaVid, Joseph Biel", "", "Frog Demo (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45beef9da1a7e45f37f3f445f769a0b3", "Atari, Suki Lee", "CX2658", "Math Gran Prix (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45c4413dd703b9cfea49a13709d560eb", "Jone Yuan Telephonic Enterprise Co", "", "Challenge of.... Nexar, The (Jone Yuan) (Hack)", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "45cb0f41774b78def53331e4c3bf3362", "Carrere Video - JWDA, Roger Booth, Sylvia Day, Todd Marshall, Robin McDaniel, Wes Trager, Henry Will IV - Teldec - Prism", "USC1007", "Octopus (1983) (Carrere Video) (PAL)", "AKA Name This Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4605a00f5b44a9cbd5803a7a55de150e", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (07-03-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "461029ab23800833e9645be3e472d470", "", "", "Combat TC (v0.1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "46258bd92b1f66f4cb47864d7654f542", "Zellers", "", "Turmoil (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "463dd4770506e6c0ef993a40c52c47be", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (Preview) (1982) (Arcadia)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "463e66ad98806a49106cffa49c08e2ed", "", "", "Interlace Game Demo (01-09-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "467340a18158649aa5e02a4372dcfccd", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4689081b7363721858756fe781cc7713", "", "", "Oystron (V2.6) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "468f2dec984f3d4114ea84f05edf82b6", "Tigervision - Teldec", "7-011 - 3.60015 VG", "Miner 2049er Volume II (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4690fdb70c86604bb35da26696818667", "", "", "Euchre (Release Candidate) (NTSC) (28-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "469473ff6fed8cc8d65f3c334f963aab", "Atari, Bruce Poehlman, Gary Stark", "", "Dune (07-10-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "46c021a3e9e2fd00919ca3dd1a6b76d8", "Atari, Jim Huether - Sears", "CX2629 - 6-99843, 49-75118", "Sky Diver (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "46c43fdcbce8fde3a91ebeafc05b7cbd", "", "", "Invaders Demo (PAL) (2001) (Eckhard Stolberg)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "46dc526773808c8b9bb2111f24e5704c", "Omegamatrix", "", "SpaceMaster X-7 (Atari Mouse) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "46e9428848c9ea71a4d8f91ff81ac9cc", "Telegames", "", "Astroblast (1988) (Telegames) (PAL)", "Can also use left joystick", "", "", "", "", "", "", "", "", "PADDLES", "", "YES", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "4702d8d9b48a332724af198aeac9e469", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "470878b9917ea0348d64b5750af149aa", "Atari, Suki Lee - Sears", "CX2658 - 49-75128", "Math Gran Prix (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "471f7bdc933e8db0e44aa3dde2dd92af", "Omegamatrix", "", "Millipede (Atari Mouse) v6.5 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47464694e9cce07fdbfd096605bf39d4", "Activision, Dan Kitchen", "EAK-050-04", "Double Dragon (1989) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47585c047802dd9af888b998fb921f32", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) v4 (PAL60) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4767356fa0ed3ebe21437b4473d4ee28", "Atari, Dan Hitchens, Mimi Nyden", "CX2685", "Gravitar (04-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47711c44723da5d67047990157dcb5dd", "CCE", "", "Ice Hockey (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47911752bf113a2496dbb66c70c9e70c", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (1984) (Atari) (PAL)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4799a40b6e889370b7ee55c17ba65141", "Konami", "RC 100-X 02", "Pooyan (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47aad247cce2534fd70c412cb483c7e0", "Rainbow Vision - Suntek", "SS-010", "Mafia (1983) (Rainbow Vision) (PAL)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47abfb993ff14f502f88cf988092e055", "Zellers", "", "Inca Gold (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "47aef18509051bab493589cb2619170b", "", "", "Stell-A-Sketch (Bob Colbert) (PD)", "Uses Driving, Joystick, or Amiga/Atari ST Mouse Controllers", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "47b82d47e491ac7fdb5053a88fccc832", "Atari Freak 1, Franklin Cruz", "", "Asteroid 2 (Atari Freak 1) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "47cd61f83457a0890de381e478f5cf5f", "Imagic, Wilfredo Aguilar, Michael Becker, Rob Fulop", "720111-2A, 13205", "Fathom (1983) (Imagic) (PAL)", "AKA Scuba", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "481d20ec22e7a63e818d5ef9679d548b", "Atari", "CX26163P", "Freeway Rabbit (32 in 1) (1988) (Atari) (PAL)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "481f9a742052801cc5f3defb41cb638e", "Jeffry Johnston", "", "Radial Pong - Version 4 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "48287a9323a0ae6ab15e671ac2a87598", "Zellers", "", "Laser Volley (Zellers)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4834b7b28ea862227ac7e40053fb52a5", "Nukey Shay", "", "Montezuma's Revenge (Genesis) (F6_Conversion)", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "48411c9ef7e2cef1d6b2bee0e6055c27", "Telesys, Don Ruffcorn, Jack Woodman", "1003", "Fast Food (1982) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "484b0076816a104875e00467d431c2d2", "Atari", "CX26150", "Q-bert (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4857f8bb88bb63c640d3ea5aac7f5d6d", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (08-12-81) (Atari) (Prototype)", "AKA Mystery Mansion, Graves' Manor, Nightmare Manor", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4868a81e1b6031ed66ecd60547e6ec85", "Eric Mooney", "", "Invaders by Erik Mooney (V2.1) (1-3-98) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "487193a7b7fe57a1bbc2f431f628bd5f", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4884b1297500bd1243659e43c7e7579e", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (10-24-1991) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4892b85c248131d6a42c66a4163a40d0", "Canal 3 - Intellivision", "", "Tac-Scan (Canal 3)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "48bcf2c5a8c80f18b24c55db96845472", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "48e5c4ae4f2d3b62b35a87bca18dc9f5", "Quelle", "476.774 5", "Bobby geht nach Hause (1983) (Quelle) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "48f18d69799a5f5451a5f0d17876acef", "ZiMAG - Emag - Vidco", "GN-070", "Mysterious Thief, A (1983) (ZiMAG) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4901c05068512828367fde3fb22199fe", "Imagic, Rob Fulop", "720101-2B, IA3200P, EIX-006-04I", "Demon Attack (1982) (Imagic) (PAL)", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4904a2550759b9b4570e886374f9d092", "Parker Brothers, Charlie Heath", "931506", "Reactor (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "490e3cc59d82f85fae817cdf767ea7a0", "", "", "Berzerk (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "490eed07d4691b27f473953fbea6541a", "Activision, Steve Cartwright, David Crane", "AB-035-04", "Pitfall II (1983) (Activision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "49366f41aa7a54baf263426e99ce4312", "", "", "POP-MDM-Test (PAL) (63 games)", "", "", "", "", "MDM", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "493daaf9fb1ba450eba6b8ed53ffb37d", "", "", "3-D Corridor Demo (27-03-2003) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "493de059b32f84ab29cde6213964aeee", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Stargate (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "493e90602a4434b117c91c95e73828d1", "Telegames", "", "Lock 'n' Chase (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4947c9de2e28b2f5f3b0c40ce7e56d93", "", "", "3-D Corridor Demo 2 (29-03-2003) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "494cda91cc640551b4898c82be058dd9", "Andreas Dietrich", "", "Donkey Kong VCS (2017) (1.0) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "49571b26f46620a85f93448359324c28", "", "", "Save Our Ship (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "497c811026367c08fd838c9c59e5041d", "Omegamatrix", "", "SpaceMaster X-7 (Atari Trak-Ball) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "497f3d2970c43e5224be99f75e97cbbb", "CommaVid, John Bronstein", "CM-002", "Video Life (1984) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4981cefe5493ea512284e7f9f27d1e54", "Home Vision - Gem International Corp. - VDI", "VCS83136", "Cosmic War (1983) (Home Vision) (PAL)", "AKA Space Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4999b45be0ab5a85bac1b7c0e551542b", "CCE", "", "Double Dragon (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "499b612f6544ae71d4915aa63e403e10", "Atari, Carol Shaw", "CX26163P", "Checkers (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "49f2cef5269fd06218be9f9474c74f8d", "Rentacom", "", "Time Pilot (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a196713a21ef07a3f74cf51784c6b12", "Jone Yuan Telephonic Enterprise Co", "", "Frogs and Flies (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a2fe6f0f6317f006fd6d4b34515448b", "", "", "Warring Worms (Midwest Classic Edition) (08-06-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a45c6d75b1ba131f94a9c13194d8e46", "", "", "How to Draw a Playfield II (Joystick Hack) (1997) (Eric Bacher) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a5fddf89801336637ac8e57a7c9a881", "Amiga", "1125", "Power Play Arcade Video Game Album IV (1984) (Amiga) (Prototype)", "Atlantis, Cosmic Ark, Dragonfire", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a6be79310f86f0bebc7dfcba4d74161", "", "", "Demolition Herby (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4a7eee19c2dfb6aeb4d9d0a01d37e127", "Hozer Video Games", "", "Crazy Valet (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a8c743396b8ad69d97e6fd3dd3e3132", "Arcadia Corporation", "", "Supercharger BIOS (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4a9009620038f7f30aaeb2a00ae58fde", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (3 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ab2ebd95a8f861ea451abebdad914a5", "Nukey Shay, Thomas Jentzsch", "PAL conversion (F6)", "Montezuma's Revenge (PAL) (Genesis)", "Genesis controller (B jumps left, C jumps right)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ab4af3adcdae8cdacc3d06084fc8d6a", "Nick Bensema", "", "Sucky Zepplin (Nick Bensema) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4abb4c87a4c5f5d0c14ead2bb36251be", "Atari - Imagineering, Alex DeMeo", "CX26135, CX26135P", "RealSports Boxing (1987) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ac9f40ddfcf194bd8732a75b3f2f214", "Atari - CCW, Stephan R. Keith, Laura Scholl, Preston Stuart", "CX26106", "Grover's Music Maker (12-29-1982) (Atari) (Prototype)", "Uses Keypad Controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ae8c76cd6f24a2e181ae874d4d2aa3d", "", "", "Flash Gordon (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4af4103759d603c82b1c9c5acd2d8faf", "Imagic, Bob Smith", "720114-2A, 13207, EIZ-001-04I", "Moonsweeper (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4afa7f377eae1cafb4265c68f73f2718", "Ed Fries", "", "Halo 2600 (2010) (Ed Fries)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4afe528a082f0d008e7319ebd481248d", "", "", "Multi-Color Demo 1 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b143d7dcf6c96796c37090cba045f4f", "Atari, Jim Huether - Sears", "CX2644 - 6-99824", "Flag Capture (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b205ef73a5779acc5759bde3f6d33ed", "", "", "Berzerk (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b27f5397c442d25f0c418ccdacf1926", "Atari, Warren Robinett", "CX2613, 49-75154", "Adventure (1980) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b379b885e2694f992c6cc932f18327f", "Omegamatrix", "", "SpaceMaster X-7 (Atari Mouse) (PAL60) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b71197153d651480830638cb6a03249", "Atari, Larry Kaplan", "CX26163P", "Bowling (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b753a97aee91e4b3e4e02f5e9758c72", "Glenn Saunders, Roger Williams", "", "Asymmetric Reflected Playfield (Glenn Saunders)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b94fd272785d7ec6c95fb7279d0f522", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (12-03-1982) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4b9581c3100a1ef05eac1535d25385aa", "", "", "IQ 180 (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4baada22435320d185c95b7dd2bcdb24", "Atari, Jerome Domurat, Dave Staugas", "CX2682", "Krull (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4bcc7f6ba501a26ee785b7efbfb0fdc8", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4bdae9246d6ee258c26665512c1c8de3", "Atari", "CX26163P", "Human Cannonball (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4bdf54a454470ba015a217a8f5e61320", "Omegamatrix", "", "Millipede (Amiga Mouse) v6.5 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, + { "4c030667d07d1438f0e5c458a90978d8", "Retroactive", "", "Qb (V2.03) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4c0fb2544ae0f8b5f7ae8bce7bd7f134", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (Preview) (1983) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c205f166157154df2f1ef60d87e552f", "", "", "Single-Scanline Positioning Demo 2 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c39a2c97917d3d71739b3e21f60bba5", "", "", "Whale (Sub Scan Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c462b2b6fb0a19a1437eb2c3dc20783", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c4ce802cbfd160f7b3ec0f13f2a29df", "", "", "Beta Demo (V1.1) (26-09-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c606235f4ec5d2a4b89139093a69437", "Andrew Davies", "", "Andrew Davies early notBoulderDash demo (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4c6afb8a44adf8e28f49164c84144bfe", "CCE", "C-806", "Mission 3,000 A.D. (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c8832ed387bbafc055320c05205bc08", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c8970f6c294a0a54c9c45e5e8445f93", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4c9307de724c36fd487af6c99ca078f2", "Imagic, Brad Stewart", "720106-1A, IA3409", "Sky Patrol (1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ca0959f846d2beada18ecf29efe137e", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666, CX2666P", "RealSports Volleyball (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ca73eb959299471788f0b685c3ba0b5", "Activision, Steve Cartwright", "AX-031", "Frostbite (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4ca90ba45eced6f5ad560ea8938641b2", "", "", "Hangman Man Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4cabc895ea546022c2ecaa5129036634", "Funvision - Fund. International Co.", "", "Ocean City (Funvision)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4cd796b5911ed3f1062e805a3df33d98", "Tigervision - Software Electronics Corporation - Teldec", "7-006", "Springer (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d06f72cc3d8934579c11ff8f375c260", "Bit Corporation", "R320", "Bowling (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d0a28443f7df5f883cf669894164cfa", "", "", "Beast Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d2cef8f19cafeec72d142e34a1bbc03", "HES", "771-422", "2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d38e1105c3a5f0b3119a805f261fcb5", "Bit Corporation", "PGP212", "Phantom UFO (4 Game in One Light Green) (1983) (BitCorp) (PAL)", "AKA Spider Fighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d502d6fb5b992ee0591569144128f99", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (11-21-1989) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d5f6db55f7f44fd0253258e810bde21", "Fabrizio Zavagli", "", "Betterblast (Fabrizio Zavagli) (Hack)", "Hack of Astroblast", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d7517ae69f95cfbc053be01312b7dba", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d77f291dca1518d7d8e47838695f54b", "Data Age", "DA1004", "Airlock (1982) (Data Age)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4d8396deeabb40b5e8578276eb5a8b6d", "Otto Versand", "781698", "Volleyball (1983) (Otto Versand) (PAL)", "AKA RealSports Volleyball (Double-Game Package)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4dbd7e8b30e715efc8d71d215aec7fe7", "Bit Corporation", "R320", "Air Raiders (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4dbf47c7f5ac767a3b07843a530d29a5", "Ric Pryor", "", "Breaking News (2002) (Ric Pryor) (Hack)", "Hack of Bump 'n' Jump", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4dcc7e7c2ec0738e26c817b9383091af", "", "", "Unknown Title (bin00026 (200110)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4dd6c7ab9ef77f2b4950d8fc7cd42ee1", "Retroactive", "", "Qb (V2.04) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4df6124093ccb4f0b6c26a719f4b7706", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) [a]", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, + { "4df9d7352a56a458abb7961bf10aba4e", "", "", "Racing Car (Unknown)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e01d9072c500331e65bb87c24020d3f", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (06-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e02880beeb8dbd4da724a3f33f0971f", "Imagic, Michael Greene", "EIZ-002-04I", "Wing War (1983) (Imagic) (PAL)", "AKA Flap!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e15ddfd48bca4f0bf999240c47b49f5", "Avalon Hill, Jean Baer, Jim Jacob", "5001002", "Death Trap (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4e2c884d04b57b43f23a5a2f4e9d9750", "", "", "Baby Center Animation (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4e37992a37ea36489283f7eb90913bbc", "Kris", "", "Hangman Ghost Halloween (Kris) (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e4895c3381aa4220f8c2795d6338237", "", "", "Backwards Cannonball v1 (Hack)", "Hack of Human Cannonball", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e66c8e7c670532569c70d205f615dad", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e86866d9cde738d1630e2e35d7288ce", "Supergame", "", "River Raid III (Supergame)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4e99ebd65a967cabf350db54405d577c", "Coleco", "2663", "Time Pilot (1983) (Coleco) [b1]", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4eb4fd544805babafc375dcdb8c2a597", "Inspirational Video Concepts, Steve Shustack", "321430", "Red Sea Crossing (1983) (Inspirational Video Concepts)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4edb251f5f287c22efc64b3a2d095504", "Atari", "", "Atari VCS Point-of-Purchase ROM (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f0071946e80ca68edfdccbac86dcce0", "", "", "Virtual Pet Demo 1 (CRACKERS) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f2d47792a06da224ba996c489a87939", "HES - Activision", "223", "Super Action Pak - Pitfall, Barnstorming, Grand Prix, Laser Blast (1988) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f32b24869d8c1310fecf039c6424db6", "U.S. Games Corporation - JWDA, Todd Marshall", "", "3-D Zapper (12-15-82) (U.S. Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4f618c2429138e0280969193ed6c107e", "Activision, Alan Miller", "AZ-028, AG-028-04", "Robot Tank (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f634893d54e9cabe106e0ec0b7bdcdf", "Retroactive", "", "Qb (2.14) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4f64d6d0694d9b7a1ed7b0cb0b83e759", "20th Century Fox Video Games, John Russell", "11016", "Revenge of the Beefsteak Tomatoes (1983) (20th Century Fox)", "AKA Revenge of the Cherry Tomatoes", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f6702c3ba6e0ee2e2868d054b00c064", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen - Ariola", "EAZ-033 - 711 033-725", "Space Shuttle (1983) (Activision) (PAL)", "A Journey Into Space, Eine Reise ins All", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f781f0476493c50dc578336f1132a67", "", "", "Indy 500 (Unknown) (PAL) (4K)", "Uses Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "4f7b07ec2bef5ccffe06403a142f80db", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4f82d8d78099dd71e8e169646e799d05", "", "", "Miniature Golf (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4f89b897444e7c3b36aed469b8836839", "Atari", "CX26190", "BMX Air Master (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4fae08027365d31c558e400b687adf21", "", "", "Qb (V2.17) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "4faeb04b1b7fb0fa25db05753182a898", "", "", "2600 Digital Clock (V x.xx) (PD) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4fbe0f10a6327a76f83f83958c3cbeff", "CCE", "C-816", "Keystone Kappers (1983) (CCE)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "4fc1b85b8074b4b9436d097900e34f29", "John K. Harvey", "", "John K. Harvey's Equalizer (John K. Harvey)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "50200f697aeef38a3ce31c4f49739551", "Mystique - American Multiple Industries, Joel H. Martin", "", "Custer's Revenge (1982) (Mystique) (PAL60)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "502044b1ac111b394e6fbb0d821fca41", "", "", "Hangman Invader 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "502168660bfd9c1d2649d415dc89c69d", "Activision, Bob Whitehead - Ariola", "EAG-019, EAG-019-04I - 711 019-715", "Sky Jinks (1982) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "504688d49a41bf03d8a955512609f3f2", "Thomas Jentzsch", "", "SWOOPS! (v0.94) (TJ)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "50568c80ac61cab789d9923c9b05b68e", "Ebivision", "", "Merlin's Walls - Standard Edition (1999) (Ebivision)", "Image rotated 90 degrees CW", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5069fecbe4706371f17737b0357cfa68", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Shark Attack (1982) (Apollo) (PAL)", "AKA Lochjaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5079bfbc7b8f5770f84215ed2e3bdd1b", "Omegamatrix (2012)", "", "Genesis Button Tester", "", "Homebrew", "", "", "", "", "", "", "", "GENESIS", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "50a410a5ded0fc9aa6576be45a04f215", "Activision, Bob Whitehead - Ariola", "EAG-019, EAG-019-04I - 711 019-715", "Sky Jinks (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "50c7edc9f9dc0369abcdab3b4efeb5e9", "U.S. Games Corporation - JWDA, Todd Marshall", "", "3-D Zapper (U.S. Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "50ef88f9a5e0e1e6b86e175362a27fdb", "", "", "Multi-Sprite Game V2.4 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "512e874a240731d7378586a05f28aec6", "Tigervision, Rorke Weigandt - Teldec", "7-005", "Marauder (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5131ab3797fe8c127e3e135b18b4d2c8", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "514f911ecff2be5eeff2f39c49a9725c", "Parker Brothers", "931510", "Sky Skipper (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "515046e3061b7b18aa3a551c3ae12673", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "516ffd008057a1d78d007c851e6eff37", "Parker Brothers, Dawn Stockbridge", "PB5910", "Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "517592e6e0c71731019c0cebc2ce044f", "Parker Brothers - JWDA, Todd Marshall", "PB5550", "Q-bert's Qubes (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "517923e655755086a3b72c0b17b430e6", "Tron", "", "Super Tennis (Tron)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5188fee071d3c5ef0d66fb45c123e4a5", "Gameworld", "133-001", "Encounter at L-5 (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, + { "519f007c0e14fb90208dbb5199dfb604", "Amiga - Video Soft", "", "Depth Charge (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "51c1ddc9d6d597f71fb7efb56012abec", "Bit Corporation", "R320", "Lock 'n' Chase (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "51de328e79d919d7234cf19c1cd77fbc", "Atari, Mark R. Hahn", "CX2678", "Dukes of Hazzard (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "51e390424f20e468d2b480030ce95d7b", "Video Game Program", "", "Fire Bird (Video Game Program) (PAL)", "AKA Phoenix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "51f15b39d9f502c2361b6ba6a73464d4", "", "", "Amanda Invaders (PD) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "51f211c8fc879391fee26edfa7d3f11c", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "521f4dd1eb84a09b2b19959a41839aad", "Bit Corporation", "PG206", "Bobby Is Going Home (1983) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "522b27a8afeb951b5a5a667f8d1a46a1", "Omegamatrix", "", "Millipede (Amiga Mouse) v6.5 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "522c9cf684ecd72db2f85053e6f6f720", "Rainbow Vision - Suntek", "SS-008", "Year 1999, The (1983) (Rainbow Vision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52385334ac9e9b713e13ffa4cc5cb940", "CCE", "C-804", "Open, Sesame! (1983) (CCE)", "AKA Abre-te, Sesamo!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "523f5cbb992f121e2d100f0f9965e33f", "Joe Grand", "", "SCSIcide (1.30) (CGE 2001 Release) (Joe Grand)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "524693b337f7ecc9e8b9126e04a232af", "", "", "Euchre (19-08-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5256f68d1491986aae5cfdff539bfeb5", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-26-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "525ea747d746f3e80e3027720e1fa7ac", "Activision, Garry Kitchen - Ariola", "EAZ-032 - 771 032-712", "Pressure Cooker (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "525f2dfc8b21b0186cff2568e0509bfc", "Activision, David Crane", "AG-930-04, AZ-030", "Decathlon (1983) (Activision) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52615ae358a68de6e76467e95eb404c7", "", "", "DJdsl-wopd (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "528400fad9a77fd5ad7fc5fdc2b7d69d", "Starpath Corporation, Stephen H. Landrum, Jon Leupp", "11 AR-4201", "Sword of Saros (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52a0003efb3b1c49fcde4dbc2c685d8f", "Atari, Alan Miller - Sears", "CX2641 - 99807, 49-75105", "Surround (1977) (Atari) (4K) [a]", "", "", "", "", "2K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52b448757081fd9fabf859f4e2f91f6b", "", "", "Worm War I (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52bae1726d2d7a531c9ca81e25377fc3", "", "", "Space Instigators (V1.8 Fixed) (20-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "52e1954dc01454c03a336b30c390fb8d", "Retroactive", "", "Qb (2.14) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "52e9db3fe8b5d336843acac234aaea79", "", "", "Fu Kung! (V0.11) (28-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5305f69fbf772fac4760cdcf87f1ab1f", "Jone Yuan Telephonic Enterprise Co", "", "Ski Run (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5324cf5b6dc17af4c64bf8696c39c2c1", "Imagic, Dennis Koble", "IA3203, IX-010-04", "Atlantis (1982) (Imagic) (8K)", "AKA Lost City of Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "533661e9bccd8a9f80ce3765f282c92f", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) (Y Inverted) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5336f86f6b982cc925532f2e80aa1e17", "Parker Brothers - JWDA, Todd Marshall, Robin McDaniel, Ray Miller", "PB5060", "Star Wars - Death Star Battle (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "534e23210dd1993c828d944c6ac4d9fb", "M Network, Stephen Tatsumi, Jane Terjung - Kool Aid", "MT4648", "Kool-Aid Man (1983) (M Network)", "AKA Kool Aid Pitcher Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5355f80cacf0e63a49cbf4ade4e27034", "Christian Samuel", "", "Cute Dead Things House (Christian Samuel) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5360693f1eb90856176bd1c0a7b17432", "", "", "Oystron (V2.85) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "536bf56baa70acb17113884ac41f2820", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (PAL) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "537ed1e0d80e6c9f752b33ea7acbe079", "", "", "A-VCS-tec Challenge (beta 5) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5385cf2a04de1d36ab55c73174b84db0", "Paul Slocum", "", "Combat Rock (PD) (Hack)", "Hack of Combat", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "539d26b6e9df0da8e7465f0f5ad863b7", "Atari, Carol Shaw - Sears", "CX2636 - 49-75156", "Video Checkers (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "539f3c42c4e15f450ed93cb96ce93af5", "Dion Olsthoorn", "v1.3", "Amoeba Jump (2018) (Dionoid)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "53b66f11f67c3b53b2995e0e02017bd7", "CCE", "C-1005", "Super Tennis (1983) (CCE)", "AKA RealSports Tennis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "53bd1c7c972ae634c912331a9276c6e3", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "53d181cde2e0219b5754caad246fcb66", "", "", "Missile Demo (1998) (Ruffin Bailey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "53e03df47e76329b701641f8bdc206f5", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "53f147b9746fdc997c62f3dd67888ee5", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "540075f657d4b244a1f74da1b9e4bf92", "Bit Corporation", "PGP230", "Festival (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5409d20c1aea0b89c56993aec5dc5740", "", "", "Carnival Shooter (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "541cac55ebcf7891d9d51c415922303f", "SpiceWare - Darrell Spice Jr.", "SW-05", "Stay Frosty 2", "AtariAge Holiday Greetings 2014", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5428cdfada281c569c74c7308c7f2c26", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "542c6dd5f7280179b51917a4cba4faff", "ZiMAG - Emag - Vidco", "GN-080", "Spinning Fireball (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5438e84b90e50a5362f01cc843b358d4", "Arcadia Corporation, Scott Nelson", "3 AR-4300", "Fireball (1982) (Arcadia) (Prototype)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "543b4b8ff1d616fa250c648be428a75c", "Warren Robinett", "", "Adventure (1978) (Warren Robinett) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "545048ccb045f9efc6cf2b125cd0dfa8", "Arcadia Corporation, Stephen Harland Landrum, Jon Leupp", "AR-4201", "Sword of Saros (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "54785fa29e28aae6038929ba29d33d38", "", "", "Poker Squares (V0.19) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "54836a8f23913e9a77c7f2665baf36ac", "Bit Corporation", "PG204", "Open, Sesame! (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5494b9ee403d9757f0fd1f749e80214a", "Larry Petit", "", "Xenophobe Arcade (2003) (Larry Petit) (Hack)", "Hack of Xenophobe", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "54a1c1255ed45eb8f71414dadb1cf669", "Spectravideo", "SA-212", "Mangia' (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "54bafc299423f5a50b8bc3a797914706", "SOLID Corp. (D. Scott Williamson)", "CX2655*", "Star Castle 2600 (SolidCorp) (PAL)", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "54da3b0b3f43f5b37911c135b9432b49", "", "", "Halloween III Revision (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "54f7efa6428f14b9f610ad0ca757e26c", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Shark Attack (1982) (Apollo)", "AKA Lochjaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "551a64a945d7d6ece81e9c1047acedbc", "Matthias Jaap", "", "Coffee Cup Soccer (Matthias Jaap) (Hack)", "Hack of Pele's Soccer", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5524718a19107a04ec3265c93136a7b5", "Thomas Jentzsch", "", "RealSports Basketball (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "553dbf9358cfd2195e2fa0e08b01fb6a", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (07-05-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "554fd5775ca6d544818c96825032cf0d", "Atari - Roklan, Bob Curtiss", "", "Firefox (06-01-83) (Atari) (Prototype)", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "557e893616648c37a27aab5a47acbf10", "Atari - Axlon, Tod Frye - Heuristica, Augustin Ortiz", "CX26169", "Shooting Arcade (01-16-1990) (Atari) (Prototype) (PAL)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "559317712f989f097ea464517f1a8318", "Panda", "100", "Space Canyon (1983) (Panda)", "AKA Space Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "55949cb7884f9db0f8dfcf8707c7e5cb", "Atari, Ed Logg, Carol Shaw - Sears", "CX2639 - 49-75162", "Othello (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "55ace3c775f42eb46f08bb1dca9114e7", "", "", "Shadow Keep (04-03-2003) (Andrew Towers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "55ef6ab2321ca0c3d369e63d59c059c8", "", "", "Pitfall! (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "55ef7b65066428367844342ed59f956c", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "56210a3b9ea6d5dd8f417a357ed8ca92", "Probe 2000 - NAP, Roger Booth, Todd Marshall, Robin McDaniel, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype) [bad dump]", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "56300ed31fef018bd96768ccc982f7b4", "HES - Activision", "559", "Rad Action Pak - Kung-Fu Master, Freeway, Frostbite (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5641c0ff707630d2dd829b26a9f2e98f", "Joystik", "", "Motocross (Joystik)", "AKA Motocross Racer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5643ee916f7dc760148fca4db3aa7d10", "", "", "Moon Patrol (Genesis)", "Genesis controller (C is jump)", "Hack of Moon Patrol", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5678ebaa09ca3b699516dba4671643ed", "Coleco, Sylvia Day, Henry Will IV", "2459", "Mouse Trap (1982) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "568371fbae6f5e5b936af80031cd8888", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "56f72247eb9ebfd33bfd0cca23ab7ef4", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) v4 (PAL60) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "571c6d9bc71cb97617422851f787f8fe", "Activision, David Crane - Ariola", "EAG-004, PAG-004 - 711 004-715", "Fishing Derby (1980) (Activision) (PAL)", "AKA Schneller als der Hai", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "572d0a4633d6a9407d3ba83083536e0f", "Funvision - Fund. International Co.", "", "Busy Police (Funvision)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "575c0fb61e66a31d982c95c9dea6865c", "", "", "Blackjack (Unknown) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "57939b326df86b74ca6404f64f89fce9", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "579baa6a4aa44f035d245908ea7a044d", "Jess Ragan", "", "Galaxian Enhanced Graphics (Jess Ragan) (Hack)", "Hack of Galaxian", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "57a66b6db7efc5df17b0b0f2f2c2f078", "Retroactive", "", "Qb (V2.08) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "57c5b351d4de021785cf8ed8191a195c", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari)", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5835a78a88f97acea38c964980b7dbc6", "", "", "Cosmic Creeps (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5846b1d34c296bf7afc2fa05bbc16e98", "Atari - Sears", "CX2643 - 6-99815", "Codebreaker (1978) (Atari)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58513bae774360b96866a07ca0e8fd8e", "Mystique - American Multiple Industries, Joel H. Martin", "1001", "Custer's Revenge (1982) (Mystique)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "585600522b1f22f617652c962e358a5d", "", "", "Multi-Sprite Game V2.2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "585f73010e205ae5b04ee5c1a67e632d", "", "", "Daredevil (V3) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5864cab0bc21a60be3853b6bcd50c59f", "", "", "Commando Raid (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58746219d8094edff869f0f5c2aeaad5", "Jone Yuan Telephonic Enterprise Co", "", "Bowling (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5894c9c0c1e7e29f3ab86c6d3f673361", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "AZ-033, AZ-033-04", "Space Shuttle (1983) (Activision)", "A Journey Into Space", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "589c73bbcd77db798cb92a992b4c06c3", "Xonox - K-Tel Software - Action Graphics, Michael Schwartz, David Thiel", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) (PAL60)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58a82e1da64a692fd727c25faef2ecc9", "CCE", "C-824", "Jaw Breaker (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58c396323ea3e85671e34c98eb54e2a4", "Brian Watson", "", "Color Tweaker (B. Watson)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58d331c23297ed98663d11b869636f16", "", "", "Fu Kung! (V0.09) (26-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "58e313e2b5613b2439b5f12bb41e3eef", "", "", "Cube Conquest (Demo Interlace) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "590ac71fa5f71d3eb29c41023b09ade9", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (01-05-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59135f13985b84c4f13cc9e55eec869a", "", "", "Multi-Sprite Game V2.0 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "594437a35603c3e857b5af75b9718b61", "HES - Activision", "", "Robot Tank (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "594dbc80b93fa5804e0f1368c037331d", "Telesys, Alex Leavens", "", "Bouncin' Baby Bunnies (1983) (Telesys) (Prototype)", "AKA Baby Boom Boom, Bouncing Baby Monkeys", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5961d259115e99c30b64fe7058256bcf", "Universal Gamex Corporation, Miguel Castillo, H.K. Poon", "GX-001", "X-Man (1983) (Universal)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59734e1cc41822373845a09c51e6ba21", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "598a4e6e12f8238b7e7555f5a7777b46", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "599cbf919d47a05af975ad447df29497", "Jake Patterson", "", "Baubles (V0.002) (2001) (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59b70658f9dd0e2075770b07be1a35cf", "Thomas Jentzsch", "", "Surfer's Paradise (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59d33e00c07665395209c1e55da0b139", "", "", "Imagic Selector ROM (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59e53894b3899ee164c91cfa7842da66", "Data Age", "", "Survival Run (1983) (Data Age) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "59e96de9628e8373d1c685f5e57dcf10", "PlayAround - J.H.M.", "204", "Beat 'Em & Eat 'Em (1982) (PlayAround)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "59f596285d174233c84597dee6f34f1f", "CCE", "C-811", "River Raid (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a0ff99ba10bd26d542e1d6f59f56850", "Champ Games", "CG-04-P", "Super Cobra Arcade (PAL60)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5a17e30e6e911e74ccd7b716d02b16c6", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a272012a62becabcd52920348c7c60b", "Star Game", "", "Pitfall (Star Game)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a2f2dcd775207536d9299e768bcd2df", "Otto Versand", "781698", "Flippern (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Video Pinball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a4205aeedd3b0588f973f38bbd9dfd4", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a5390f91437af9951a5f8455b61cd43", "Retroactive", "", "Qb (0.11) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5a6febb9554483d8c71c86a84a0aa74e", "CCE", "C-1003", "Donkey Kong Jr (1983) (CCE)", "AKA Donkey Kong Junior", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a734779d797ccef25dc8acfa47244c7", "", "", "Oh No! (Version 2) (18-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a80b857eb8b908ab477ec4ef902edc8", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a81ad4e184050851e63c8e16e3dac77", "Jone Yuan Telephonic Enterprise Co", "Hack", "Sky Diver (Jone Yuan) (Hack)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a8afe5422abbfb0a342fb15afd7415f", "Atari - Bobco, Robert C. Polaro", "CX26155", "Sprint Master (1988) (Atari)", "AKA Sprint 88, Sprint 2000", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a93265095146458df2baf2162014889", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a9685c4d51a6c1d6a9544946d9e8dc3", "AtariAge", "", "Grandma's Revenge (AtariAge)", "Can use Driving Controller in right port", "", "", "", "", "", "", "", "", "", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5a9d188245aff829efde816fcade0b16", "CCE", "C-808", "Phantom Tank (1983) (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5acf9865a72c0ce944979f76ff9610f0", "", "", "Dodge Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5ae73916fa1da8d38ceff674fa25a78a", "CCE", "", "Barnstorming (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5aea9974b975a6a844e6df10d2b861c4", "Atari, Dan Hitchens. Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari)", "AKA Adventure I, SwordQuest I - EarthWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5af9cd346266a1f2515e1fbc86f5186a", "SEGA", "002-01", "Sub-Scan (1983) (SEGA)", "AKA Subterfuge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b124850de9eea66781a50b2e9837000", "PlayAround - J.H.M.", "205", "Bachelor Party (1982) (PlayAround)", "Uses the paddle controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "5b574faa56836da0866ba32ae32547f2", "", "", "Tomb Raider 2600 [REV 03] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b5d04887922b430de0b7b2a21f9cd25", "", "", "Omega Race (Genesis)", "Genesis controller (B is thrust, C is fire)", "Hack of Omega Race", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b6f5bcbbde42fc77d0bdb3146693565", "", "", "Seaquest (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b7ea6aa6b35dc947c65ce665fde624b", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (2 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b85e987e2b1618769d97ba9182333d0", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (05-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b92a93b23523ff16e2789b820e2a4c5", "Activision - Imagineering, Dan Kitchen, Garry Kitchen", "AG-039-04", "Kung-Fu Master (1987) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b98e0536c3f60547dd708ae22adb04b", "Ben Hudman", "", "Donkey Kong Gingerbread Man (Ben Hudman) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5b9c2e0012fbfd29efd3306359bbfc4a", "HES", "", "2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5babe0cad3ec99d76b0aa1d36a695d2f", "Coleco - Individeo, Ed Temple", "2654", "Looping (1983) (Coleco) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5bba254e18257e578c245ed96f6b003b", "", "", "Music Effects Demo (21-01-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5bbab3f3e4b47e3e23f9820765dbb45c", "", "", "Pitfall! (says 1985) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5bbb75b49b2bccef9c91ff84bb249c80", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5bc9998b7e9a970e31d2cb60e8696cc4", "Jack Kortkamp", "", "Borgwars Asteroids (2003) (Jack Kortkamp) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5bcc83677d68f7ef74c1b4a0697ba2a8", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision) (16K)", "", "", "", "", "4K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5bd79139a0c03b63f6f2cf00a7d385d2", "Marc de Smet", "", "An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5be03a1fe7b2c114725150be04b38704", "Atari, Alan Miller", "CX2642", "Hunt & Score (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c0227ad63300670a647fcebf595ea37", "Josh", "", "Battle for Naboo (Josh) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c0520c00163915a4336e481ca4e7ef4", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL) [a1]", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c19f6da638c4c7c1f98d09e63df43e4", "Canal 3 - Intellivision", "", "Cosmic Ark (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c1b1aa78b7609d43c5144c3b3b60adf", "", "", "Demo Image Series #8 - Two Marios (Different Interlacing) (27-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c3a6d27c026f59a96b7af91e8b1bf26", "PlayAround - J.H.M.", "", "PlayAround Demo (PlayAround) (1982)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c618a50dfa23daac97ba459b9ff5206", "Steve Engelhardt", "", "Berzerk Renegade (2002) (Steve Engelhardt) (Hack)", "Hack of Room of Doom", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5c73693a89b06e5a09f1721a13176f95", "", "", "Wavy Line Test 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5c86e938e0845b9d61f458539e9a552b", "Atari, Alan Miller", "CX26163P", "Surround (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5cbd7c31443fb9c308e9f0b54d94a395", "Spectravideo, Mark Turmell", "SA-217", "Gas Hog (1983) (Spectravideo) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5ce98f22ade915108860424d8dde0d35", "", "", "Hangman Man Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5ced13931c21ef4fc77d3fe801a1cbfa", "CCE", "C-828", "Missile Command (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d0e8a25cbd23e76f843c75a86b7e15b", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-07-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d132d121aabc5235dd039dfc46aa024", "", "", "Basketball (208 in 1) (Unknown) (PAL) (Hack)", "Console ports are swapped", "Hack", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d25df9dc2cde746ceac48e834cf84a7", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "EAZ-033", "Space Shuttle (1983) (Activision) (SECAM)", "A Journey Into Space", "", "", "", "FE", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d2cc33ca798783dee435eb29debf6d6", "Activision - Imagineering, Mike Reidel", "AK-043-04", "Commando (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d7293f1892b66c014e8d222e06f6165", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a1]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d799bfa9e1e7b6224877162accada0d", "Spectravision - Spectravideo - Sirius Software, David Lubar", "SA-206", "Challenge of.... Nexar, The (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d8f1ab95362acdf3426d572a6301bf2", "Thomas Jentzsch", "", "SWOOPS! (v0.96) (TJ) (PAL)", "Uses the Joystick (L) and Paddle (R) Controllers", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d8fb14860c2f198472b233874f6b0c9", "", "", "Boing! (PD) [a2]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5d9592756425192ec621d2613d0e683d", "CCE", "C-839", "Misterious Thief, A (1983) (CCE) [a]", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5da8fd0b5ed33a360bff37f8b5d0cd58", "Tron", "", "Pole Position (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5dae540347cf0a559962d62604ecf750", "Canal 3 - Intellivision", "", "Freeway (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5db9e5bf663cad6bf159bc395f6ead53", "Goliath - Hot Shot", "83-212", "Time Race (1983) (Goliath) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5dccf215fdb9bbf5d4a6d0139e5e8bcb", "Froggo", "FG1009", "Sea Hunt (1987) (Froggo)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5de8803a59c36725888346fdc6e7429d", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5df32450b9fbcaf43f9d83bd66bd5a81", "Eric Ball", "", "Atari Logo Playfield Demo (2001) (Eric Ball) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5df559a36347d8572f9a6e8075a31322", "Digivision", "", "Enduro (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e0c37f534ab5ccc4661768e2ddf0162", "Telegames - VSS, Ed Salvo", "5667 A106", "Glacier Patrol (1988) (Telegames)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e1b4629426f4992cf3b2905a696e1a7", "Activision - Bobco, Robert C. Polaro", "AK-049-04", "Rampage! (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e1b7a6078af428ef056fe85a37a95ca", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e1cd11a6d41fc15cf4792257400a31e", "Philip R. Frey", "", "Return of Mario Bros (Philip R. Frey) (Hack)", "Hack of Mario Bros.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e201d6bfc520424a28f129ee5e56835", "Universal Gamex Corporation, Miguel Castillo, H.K. Poon", "GX-001", "X-Man (1983) (Universal) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e2495d43b981010304af55efed1e798", "Jone Yuan Telephonic Enterprise Co", "", "Math Gran Prix (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e43c0391f7412ae64fae6f3742d6ee9", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.27)", "", "New Release, supports BoosterGrip", "", "", "", "", "", "", "", "BOOSTERGRIP", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5e99aa93d0acc741dcda8752c4e813ce", "", "", "2600 Digital Clock (V b2) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5ec73ac7d2ac95ac9530c6d33e713d14", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (2 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5eeb81292992e057b290a5cd196f155d", "Wizard Video Games - VSS, Ed Salvo", "008", "Texas Chainsaw Massacre, The (1983) (Wizard Video)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5ef303b9f0aa8cf20720c560e5f9baa1", "Atari, Jim Huether", "CX2629, CX2629P", "Sky Diver (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f1b7d5fa73aa071ba0a3c2819511505", "CCE", "", "Cosmic Commuter (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f2b4c155949f01c06507fb32369d42a", "Apollo, Ed Salvo", "AP-1001", "Skeet Shoot (1981) (Apollo) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f316973ffd107f7ab9117e93f50e4bd", "", "", "Commando Raid (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f39353f7c6925779b0169a87ff86f1e", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (1983) (Atari) [a]", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f46d1ff6d7cdeb4b09c39d04dfd50a1", "Atari, Gary Palmer", "CX2661P", "Fun with Numbers (1980) (Atari) (PAL)", "AKA Basic Math", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f4ebf8a1e5f5f7b9ff3e3c6affff3e6", "Bit Corporation", "R320", "Donkey Kong (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f560837396387455c9dcb05cdd4b053", "Canal 3 - Intellivision", "", "Eggomania (Canal 3)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "5f681403b1051a0822344f467b05a94d", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5f708ca39627697e859d1c53f8d8d7d2", "Atari, Warren Robinett - Sears", "CX2606 - 6-99825, 49-75112", "Slot Racers (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f73e7175474c1c22fb8030c3158e9b3", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f786b67e05fb9985b77d4beb35e06ee", "Atari, Bill Aspromonte, Andrew Fuchs", "CX26120", "Defender II (1987) (Atari) (PAL)", "AKA Stargate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f7ae9a7f8d79a3b37e8fc841f65643a", "Atari, Jerome Domurat, Peter C. Niday, Robert Vieira", "CX26109", "Sorcerer's Apprentice (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f7de62a408b9de3a1168898298fd31d", "", "", "Super Cobra (Genesis)", "Genesis controller (B is bomb, C is laser)", "Hack of Super Cobra", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5f950a2d1eb331a1276819520705df94", "20th Century Fox Video Games - Micro Computer Technologies, Jim Collas", "", "Heart Like a Wheel (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "5f9b62350b31be8bd270d9a241cbd50e", "Telegames", "5658 A088", "Football (1988) (Telegames) (PAL)", "AKA Super Challenge Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5faffe1c4c57430978dec5ced32b9f4a", "Dactari - Milmar", "", "Volleyball (Dactari - Milmar)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "5fb71cc60e293fe10a5023f11c734e55", "", "", "This Planet Sucks (Fix) (27-12-2002) (Greg Troutman)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "600d48eef5c0ec27db554b7328b3251c", "", "", "Bars and Text Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6015a9cef783e97e98a2aa2cf070ae06", "Thomas Jentzsch", "", "Battlezone TC (Thomas Jentzsch) (Hack)", "Uses two simultaneous Joystick Controllers, Hack of Battlezone", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "60358edf0c2cc76b1e549e031e50e130", "Manuel Polik", "", "Cyber Goth Galaxian (Manuel Polik) (Hack)", "Hack of Galaxian", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "603c7a0d12c935df5810f400f3971b67", "Bit Corporation", "PG209", "Mr. Postman (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6041f400b45511aa3a69fab4b8fc8f41", "Apollo, Ban Tran", "AP-2010", "Wabbit (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "604e09724555807c28108049efe34a13", "", "", "Sokoban (01-01-2003) (Adam Wozniak)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6058e40ce79d7434c7f7477b29abd4a5", "", "", "Rubik's Cube Demo (23-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "605dcb73d22f4efdb90ef9da2f290f7c", "Atari, Larry Kaplan", "CX26163P", "Air-Sea Battle (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "605fd59bfef88901c8c4794193a4cbad", "Data Age", "", "Secret Agent (1983) (Data Age) (Prototype)", "Uses the Paddle Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "606c2c1753051e03c1f1ac096c9d2832", "Jone Yuan Telephonic Enterprise Co", "", "Crackpots (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6076b187a5d8ea7a2a05111c19b5d5cd", "", "", "Fu Kung! (V0.14) (01-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "60a61da9b2f43dd7e13a5093ec41a53d", "VentureVision, Dan Oliver", "VV2001", "Rescue Terra I (1982) (VentureVision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "60bbd425cb7214ddb9f9a31948e91ecb", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "60cd61a2dfccb0e2736434f9792c1672", "Amiga - Video Soft, Frank Ellis, Jerry Lawson", "2110", "3-D Havoc (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "60d304582d33e2957b73eb300a7495bb", "", "", "Jam Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "60e0ea3cbe0913d39803477945e9e5ec", "Atari, Joe Decuir - Sears", "CX2621 - 99806, 6-99806, 49-75104", "Video Olympics (1977) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "PADDLES_IAXDR", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "613abf596c304ef6dbd8f3351920c37a", "", "", "Boring Pac-Man (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6141c095d0aee4e734bebfaac939030a", "Rainbow Vision - Suntek", "SS-017", "Mariana (1983) (Rainbow Vision) (PAL)", "AKA Seaquest", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61426cee013306e7f7367534ab124747", "", "", "One Blue Bar Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "615a3bf251a38eb6638cdc7ffbde5480", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61621a556ad3228f0234f5feb3ab135c", "", "", "Fu Kung! (V0.05 Cuttle Card Compattle Revision) (14-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61631c2f96221527e7da9802b4704f93", "Activision - Imagineering, Mike Reidel", "AK-043-04", "Commando (1988) (Activision) [different logo]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61719a8bdafbd8dab3ca9ce7b171b9e2", "", "", "Enduro (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61728c6cfb052e62a9ed088c5bf407ba", "", "", "Sprite Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "619de46281eb2e0adbb98255732483b4", "", "", "Time Warp (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61baadddc2c8f6e5faa57d4d0f285462", "", "", "208-in-1 MDM-Test (PAL) (127 games)", "", "", "", "", "MDM", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61dbe94f110f30ca4ec524ae5ce2d026", "CCE", "C-820", "Space Invaders (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61e0f5e1cc207e98704d0758c68df317", "Star Game", "007", "Tennis (Star Game)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "61ef8c2fc43be9a04fe13fdb79ff2bd9", "", "", "Gas Gauge Demo - Revisited (2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6205855cc848d1f6c4551391b9bfa279", "", "", "Euchre (Release Candidate 2) (NTSC) (01-10-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6238ac888871fec301d1b9fc4fc613c9", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (PAL) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "624e0a77f9ec67d628211aaf24d8aea6", "Panda", "108", "Sea Hawk (1983) (Panda)", "AKA Seahawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "626d67918f4b5e3f961e4b2af2f41f1d", "Atari", "50008", "Diagnostic Test Cartridge 2.0 (1980) (Atari) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6272f348a9a7f2d500a4006aa93e0d08", "Atari, Jerome Domurat, Michael Sierchio", "CX2667, CX2667P", "RealSports Soccer (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "62899430338e0538ee93397867d85957", "Gameworld", "133-004", "Airlock (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "62921652f6634eb1a0940ed5489c7e18", "", "", "SCSIcide (V1.09) (2001) (Joe Grand)", "", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "62992392ea651a16aa724a92e4596ed6", "Eric Mooney", "", "Invaders by Erik Mooney (Beta) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "62d1f50219edf9a429a9f004c19f31b3", "JWDA, Todd Marshall", "", "Euro Gen (02-01-83) (JWDA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "62ee2b8f59e9cd6285bbdb674a952e8b", "Probe 2000 - NAP, Roger Booth, Todd Marshall, Robin McDaniel, Jim Wickstead", "3152VC", "Pursuit of the Pink Panther (Probe) (Prototype)", "AKA Adventures of the Pink Panther", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "62f74a2736841191135514422b20382d", "", "", "Pharaoh's Curse (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "YES", "", "", "", "", "" }, + { "62ffd175cac3f781ef6e4870136a2520", "", "", "2600 Digital Clock (V x.xx) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63166867f75869a3592b7a94ea62d147", "", "", "Indy 500 (Hack) [a1]", "Hack of Indy 500", "Hack", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6333ef5b5cbb77acd47f558c8b7a95d3", "Greg Troutman", "", "Dark Mage (Greg Troutman) (PD) (8K)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6337927ad909aa739d6d0044699a916d", "Jeffry Johnston", "", "Radial Pong - Version 2 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6339d28c9a7f92054e70029eb0375837", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6342afe9c9ad1b6120b8f6fb040d0926", "", "", "Move a Blue Blob Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6354f9c7588a27109c66905b0405825b", "Thomas Jentzsch", "", "Amidar DS (2003) (TJ) (Hack)", "Hack of Amidar", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6358f7f8bf0483402a080efccf250d61", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid) (Prototype)", "AKA Termite", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "635cc7a0db33773959d739d04eff96c2", "", "", "Minesweeper (V.90) (Soren Gust) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6362396c8344eec3e86731a700b13abf", "Panda", "109", "Exocet (1983) (Panda)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "637efac676ff063f2fbb0abff77c4fa5", "", "", "Noize Maker Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63811ed69bdbc35c69d8aa7806c3d6e9", "Atari", "CX26163P", "Homerun (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "638cc82ea96f67674595ba9ae05da6c6", "Rainbow Vision - Suntek", "SS-011", "Super Ferrari (1983) (Rainbow Vision) (PAL)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63a6eda1da30446569ac76211d0f861c", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63a7445b1d3046d3cdcdbd488dca38d9", "Rob Kudla", "", "Better Space Invaders (1999) (Rob Kudla) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63c5fef3208bb1424d26cf1ab984b40c", "", "", "Analog Clock (V0.1) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63c7395d412a3cd095ccdd9b5711f387", "Eric Ball", "ELB005", "Skeleton+ (PAL)", "Stereo sound", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63d6247f35902ba32aa49e7660b0ecaa", "", "", "Space War (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63e42d576800086488679490a833e097", "Telesys, Jim Rupp", "1004", "Ram It (1983) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63e783994df824caf289b69a084cbf3e", "David Marli", "", "Fat Albert (David Marli) (Hack)", "Hack of Fast Food", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "63e9e612bbee31045f8d184a4e53f8ec", "ATARITALIA", "", "Moby Blues (2002) (ATARITALIA) (Hack)", "Hack of Mario Bros", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "640a08e9ca019172d612df22a9190afb", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691, CX2691P", "Joust (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "64198bb6470c78ac24fcf13fe76ab28c", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "643e6451eb6b8ab793eb60ba9c02e000", "Salu - Avantgarde Software, Michael Buetepage", "460741", "Ghostbusters II (1992) (Salu) (PAL) [different tune]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "645bf7f9146f0e4811ff9c7898f5cd93", "Xonox - K-Tel Software - VSS, Robert Weatherby", "6230, 6250", "Super Kung-Fu (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6468d744be9984f2a39ca9285443a2b2", "Atari, Ed Logg, Carol Shaw", "CX26163P", "Reversi (32 in 1) (1988) (Atari) (PAL)", "AKA Othello", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "647162cceb550fd49820e2206d9ee7e8", "", "", "Skeleton (NTSC) (2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "64b8e19c767191ccdc97acc6904c397b", "Jeffry Johnston", "", "Radial Pong - Version 6 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "64ca518905311d2d9aeb56273f6caa04", "CCE", "", "Cubo Magico (CCE)", "AKA Cubicolor", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "64d43859258dc8ca54949e9ff4174202", "Thomas Jentzsch", "", "Lilly Adventure (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "64fab9d15df937915b1c392fc119b83b", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (05-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "650df778c6ce22d3fd1a7c33c565bcc3", "Atari - GCC, Betty Ryan Tylko, Douglas B. Macrae", "CX2694", "Pole Position (1983) (Atari)", "Genesis controller (B is high gear, C is low gear, left difficulty switch swaps gear buttons)", "Hack of Pole Position", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "651d2b6743a3a18b426bce2c881af212", "CCE", "C-812", "Pac Man (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6522717cfd75d1dba252cbde76992090", "Home Vision - Gem International Corp. - VDI", "VCS83102", "War 2000 (1983) (Home Vision) (PAL)", "AKA Astrowar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6538e454b0498ad2befe1ef0f87815c0", "Joe Grand", "", "SCSIcide (v1.2) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "65490d61922f3e3883ee1d583ce10855", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692, CX2692P", "Moon Patrol (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "65562f686b267b21b81c4dddc129d724", "", "", "Euchre (28-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "655c84e5b951258c9d20f0bf2b9d496d", "", "", "2600_2003 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "656dc247db2871766dffd978c71da80c", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (1981) (Sears)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "6588d192d9a8afce27b44271a2072325", "Bit Corporation", "R320", "Basketball (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "65917ae29a8c9785bb1f2acb0d6aafd0", "", "", "Junkosoft One Year Demo (1999) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6596b3737ae4b976e4aadb68d836c5c7", "Digivision", "", "Defender (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "659a20019de4a23c748ec2292ea5f221", "Retroactive", "", "Qb (V2.05) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "65a6f1255fe22468a8bf84ff28a4d289", "Akor", "", "Super TV Boy (1995) (Akor)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "65b106eba3e45f3dab72ea907f39f8b4", "Christian Software Development - HomeComputer Software, Dan Schafer, Glenn Stohel, Jon Tedesco - Sparrow", "GCG 1001T", "Music Machine, The (1983) (Sparrow)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "65ba1a4c643d1ab44481bdddeb403827", "Quelle", "876.013 4", "Katastrophen-Einsatz (1983) (Quelle) (PAL)", "AKA M.A.S.H.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "65bd29e8ab1b847309775b0de6b2e4fe", "Coleco, Ed English", "2667", "Roc 'n Rope (1984) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "65c6406f5af934590097c8c032ebb482", "", "", "Three Hugger (Pave Demo) (20-12-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6604f72a966ca6b2df6a94ee4a68eb82", "", "", "MegaMania (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "662eca7e3d89175ba0802e8e3425dedb", "", "", "Hangman Pac-Man Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66362890eb78d6ea65301592cce65f5b", "", "", "Euchre (13-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "663ef22eb399504d5204c543b8a86bcd", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "4L1720, 4L1721, 4L1722, 4L2276", "Wizard of Wor (1982) (CBS Electronics) (PAL)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "664d9bfda6f32511f6b4aa0159fd87f5", "Atari - Roklan, Joe Gaucher", "", "Racer (1982) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6651e2791d38edc02c5a5fd7b47a1627", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (04-05-1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "665b8f8ead0eef220ed53886fbd61ec9", "Telesys, Don Ruffcorn, Jack Woodman", "1003", "Fast Food (1982) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66706459e62514d0c39c3797cbf73ff1", "Video Gems", "VG-05", "Treasure Below (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6672de8f82c4f7b8f7f1ef8b6b4f614d", "Videospielkassette - Ariola", "PGP237", "Angeln I (Ariola) (PAL)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "667a70b028f581d87648693b873bc962", "Parker Brothers - Roklan, Joe Gaucher", "PB5370", "Popeye (1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "668dc528b7ea9345140f4fcfbecf7066", "Gakken", "001", "Pooyan (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6697f177847c70505824422e76aad586", "", "", "Tennis (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "669840b0411bfbab5c05b786947d55d4", "Atari, Andrew Fuchs, Jeffrey Gusman, Dave Jolly, Suki Lee", "CX26117", "Obelix (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66b89ba44e7ae0b51f9ef000ebba1eb7", "Atari - CCW, Stephan R. Keith, Laura Scholl, Preston Stuart", "CX26106", "Grover's Music Maker (01-18-1983) (Atari) (Prototype)", "Uses Keypad Controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66b92ede655b73b402ecd1f4d8cd9c50", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66bc1bef269ea59033928bac2d1d81e6", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (Preview) (1982) (Arcadia)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "66c2380c71709efa7b166621e5bb4558", "Parker Brothers, Dave Engman, Dawn Stockbridge", "931509", "Tutankham (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66c4e0298d4120df333bc2f3e163657e", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (2 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66f49b3248791b9803fa3e2f4165d072", "Bit Corporation", "R320", "Football (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "66fcf7643d554f5e15d4d06bab59fe70", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6706a00f9635508cfeda20639156e66e", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "672012d40336b403edea4a98ce70c76d", "", "", "Spider Kong (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "675ae9c23fa1aae376cea86cad96f9a5", "", "", "Poker Squares (V0.25) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67631ea5cfe44066a1e76ddcb6bcb512", "", "", "Termool (Unknown) (PAL)", "AKA Turmoil", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67684a1d18c85ffa5d82dab48fd1cb51", "Tigervision, Warren Schwader - Teldec", "7-003", "Threshold (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "678c1d71a1616d9d022f03d8545b64bb", "", "", "Demo Image Series #11 - Donald And Mario (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67931b0d37dc99af250dd06f1c095e8d", "CommaVid, Irwin Gaines", "CM-004", "Room of Doom (1982) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "679d30c7886b283cbe1db4e7dbe5f2a6", "Colin Hughes", "", "Puzzle (Colin Hughes) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "679e910b27406c6a2072f9569ae35fc8", "Data Age", "DA1002", "Warplock (1982) (Data Age)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 40", "", "", "YES", "", "", "", "", "" }, + { "67bd3d4dc5ac6a42a99950b4245bdc81", "Retroactive", "", "Qb (2.11) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "67c05ae94bf8b83a666c3ae2c4bc14de", "Atari", "CX26163P", "NFL Football (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67cdde4176e0447fc45a71e0a1cdd288", "Telegames - VSS, Ed Salvo", "5665 A016", "Glacier Patrol (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67ce6cdf788d324935fd317d064ed842", "Retroactive", "", "Qb (V2.09) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "67cf913d1df0bf2d7ae668060d0b6694", "", "", "Hangman Monkey 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "67f90d74fd0b72fdc6d9b92436780ea9", "Omegamatrix", "", "SpaceMaster X-7 (Atari Trak-Ball) (PAL60) (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6803fa7c2c094b428b859a58dc1dd06a", "Retroactive", "", "Qb (0.11) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6805734a0b7bcc8925d9305b071bf147", "Bit Corporation", "PGP229", "Kung Fu (4 Game in One Dark Green) (1983) (BitCorp) (PAL)", "AKA Karate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "681206a6bde73e71c19743607e96c4bb", "", "", "Casino (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6833c26f385e866f3a0fa0dff311216e", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "683bb0d0f0c5df58557fba9dffc32c40", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia) [a]", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "683dc64ef7316c13ba04ee4398e2b93a", "Ed Federmeyer", "", "Edtris (1995) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68449e4aaba677abcd7cde4264e02168", "", "", "Horizonal Color Bars Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6847ce70819b74febcfd03e99610243b", "", "", "Ruby Runner 4A50", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "68489e60268a5e6e052bad9c62681635", "Bit Corporation", "PG201", "Sea Monster (1982) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68597264c8e57ada93be3a5be4565096", "Data Age", "DA1005", "Bugs (1982) (Data Age)", "Uses the Paddle Controllers", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, + { "685e9668dc270b6deeb9cfbfd4d633c3", "CommaVid, Irwin Gaines - Ariola", "CM-004 - 712 004-720", "Room of Doom (1982) (CommaVid) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "68760b82fc5dcf3fedf84376a4944bf9", "CCE", "C-860", "Laser Gate (1983) (CCE)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "687c23224e26f81c56e431c24faea36d", "", "", "Qb (Simple Background Animation) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "68878250e106eb6c7754bc2519d780a0", "CCE", "C-809", "Squirrel (1983) (CCE)", "AKA Snail Against Squirrel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68ac69b8e1ba83af8792f693f5ae7783", "Digivision", "", "Fathon (Digivision)", "AKA Fathom", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68c80e7e1d30df98a0cf67ecbf39cc67", "Hozer Video Games", "", "Gunfight 2600 - One Step Forward & Two Steps Back (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68c938a2a2b45c37db50509f1037fe6e", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "68cd2adc6b1fc9a1f263ab4561112f30", "Thomas Jentzsch", "", "Boulderdash Demo (09-12-2002) (TJ)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "68feb6d6ff63e80df1302d8547979aec", "", "", "Starfield Demo 2 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "690a6049db78b9400c13521646708e9c", "King Tripod Enterprise Co.", "SS - 007", "Space Raid (King Tripod) (PAL)", "AKA Challenge of.... Nexar, The", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6913c90002636c1487538d4004f7cac2", "Atari - CCW", "CX26131", "Monster Cise (1984) (Atari) (Prototype)", "Uses the Keypad Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "691d67910b08b63de8631901d1887c1f", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "692202772d8b38ccf85a90c8003a1324", "", "", "Zi - The Flie Buster (2002) (Fernando Mora) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "693137592a7f5ccc9baae2d1041b7a85", "", "", "Qb (V2.02) (Stella) (2001) (Retroactive) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6936aa6763835f62ac13d1aaa79b9f91", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6979f30204149be3e227558cffe21c1d", "Atari", "CX26163P", "Miniaturer Golf (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Miniature Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6982854657a2cc87d712f718e402bf85", "Zellers", "", "Earth Attack (Zellers)", "AKA Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69877da5caded48315e3e45882a303d5", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "698f569eab5a9906eec3bc7c6b3e0980", "SpkLeader", "", "Demons! (2003) (SpkLeader) (Hack)", "Hack of Phoenix", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69974dd5d6420b90898cde50aec5ef39", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69df0411d4d176e558017f961f5c5849", "CCE", "C-831", "Cosmic Ark (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69e79b1352b9ee1754bbe63b4a7062c3", "Barry Laws Jr.", "", "Pink Floyd - The Wall (2003) (Barry Laws Jr.) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69ebf910ab9b63e5b8345f016095003b", "", "", "Maze Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69edfb4e1810a523311b3e250fc1e275", "Thomas Jentzsch", "", "Missile Command Atari Trak-Ball Hack v1.3 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "69fac82cd2312dd9ce5d90e22e2f070a", "Spectravision - Spectravideo - Quelle", "SA-202 - 412.851 8", "Planet Patrol (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a03c28d505bab710bf20b954e14d521", "", "", "Pressure Gauge 2 Beta (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a07836c382195dd5305ce61d992aaa6", "Apollo, Larry Martin", "AP-2008", "Guardian (1982) (Apollo) (Prototype)", "Uses the Paddle Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "6a091b8ffeacd0939850da2094b51564", "", "", "Vertically Scrolling Playfield (02-02-2003) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a222c26bcece3a510ddda21398f72c6", "Bit Corporation", "PG203", "Phantom Tank (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a2c68f7a77736ba02c0f21a6ba0985b", "Atari, Larry Wagner, Bob Whitehead", "", "Computer Chess (07-07-1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a3b0c33cf74b1e213a629e3c142b73c", "Cody Pittman", "", "Cory The Interviewer (Cody Pittman) (Hack)", "Hack of Ghostbusters", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a76d5f0ed721639474aa9bbde69ebf0", "", "", "Play Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6a82b8ecc663f371b19076d99f46c598", "Activision, Larry Miller - Ariola", "EAX-026, EAX-026-04B, EAX-026-04I - 711 026-725", "Enduro (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a882fb1413912d2ce5cf5fa62cf3875", "Video Game Cartridge - Ariola", "TP-605", "Dragon Defender (Ariola) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6a8c6940d3be6fd01274363c4d4b298e", "", "", "Spy Hunter (Genesis)", "Genesis controller (C is oil/smoke)", "Hack of Spy Hunter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a9b30ca46b0dba9e719f4cbd340e01c", "", "", "Frostbite (Unknown) (PAL) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6a9e0c72fab92df70084eccd9061fdbd", "CCE", "C-835", "Beany Bopper (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6aa66e9c3eea76a0c40ef05513497c40", "", "", "Hangman Ghost Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6ac3fd31a51730358708c7fdc62487f8", "Matthias Jaap", "", "PC Invaders (Matthias Jaap) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6aca52e11b597ab84b33d5252e1cd9d1", "Bit Corporation", "R320", "Tac-Scan (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "6ae4dc6d7351dacd1012749ca82f9a56", "Atari - GCC, Jaques Hugon, Seth Lipkin", "CX26125, CX26127", "Track and Field (1984) (Atari)", "Uses the Track & Field Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b01a519b413f8cfa2f399f4d2841b42", "", "", "Aphex Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b1fc959e28bd71aed7b89014574bdc2", "Bit Corporation", "PG203", "Phantom Tank (1982) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b4eb5b3df80995b8d9117cb7e9aeb3c", "Gameworld, J. Ray Dettling", "133-006", "Journey Escape (1983) (Gameworld) (PAL)", "AKA Rock 'n' Roll Escape", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6b683be69f92958abe0e2a9945157ad5", "U.S. Games Corporation - Western Technologies, Jeff Corsiglia, Paul Allen Newell, Steven B. Sidley, Tom Sloper", "VC2007", "Entombed (1983) (U.S. Games)", "Released as Name That Game for a contest (winning name was Entombed)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6b6ca32228ae352b4267e4bd2cddf10c", "", "", "Pac-Man 4 (Pac-Man Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b71f20c857574b732e7a8e840bd3cb2", "", "", "Frostbite (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b72b691ea86f61438ed0d84c4d711de", "", "", "Fishing Derby (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b75f8fa4fd011a6698c58315f83d2ac", "Thomas Jentzsch", "", "Sprintmaster DC (TJ)", "Uses the Driving Controllers, Hack of Sprintmaster (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "6b7a56b6ac2ca4bf9254474bf6ed7d80", "", "", "Horizonal Color Bars Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b7e1c11448c4d3f28160d2de884ebc8", "Zirok", "", "Fast Food (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6b8fb021bb2e1f1e9bd7ee57f2a8e709", "Paul Slocum", "", "3-D Corridor (29-03-2003) (Paul Slocum) (PD) [a]", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6bb09bc915a7411fe160d0b2e4d66047", "Atari", "CX26163P", "UFO (32 in 1) (1988) (Atari) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6bb22efa892b89b69b9bf5ea547e62b8", "Dynacom", "", "Megamania (1982) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6bde3f6ac31aceef447ce57d4d2c2ec0", "Piero Cavina", "", "Mondo Pong V1 (Piero Cavina) (PD)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "6c128bc950fcbdbcaf0d99935da70156", "Digitel", "", "Volleyball (1983) (Digitel)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c1553ca90b413bf762dfc65f2b881c7", "Quelle", "343.073 3", "Winterjagd (1983) (Quelle) (PAL)", "AKA Ski Hunt", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c1f3f2e359dbf55df462ccbcdd2f6bf", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c25f58fd184632ca76020f589bb3767", "Dynacom", "", "Beat 'Em & Eat 'Em (1983) (Dynacom)", "Uses the Paddle Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "6c449db9bbbd90972ad1932d6af87330", "", "", "20 Sprites at Once Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c658b52d03e01828b9d2d4718a998ac", "", "", "Hangman Invader Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c76fe09aa8b39ee52035e0da6d0808b", "Atari, Brad Stewart", "CX2622, CX2622P", "Breakout (1978) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, + { "6c85098518d3f94f7622c42fd1d819ac", "Suntek", "SS-028", "Firebug (1983) (Suntek) (PAL)", "AKA Spinning Fireball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c91ac51421cb9fc72c9833c4f440d65", "ITT Family Games", "554-33 375", "Cosmic Town (1983) (ITT Family Games) (PAL)", "AKA Base Attack (Perry Rhodan-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6c9a32ad83bcfde3774536e52be1cce7", "", "", "Space Treat (NTSC) (13-08-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6cab04277e7cd552a3e40b3c0e6e1e3d", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames) (Prototype)", "AKA Targ", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6cbe945e16d9f827d0d295546ac11b22", "", "", "Gunfight 2600 - AI (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6ccd8ca17a0e4429b446cdcb66327bf1", "", "", "RPG Engine (12-05-2003) (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6cd1dc960e3e8d5c5e0fbe67ab49087a", "", "", "Vertical Playfield Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6cd506509e8fd5627f55603780e862a8", "Greg Troutman", "", "Dark Mage (SuperCharger) (Greg Troutman) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6ce2110ac5dd89ab398d9452891752ab", "Funvision - Fund. International Co.", "", "Persian Gulf War (Funvision)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6cea35ded079863a846159c3a1101cc7", "", "", "Atlantis (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6ceb7d6a54e9a5e62d26874d1cc88dbc", "Video Soft", "", "Atom Smasher (1984) (Video Soft) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6cf054cd23a02e09298d2c6f787eb21d", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6d218dafbf5a691045cdc1f67ceb6a8f", "Robin Harbron", "", "6 Digit Score Display (1998) (Robin Harbron) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6d475019ea30d0b29f695e9dcfd8f730", "Eric Mooney", "", "Invaders by Erik Mooney (Alpha 2) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6d74ebaba914a5cfc868de9dd1a5c434", "", "", "Fortress (Smooth Version) (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6d842c96d5a01967be9680080dd5be54", "Activision, Steve Cartwright, David Crane", "AB-035-04", "Pitfall II (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6d8a04ee15951480cb7c466e5951eee0", "Zirok", "", "Kanguru (1983) (Zirok)", "AKA Kangaroo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6d9afd70e9369c2a6bff96c4964413b7", "", "", "Time Warp (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6dda84fb8e442ecf34241ac0d1d91d69", "Atari - GCC, Douglas B. Macrae", "CX2677", "Dig Dug (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6de924c2297c8733524952448d54a33c", "CCE", "C-1006", "Moon Patrol (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6dfad2dd2c7c16ac0fa257b6ce0be2f0", "Parker Brothers, Larry Gelberg", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e179eee3d4631a7434d40cf7aeea6e8", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e19428387686a77d8c8d2f731cb09e0", "", "", "Purple Cross Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e372f076fb9586aff416144f5cfe1cb", "Atari, Tod Frye - Sears", "CX2646 - 49-75185", "Pac-Man (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e59dd52f88c00d5060eac56c1a0b0d3", "Atari, Bob Smith", "CX2648", "Video Pinball (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e5d5ba193d2540aec2e847aafb2a5fb", "Retroactive", "", "Qb (2.14) (Retroactive) (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6e7ed74082f39ad4166c823765a59909", "", "", "Poker Squares (V0.14) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6e7efb0ed13ec28a00d19572de9c9f03", "Apollo - Games by Apollo", "AP-2006", "Infiltrate (1982) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6eb10fd23c7161751d18b9e8484c0004", "Coleco - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "2465", "Smurf - Rescue in Gargamel's Castle (1983) (Coleco) (Prototype)", "AKA Smurf, Smurf Action", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6ed5012793f5ddf4353a48c11ea9b8d3", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Down on the Line (3 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "01 70", "", "", "", "", "", "", "", "" }, + { "6ed6bda5c42b2eb7a21c54e5b3ace3e3", "Canal 3 - Intellivision", "", "Ice Hockey (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6efe876168e2d45d4719b6a61355e5fe", "Bit Corporation", "PG207", "Mission 3,000 A.D. (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6f084daf265599f65422ef4173b69bc7", "", "", "Music Kit (V2.0) - Song Player (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6f2aaffaaf53d23a28bf6677b86ac0e3", "U.S. Games Corporation - Vidtec - JWDA, Garry Kitchen", "VC1001", "Space Jockey (1982) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6f3e3306da2aa6e74a5e046ff43bf028", "", "", "Defender Arcade (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender 2", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6f744f14aac04f7e1ea0d3f4bafcb3e4", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a3]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6f74ed915ffe73b524ef0f63819e2a1d", "Eckhard Stolberg", "", "An Exercise In Minimalism (V2) (1999) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fa0ac6943e33637d8e77df14962fbfc", "Imagic, Rob Fulop", "", "Cubicolor (1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fac680fc9a72e0e54255567c72afe34", "", "", "Superman (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fbd05b0ad65b2a261fa154b34328a7f", "", "", "Boardgame Demo (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fc0176ccf53d7bce249aeb56d59d414", "Rainbow Vision - Suntek", "SS-004", "Pyramid War (1983) (Rainbow Vision) (PAL)", "AKA Chopper Command", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fc27a9233fc69d28d3f190b4ff80f03", "", "", "UFO #6 (Charles Morgan) (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fc394dbf21cf541a60e3b3631b817f1", "Imagic, Bob Smith", "720020-2A, IA3611P", "Dragonfire (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "6fd7c7057eeab273b29c7aafc7429a96", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6fe67f525c39200a798985e419431805", "Atari - GCC, Kevin Osborn", "CX2689, CX2689P", "Kangaroo (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "6ff4156d10b357f61f09820d03c0f852", "Atari, Larry Kaplan - Sears", "CX2612 - 99804, 49-75103", "Street Racer (1977) (Atari) (4K)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 60", "", "", "", "", "", "", "", "" }, + { "6ffc95108e5add6f9b8abcaf330be835", "Charles Morgan", "", "TP Bug (Charles Morgan) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "700a786471c8a91ec09e2f8e47f14a04", "Activision", "", "Hard-Head (1983) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "703d32062436e4c20c48313dff30e257", "", "", "Moving Maze Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "703f0f7af350b0fa29dfe5fbf45d0d75", "Bit Corporation", "P460", "4 Game in One Dark Green (1983) (BitCorp) (PAL)", "Rodeo Champ, Bobby is Going Home, Open Sesame, Festival", "", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "705fe719179e65b0af328644f3a04900", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "706e3cc4931f984447213b92d1417aff", "", "", "Joustpong (06-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "707ecd80030e85751ef311ced66220bc", "", "", "Double-Height 6-Digit Score Display (Background Color Change) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7096a198531d3f16a99d518ac0d7519a", "Telesys, Jim Rupp", "1004", "Ram It (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "709910c2e83361bc4bf8cd0c20c34fbf", "Rainbow Vision - Suntek", "SS-006", "Netmaker (1983) (Rainbow Vision) (PAL)", "AKA Amidar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "70a43fbdb1c039283ee5048d99842469", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "70a8480cfaf08776e5420365732159d2", "Rob Kudla", "", "Horizontally Scrolling Playfield Thing (Rob Kudla) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "70ce036e59be92821c4c7fd735ec6f68", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "70d14c66c319683b4c19abbe0e3db57c", "", "", "Oystron (V2.82) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "710497df2caab69cdcc45e919c69e13f", "Arcadia Corporation, Dennis Caswell", "5 AR-4200", "Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "713fde2af865b6ec464dfd72e2ebb83e", "", "", "Challenge (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "71464c54da46adae9447926fdbfc1abe", "M Network - INTV - APh Technological Consulting, Bruce Pedersen", "MT5663", "Lock 'n' Chase (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "714e13c08508ee9a7785ceac908ae831", "Home Vision - Gem International Corp. - VDI", "VCS83123", "Parachute (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "715dbf2e39ba8a52c5fe5cdd927b37e0", "Amiga - Video Soft", "3135", "S.A.C. Alert (1983) (Amiga) (Prototype)", "Uses Joyboard", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "715dd9e0240638d441a3add49316c018", "Atari", "", "128-in-1 Junior Console (Chip 2 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7187118674ff3c0bb932e049d9dbb379", "Zirok", "", "Keystone Keypers (1983) (Zirok)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "718ae62c70af4e5fd8e932fee216948a", "Data Age, J. Ray Dettling", "112-006", "Journey Escape (1983) (Data Age)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "718ee85ea7ec27d5bea60d11f6d40030", "Thomas Jentzsch", "", "Ghostbusters II (1992) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7197b6cbde6ecd10376155e6b848e80d", "Piero Cavina", "", "Multi-Sprite Game V2.1 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "71b193f46c88fb234329855452dfac5b", "Digitel", "", "Atlantis (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "71d005b60cf6e608d04efb99a37362c3", "Atari, Larry Kaplan", "CX2643", "Codebreaker (1978) (Atari) (PAL) (4K) [a]", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "71f09f128e76eb14e244be8f44848759", "Funvision - Fund. International Co.", "", "Time Race (Funvision) (PAL)", "AKA Time Warp", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "71f8bacfbdca019113f3f0801849057e", "Atari, Dan Hitchens", "CX26126", "Elevator Action (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72097e9dc366900ba2da73a47e3e80f5", "", "", "Euchre (15-06-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "721a5567f76856f6b50a6707aa8f8316", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72305c997f2cec414fe6f8c946172f83", "Arcadia Corporation, Dennis Caswell", "AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "724613effaf7743cbcd695fab469c2a8", "", "", "Super-Ferrari (Unknown)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "728152f5ae6fdd0d3a9b88709bee6c7a", "Spectravideo, Mark Turmell", "SA-217", "Gas Hog (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72876fd7c7435f41d571f1101fc456ea", "Quelle", "688.383 9", "Die Ente und der Wolf (1983) (Quelle) (PAL)", "AKA Pooyan", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72a46e0c21f825518b7261c267ab886e", "Xonox - K-Tel Software - Computer Magic", "99005, 6220, 6250", "Robin Hood (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72a5b5052272ac785fa076709d16cef4", "", "", "KC Munckin (29-01-2003) (J. Parlee)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72a63bcb5eb31bd0fd5e98ed05125ec1", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72bda70c75dfa2365b3f8894bace9e6a", "Thomas Jentzsch", "", "Atlantis (TJ) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72d0acb5de0db662de0360a6fc59334d", "", "", "Cosmic Ark (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72db1194b1cc7d45b242f25eb1c148d3", "", "", "Pac-Man (1981) (Atari) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72fd08deed1d6195942e0c6f392e9848", "HES", "0701-406", "2 Pak Special - Wall Defender, Planet Patrol (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "72ffbef6504b75e69ee1045af9075f66", "Atari, Richard Maurer - Sears", "CX2632 - 49-75153", "Space Invaders (1980) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73158ea51d77bf521e1369311d26c27b", "Zellers", "", "Challenge (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73521c6b9fed6a243d9b7b161a0fb793", "Atari, Tom Reuterdahl", "CX26163P", "Miniaturer Golf (32 in 1) (1988) (Atari) (PAL)", "AKA Miniature Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "736388d73198552d77d423962000006f", "Dactari", "", "Tennis (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73a710e621d44e97039d640071908aef", "", "", "Barber Pole Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73aa02458b413091ac940c0489301710", "Rainbow Vision - Suntek", "SS-016", "Boom Bang (1983) (Rainbow Vision) (PAL)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73b4e8f8b04515d91937510e680214bc", "", "", "Rubik's Cube Demo 3 (24-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73c545db2afd5783d37c46004e4024c2", "CBS Electronics - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "4L1767, 4L1768, 4L1769, 4L1770", "Smurf - Schtroumpfs (1983) (CBS Electronics) (PAL)", "Pitufo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73c839aff6a055643044d2ce16b3aaf7", "Activision, Alan Miller - Ariola", "EAX-016, PAX-016 - 711 016-725", "StarMaster (1982) (Activision) (PAL)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73cb1f1666f3fd30b52b4f3d760c928f", "", "", "Mines of Minos (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "73e66e82ac22b305eb4d9578e866236e", "Jone Yuan Telephonic Enterprise Co", "", "Unknown Datatech Game (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "73efa9f3cbe197f26e0fb87132829232", "CCE", "C-858", "Tennis (1983) (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "74023e0f2e739fc5a9ba7caaeeee8b6b", "Jone Yuan Telephonic Enterprise Co", "", "Fishing Derby (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "740a7fa80f52cc7287ba37677afb6b21", "", "", "Double Dragon (PAL) (Genesis)", "Genesis controller (C is jumpkick)", "Hack of Double Dragon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "740b47df422372fbef700b42cea4e0bf", "", "", "Dizzy Wiz (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "740f39e71104e90416c29a73560b9c6b", "Atari", "TE016643", "Diagnostic Test Cartridge 2.6P (1982) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7412f6788087d7e912c33ba03b36dd1b", "AtariAge, Omegamatrix", "", "Venture Reloaded (2019) (AtariAge) (Hack)", "Transformative hack of Venture", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "742de93b8d849220f266b627fbabba82", "", "", "SCSIcide (25-02-2001) (Chris Wilkson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7450ae4e10ba8380c55b259d7c2b13e8", "", "", "Register Twiddler Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7454786af7126ccc7a0c31fcf5af40f1", "", "", "Phantom Tank (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7465b06b6e25a4a6c6d77d02242af6d6", "Atari", "CX26193", "8 in 1 (01-16-92) (Atari) (Prototype)", "Game 2 is Centipede, but doesn't work", "Prototype", "", "", "8IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7481f0771bff13885b2ff2570cf90d7b", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "749fec9918160921576f850b2375b516", "Spectravision - Spectravideo", "SA-205", "China Syndrome (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "74d072e8a34560c36cacbc57b2462360", "Sancho - Tang's Electronic Co.", "TEC002", "Seahawk (1982) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "74ebaca101cc428cf219f15dda84b6f8", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "74f623833429d35341b7a84bc09793c0", "Zellers", "", "Radar (Zellers)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75028162bfc4cc8e74b04e320f9e6a3f", "Atari, Greg Easter, Mimi Nyden", "CX26107", "Snow White (02-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7511c34518a9a124ea773f5b0b5c9a48", "", "", "Donkey Kong (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75169c08b56e4e6c36681e599c4d8cc5", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5666", "Astroblast (1982) (M Network)", "Can also use left joystick", "Uncommon", "", "", "", "", "", "", "", "PADDLES", "", "YES", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "752da1c0acd7d132ccfb0b1067f53cf6", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "753375d183c713cfa0aa7298d1f3067b", "Arcadia Corporation, Steve Hales, Stephen Harland Landrum", "AR-4102", "Suicide Mission (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7550b821ee56fb5833dca2be88622d5a", "", "", "Multiple Moving Objects Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75511bb694662301c9e71df645f4b5a7", "Activision, Bob Whitehead - Ariola", "EAG-011, PAG-011 - 711 011-715", "Stampede (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "755fed16b48e81de05130708a905d00d", "SnailSoft", "", "Comitoid beta 3 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "756ca07a65a4fbbedeb5f0ddfc04d0be", "Atari, Jim Huether", "CX2629, CX2629P", "Sky Diver (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7574480ae2ab0d282c887e9015fdb54c", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1984) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7576dd46c2f8d8ab159d97e3a3f2052f", "Goliath - Hot Shot", "83-112", "Time Machine (1983) (Goliath) (PAL)", "AKA Asteroid Fire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "757f529026696e13838364dea382a4ed", "Activision, David Crane - Ariola", "EAX-014, PAX-014, EAX-014-04B, EAX-014-04I - 711 014-720", "Grand Prix (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75893a9dc5de4b91cc426959b82a1da0", "Champ Games", "CG-02-P", "Conquest Of Mars (2010) (PAL60)", "Rev 2 release", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75a303fd46ad12457ed8e853016815a0", "ZiMAG - Emag - Vidco", "715-111 - GN-060", "Immies & Aggies (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75b22fdf632d76e246433db1ebccd3c4", "", "", "Skeleton+ (05-05-2003) (Eric Ball) (PAL)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75b557be7f08db84ec5b242207b9f241", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75e276ba12dc4504659481c31345703a", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75e8d8b9e9c5c67c2226dbfd77dcfa7d", "", "", "2600 Digital Clock (V b1) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75ea128ba96ac6db8edf54b071027c4e", "Atari, David Crane", "CX26163P", "Slot Machine (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "75ea60884c05ba496473c23a58edf12f", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari) (PAL) [a]", "ROM must be started in bank 0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "75ee371ccfc4f43e7d9b8f24e1266b55", "Atari, Greg Easter, Mimi Nyden", "CX26107", "Snow White (11-09-1982) (Atari) (Prototype)", "ROM must be started in bank 0", "Prototype", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7608abdfd9b26f4a0ecec18b232bea54", "Atari, Bob Whitehead", "CX26163P", "NFL Football (32 in 1) (1988) (Atari) (PAL)", "AKA Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7623a639a6fffdb246775fe2eabc8d01", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7628d3cadeee0fd2e41e68b3b8fbe229", "Atari", "CX26163P", "Fishing Derby (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7648e72a5b5899076688df18a1ddcf72", "CBS Electronics, Richard K. Balaska Jr., Andy Frank, Stuart Ross", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics) (Prototype)", "Black Box", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "764ce6801f28a9ad36f11de3e57c053b", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666", "RealSports Volleyball (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76809eb1ee0db8a318308a5cdda0f4e2", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (1983) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "769ddc995dbb9edb8167efcea9f34a7c", "", "", "H.E.R.O. (Genesis)", "Genesis controller (B is laser, C is dynamite)", "Hack of H.E.R.0.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76a9bf05a6de8418a3ebc7fc254b71b4", "VideoSoft, Jerry Lawson, Dan McElroy", "VS1008", "Color Bar Generator (1984) (VideoSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76c685d1a60c0107aa54a772113a2972", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (3 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76c88341017eae660efc6e49c4b6ab40", "", "", "Indiana Pitfall (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76ee917d817ef9a654bc4783e0273ac4", "Otto Versand", "311377", "Fox & Goat (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Nuts", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76f53abbbf39a0063f24036d6ee0968a", "M Network, David Akers, Joe 'Ferreira' King, Patricia Lewis Du Long, Jeff Ratcliff - INTV", "MT7045", "Bump 'n' Jump (1983) (M Network)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "76f66ce3b83d7a104a899b4b3354a2f2", "UA Limited", "", "Cat Trax (1983) (UA Limited) (1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "77057d9d14b99e465ea9e29783af0ae3", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision)", "AKA Drag Strip", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7732e4e4cc2644f163d6650ddcc9d9df", "HES", "771-333", "2 Pak Special - Challenge, Surfing (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7761418d46af069b8cd80c29fe6cd814", "Dion Olsthoorn", "RetroN 77 edition", "Amoeba Jump (R77) (DionoiD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7778ac65d775a079f537e97cbdad541c", "", "", "Spider Fighter (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "777aece98d7373998ffb8bc0b5eff1a2", "", "", "2600 Collison Demo 2 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "77887e4192a6b0a781530e6cf9be7199", "Atari", "CX2604", "Space War (1978) (Atari) [b1]", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "77be57d872e3f5b7ecf8d19d97f73281", "", "", "Basketball (208 in 1) (Unknown) (PAL)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "77cd9a9dd810ce8042bdb9d40e256dfe", "Kyle Pittman", "", "Evil Dead (2003) (Kyle Pittman) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "77d0a577636e1c9212aeccde9d0baa4b", "Atari, Joe Decuir", "CX2621, CX2621P", "Video Olympics (1977) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "PADDLES_IAXDR", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "78297db7f416af3052dd793b53ff014e", "", "", "Poker Squares (V0.17) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7836794b79e8060c2b8326a2db74eef0", "", "", "RIOT RAM Test (26-11-2002) (Dennis Debro)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "784176346e9422733d55c427230e5bad", "Activision, Alex DeMeo", "", "Title Match Pro Wrestling (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "784abfdb31d5341e5bd404d8d2a71c3b", "Alessandro Ciceri", "", "MagiCard (TV format conversion) (alex_79) (PAL)", "MagiCard PAL conversion hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7860716fa5dbc0fffab93fb9a4cb4132", "", "", "Hangman Monkey Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7867ee819b53d69cfcfe740f7ddca574", "Arcadia Corporation, Dennis Caswell", "1 AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "787ebc2609a31eb5c57c4a18837d1aee", "Prescott", "", "Vault Assault (19xx) (Prescott)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "78821ef76ebc3934850d1bc1b9e4f4b0", "HES - Activision", "542", "Hot Action Pak - Ghostbusters, Tennis, Plaque Attack (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "78963290052fd17c6c7998305ab3a6a0", "", "", "Push (V0.08) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "78b84cfb1c57b0488d674d2374e656e6", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "78c2de58e42cd1faac2ea7df783eaeb3", "", "", "Fu Kung! (V0.07) (25-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79004f84bdeee78d142e445057883169", "CCE", "C-830", "Planet Patrol (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "791bc8aceb6b0f4d9990d6062b30adfa", "Activision, David Crane - Ariola", "EAX-018, EAX-018-04B, EAX-018-04I - 711 018-725", "Pitfall! (1982) (Activision) (PAL)", "Abenteuer im Urwald (Jungle Runner)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "791c88eca9836af8c34bf32b07cb58a7", "SpiceWare - Darrell Spice Jr.", "SW-05", "Stay Frosty 2 (PAL60)", "AtariAge Holiday Greetings 2014", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7926083ad423ed685de3b3a04a914315", "Barry Laws Jr.", "", "Face Invaders 2 (Barry Laws Jr.) (Hack)", "Hack of Astroblast", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "792b1d93eb1d8045260c840b0688ec8f", "Kroko", "", "3E Bankswitch Test (TIA @ $00)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7972e5101fa548b952d852db24ad6060", "Atari - Sears", "CX2627 - 6-99841", "Human Cannonball (1979) (Atari)", "AKA Cannon Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "798b8921276eec9e332dfcb47a2dbb17", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari) (PAL) [a]", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "798cc114f1623c14085868cd3494fe8e", "", "", "Pins Revenge (Atari Freak 1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7991e1797e5e9f311fd957e62d889dff", "Joe Grand", "", "SCSIcide (v1.1) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "7996b8d07462a19259baa4c811c2b4b4", "", "", "Math Gran Prix (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79ab4123a83dc11d468fb2108ea09e2e", "Activision - Cheshire Engineering, David Rolfe, Larry Zwick", "AZ-037-04", "Beamrider (1984) (Activision)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79b649fb812c50b4347d12e7ddbb8400", "", "", "Red Pong Number 2 Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "79c27f90591e3fdc7d2ed020ecbedeb3", "CCE", "C-815", "Seaquest (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79d4af56036ec28f298cad964a2e2494", "", "", "Hangman Pac-Man Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79d6f61da3c64688ac8e075667f8a39f", "", "", "Tie-Fighters (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79e5338dbfa6b64008bb0d72a3179d3c", "M Network - INTV, David Akers, Patricia Lewis Du Long", "MT4313", "Star Strike (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "79fcdee6d71f23f6cf3d01258236c3b9", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673, CX2673P", "Phoenix (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a09299f473105ae1ef3ad6f9f2cd807", "Atari, Steve Wright", "CX2616P", "Pele's Soccer (1981) (Atari) (PAL)", "AKA Pele's Championship Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a2af383014f5d810ad26d322823549d", "", "", "FlickerSort Demo (20-04-2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a5463545dfb2dcfdafa6074b2f2c15e", "20th Century Fox Video Games - Sirius Software, Mark Turmell", "11007", "Turmoil (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a63d7ea3f2851bcf04f0bb4ba1a3929", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (3 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a64a8b727c8215d945e37d565ca95a5", "Atari, Warren Robinett", "CX2606", "Slot Racers (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a64b5a6e90619c6aacf244cdd7502f8", "Baroque Gaming (Brian Eno)", "", "Warring Worms (Beta 1) (2002) (Baroque Gaming)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a7f6ab9215a3a6b5940b8737f116359", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7a93d0c029eaa72236523eedc3f19645", "", "", "20 Sprites at Once Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ab0917107b6ec768a5ebaadf28c497a", "", "", "Santa's Helper (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "7ab210f448de518fa61a5924120ba872", "", "", "Fortress (20-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ab2f190d4e59e8742e76a6e870b567e", "Apollo, Larry Martin", "AP-2008", "Guardian (1982) (Apollo)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 65", "", "", "", "", "", "", "", "" }, + { "7ac4f4fb425db38288fa07fb8ff4b21d", "Goliath", "83-213", "Space Eagle (1983) (Goliath) (PAL)", "AKA Exocet", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ad257833190bc60277c1ca475057051", "Atari, Alan J. Murphy, Robert Zdybel", "CX2668", "RealSports Football (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7ad782952e5147b88b65a25cadcdf9e0", "Imagic, Dave Johnson", "720119-1A, 03211", "Kwibble (1983) (Imagic) (Prototype)", "AKA Quick Step! Beta", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7adbcf78399b19596671edbffc3d34aa", "Atari, Mimi Nyden, Joseph Tung", "CX26152", "Super Baseball (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7af40c1485ce9f29b1a7b069a2eb04a7", "Amiga - Video Soft", "3120", "Mogul Maniac (1983) (Amiga)", "Uses the Amiga Joyboard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b24bfe1b61864e758ada1fe9adaa098", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b33407b2b198af74906b936ce1eecbb", "King Atari", "", "Ghostbuster 2 (King Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7b3cf0256e1fa0fdc538caf3d5d86337", "CommaVid, Joseph Biel", "CM-009", "Stronghold (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b43c32e3d4ff5932f39afcb4c551627", "Syncro, Daniel Wolf", "", "Kamikaze Saucers (1983) (Syncro) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b4be337ac4d73eda75c848355f6f480", "Omegamatrix", "", "Star Wars Arcade (Atari Trak-Ball) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b5207e68ee85b16998bea861987c690", "Atari, Carol Shaw", "CX26163P", "3-D Tic-Tac-Toe (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b57318c489ff178f7ff500da1ec9e8c", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b6f3348dbf71ada88db0fdaf7feefe0", "", "", "3-D Corridor (Pink Spiral) (31-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b79beb378d1b4471def90ceccf413de", "", "", "Pitfall Cupcake (Hack)", "Hack of Pitfall", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b7b4ac05232490c28f9b680c72998f9", "Zellers", "", "Freeway (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b8a481e0c5aa78150b5555dff01f64e", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (05-12-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7b938c7ddf18e8362949b62c7eaa660a", "Atari, Bob Whitehead - Sears", "CX2603 - 99803, 49-75601", "Star Ship (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ba07d4ea18bf3b3245c374d8720ad30", "Starpath Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (Preview) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7bb286cb659d146af3966d699b51f509", "Atari - Axlon, Tod Frye", "CX26178", "Save Mary! (04-03-1989) (Atari) (Prototype)", "AKA Saving Mary", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7bc4fd254ec8c0a25a13f02fd3f762ff", "Retroactive", "", "Qb (V1.00) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7c00e7a205d3fda98eb20da7c9c50a55", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo", "AP-2004", "Lost Luggage (1982) (Apollo)", "AKA Airport Mayhem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7c4a499d343fca0cef2d59dd16af621a", "", "", "Poker Card Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7c757bb151269b2a626c907a22f5dae7", "TNT Games - Sculptured Software, Adam Clayton", "26192", "BMX Air Master (1989) (TNT Games) (PAL)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7c7a4a2d505c2d0c75337c44711d8d54", "Atari, Warren Robinett", "", "Elf Adventure (04-22-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7c9b3b8b25acf2fe3b8da834f69629c6", "", "", "I Robot (1984) (Atari) (Prototype) [!]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ca7a471d70305c673fedd08174a81e8", "Tim Snider", "", "Venture II (2001) (Tim Snider)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7cc77f6745e1f2b20df4a4327d350545", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ccf350354ee15cd9b85564a2014b08c", "", "", "Big Dig (13-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7cd379da92c93679f3b6d2548617746a", "", "", "Demo Image Series #5 - Clown (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7cd900e9eccbb240fe9c37fa28f917b5", "Jone Yuan Telephonic Enterprise Co", "", "Bi! Bi! (Jone Yuan) (PAL)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ced6709f091e79a2ab9575d3516a4ac", "Activision, Steve Cartwright - Ariola", "EAX-027 - 711 027-722", "Plaque Attack (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7cedffa0db65d610568b90aeca705ac6", "Atari, Rob Fulop - Sears", "CX2638 - 49-75166", "Missile Command (1981) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7cf3a9267cdb95aba91abc5838d61cc5", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d0b49ea4fe3a5f1e119a6d14843db17", "Gameworld, J. Ray Dettling", "133-008", "Frankenstein's Monster (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d1034bcb38c9b746ea2c0ae37d9dff2", "Atari, Brad Stewart", "", "Morse Code Tutor (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d3cdde63b16fa637c4484e716839c94", "CCE", "", "Road Runner (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d483b702c44ee65cd2df22cbcc8b7ed", "Atari, Warren Robinett", "", "Elf Adventure (05-25-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d5c3b7b908752b98e30690e2a3322c2", "Dactari - Milmar", "", "Freeway (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d726fa494f706784bafeb1b50d87f23", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (07-27-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d8287e8423a56d4f8cef10435d97179", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d903411807704e725cf3fafbeb97255", "Imagic, Rob Fulop", "720104-1A, 720104-1B, IA3204", "Cosmic Ark (Reaction) (1982) (Imagic) [selectable starfield]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d93071b3e3616093a6b5a98b0315751", "", "", "Gunfight 2600 - Music & Bugfixes 2 (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d940d749e55b96b7b746519fa06f2de", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (Preview) (1983) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7d9c96b215d1941e87b6fb412eb9204f", "", "", "Othello (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7da9de8d62fcdd3a2c545b2e720c2a61", "CommaVid, John Bronstein", "CM-001", "MagiCard (1981) (CommaVid) (4K)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7dbc8fa2e488e3f6b87fbe0f76c5b89f", "Ed Federmeyer", "", "Sound X (1996) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7dc03a1f56d0e6a8aae3e3e50d654a08", "", "", "Hozer Video Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7dcbfd2acc013e817f011309c7504daa", "Arcadia Corporation, Dennis Caswell", "AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7dd9c5284422f729066ab22a284c8283", "CCE", "C-833", "Target Practice (1983) (CCE) [a]", "AKA Carnival", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ded20e88b17c8149b4de0d55c795d37", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.26)", "", "New Release, supports BoosterGrip", "", "", "", "", "", "", "", "BOOSTERGRIP", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7dfd100bda9abb0f3744361bc7112681", "Telesys, Don Ruffcorn", "1006", "Demolition Herby (1983) (Telesys) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7e2fe40a788e56765fe56a3576019968", "Activision - Imagineering, Donald Hahn, Dan Kitchen", "AK-050-04", "Double Dragon (1989) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e464186ba384069582d9f0c141f7491", "PlayAround - J.H.M.", "206", "General Re-Treat (1982) (PlayAround) (PAL)", "AKA Custer's Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e4783a59972ae2cd8384f231757ea0b", "Atari - Imagineering, Dan Kichen", "CX26139P", "Crossbow (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e51a58de2c0db7d33715f518893b0db", "CBS Electronics, E.F. Dreyer, Ed Salvo", "4L 2738 0000", "Mountain King (1983) (CBS Electronics) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7e52a95074a66640fcfde124fffd491a", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673", "Phoenix (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e7c4c59d55494e66eef5e04ec1c6157", "Baroque Gaming (Brian Eno)", "", "Warring Worms (2002) (Baroque Gaming)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e8aa18bc9502eb57daaf5e7c1e94da7", "CBS Electronics - Roklan, Joe Hellesen, Joe Wagner", "M8774, M8794", "Wizard of Wor (1982) (CBS Electronics)", "Uses the Joystick Controllers (swapped)", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7e9da5cb84d5bc869854938fe3e85ffa", "Atari, Ian Shepard - Sears", "CX2604 - 6-99812, 49-75106", "Space War (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7e9f088e15b2af9ff3411991393e6b1f", "Atari - Roklan, Joe Gaucher", "CX2679", "RealSports Basketball (12-28-1982) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7eab0284a0cd1043461d446a08d08cec", "Jone Yuan Telephonic Enterprise Co", "", "Basic Math (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ead257e8b5a44cac538f5f54c7a0023", "Xonox, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7eaf009a892f03d90682dc1e67e85f07", "Fabrizio Zavagli", "", "Bounce! (18-03-2003) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7eafc9827e8d5b1336905939e097aae7", "Atari, Mark R. Hahn", "", "Elk Attack (1987) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7eba20c2291a982214cc7cbe8d0b47cd", "Imagic, Dave Johnson", "720119-1A, 03211", "Quick Step! (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ed61a18cebdeca0a93be1f5461731e5", "Dactari", "", "Skiing (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ed7130a6e4020161836414332b11983", "", "", "Fu Kung! (V0.05 Cuttle Card Compatible) (13-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7edc8fcb319b3fb61cac87614afd4ffa", "Activision, Alan Miller", "AG-003", "Checkers (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ef3ca08abde439c6ccca84693839c57", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix (1983) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "7ef74879d7cb9fa0ef161b91ad55b3bb", "CCE", "", "Vanguard (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f0209cfcc3d181715463f4d6451cecf", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (05-15-1983) (Atari) (Prototype)", "AKA RealSports Driving", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f07cd2e89dda5a3a90d3ab064bfd1f6", "Videospielkassette - Ariola", "PGP234", "Boxen (Ariola) (PAL)", "AKA Boxing", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f430c33044e0354815392b53a9a772d", "HES", "773-891", "2 Pak Special - Cavern Blaster, City War (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f525b07bc98080cc8950f7284e52ede", "Atari", "", "128-in-1 Junior Console (Chip 4 of 4) (1991) (Atari) (PAL)", "Actually contains only 16 games, not 32", "", "", "", "16IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f54fa6aa824001af415503c313262f2", "HES", "", "Boom Bang (HES) (PAL)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f6533386644c7d6358f871666c86e79", "CommaVid, Irwin Gaines", "CM-008", "Cakewalk (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f790939f7eaa8c47a246c4283981f84", "", "", "This Planet Sucks Demo 3 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7f819454734ddf93f83fefcffcd3e212", "Jone Yuan Telephonic Enterprise Co", "", "Outlaw (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7f9fbe3e00a21ea06e6ae5e0e5db2143", "", "", "Skate Boardin' (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7fcd1766de75c614a3ccc31b25dd5b7a", "PlayAround - J.H.M.", "203", "Knight on the Town (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "7fcd5fb59e88fc7b8473c641f44226c3", "CCE", "C-807", "Space Tunnel (1983) (CCE)", "AKA O Tunel Espacial", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ff53f6922708119e7bf478d7d618c86", "Suntek", "SS-032", "Walker (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "7ffc2d80fd49a124808315306d19868e", "Ishido", "", "Domino (Ishido) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "801ba40f3290fc413e8c816c467c765c", "Hozer Video Games", "", "Gunfight 2600 - Westward Ho! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "803393ed29a9e9346569dd1bf209907b", "Atari - GCC, Mark Ackerman, Tom Calderwood, Glenn Parker", "CX2684", "Galaxian (02-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "804ed85eadf1ce3e93721547cbea7592", "CCE", "", "Fishing Derby (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8055b9c2622136fd91edfea6df642daf", "Activision", "", "Unknown Activision Game #1 (1983) (Activision) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "805f9a32ef97ac25f999a25014dc5c23", "SnailSoft", "", "Balthazar (SnailSoft)", "AKA Babylon 5", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8068e07b484dfd661158b3771d6621ca", "Epyx, Steven A. Baker, Peter Engelbrite", "80561-00286", "California Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "807841df228ee8aab0a06ee639ce5a8a", "Coleco - Project Guild - GMA, Michael Green, Anthony R. Henderson, Gary Littleton", "2455", "Turbo (1982) (Coleco) (Prototype)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "807a8ff6216b00d52aba2dfea5d8d860", "John Payson", "", "Strat-O-Gems Deluxe (2005) (J. Payson)", "Uses the AtariVox controller", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "808c3b1e60ee0e7c65205fa4bd772221", "CCE", "", "Defender (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80cd42881e670e4b74a9ccd10d0d7b2e", "20th Century Fox Video Games - Sirius, Ed Hodapp", "11004", "Deadly Duck (1982) (20th Century Fox) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80cec82239913cb8c4016eb13749de44", "David Marli", "", "Invaders from Space by David Marli (Space Invaders Hack)", "Hack of Space Invaders (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80dcbe1b55f12be731a224a53ee4ad5f", "Bit Corporation", "R320", "Amidar (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80e1410ec98089e0733cc09e584dba4b", "Dynamics", "DY-293005", "Jumping Jack (1983) (Dynamics) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80e52315919bd8a8b82a407ccd9bb13f", "", "", "Euchre (Jul 28) (2002) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80e5400470ac788143e6db9bc8dd88cf", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (06-XX-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "80f7bf7418a462e8687ecefeaf6eb9c2", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8101efafcf0af32fedda4579c941e6f4", "", "", "Okie Dokie (4K) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81073d0377a2badef8d5e74fc44fc323", "Thomas Jentzsch", "", "Sadoom (TJ) (PAL60) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "8108162bc88b5a14adc3e031cf4175ad", "Suntek", "SS-030", "Skydiver (1983) (Suntek) (PAL)", "AKA Parachute", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8108ad2679bd055afec0a35a1dca46a4", "", "", "Maze Craze (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC", "", "", "", "", "", "", "" }, + { "810d8952af5a6036fca8d0c4e1b23db6", "Tiger Vision - Eram", "", "Keystone (Tiger Vision)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81254ebce88fa46c4ff5a2f4d2bad538", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81341f00b61ab37d19d1529f483d496d", "", "", "Fu Kung! (V0.04) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "813985a940aa739cc28df19e0edd4722", "Imagic, Bob Smith", "720000-201, 720102-1B, IA3201", "Star Voyager (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81414174f1816d5c1e583af427ac89fc", "Thomas Jentzsch", "", "Treasure Below (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "814210c0e121f7dbc25661b93c06311c", "", "", "Joustpong (16-09-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81591a221419024060b890665beb0fb8", "Atari, Carla Meninsky, Ed Riddle", "CX2611, CX2611P", "Indy 500 (1977) (Atari) (PAL)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "8190b403d67bf9792fe22fa5d22f3556", "", "", "Sky Diver (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "819aeeb9a2e11deb54e6de334f843894", "Atari, Gary Palmer", "CX2661", "Fun with Numbers (1980) (Atari)", "AKA Basic Math", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81a010abdba1a640f7adf7f84e13d307", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames)", "AKA Targ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "81b3bf17cf01039d311b4cd738ae608e", "CBS Electronics - Roklan, Joe Gaucher, Alex Leavens", "M8776, M8793", "Gorf (1982) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "81f4f0285f651399a12ff2e2f35bab77", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "822a950f27ff0122870558a89a49cad3", "", "", "Space Jockey (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82337e5fe0f418ca9484ca851dfc226a", "Thomas Jentzsch", "", "Robot City (V1.0) (Alpha) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "826481f6fc53ea47c9f272f7050eedf7", "Imagic, Dennis Koble", "720103-1A, IA3203", "Atlantis II (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "827a22b9dffee24e93ed0df09ff8414a", "CBS Electronics, Stuart Ross", "", "Wings (10-10-1983) (CBS Electronics) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8290daea8391f96d7c8e1482e184d19c", "Eckhard Stolberg", "", "Frame Timed Sound Effects (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82bf0dff20cee6a1ed4bb834b00074e6", "Suntek", "SS-035", "Panda (1983) (Quest) (Suntek) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82c25d1c35e6ac6f893d1d7c2fc2f9c8", "Atari, Larry Kaplan", "CX2628, CX2628P", "Bowling (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82de957d155fc041fc6afb8315a28550", "Coleco, Joseph Biel", "2457", "Venture (1982) (Coleco) (Prototype)", "2K", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82e7aab602c378cffdd8186a099e807e", "", "", "Space Robot (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "82efe7984783e23a7c55266a5125c68e", "CCE", "C-837", "Pizza Chef (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "834a2273e97aec3181ee127917b4b269", "Quelle", "043.151 0, 874.382 5", "Die hungrigen Froesche (1983) (Quelle) (PAL)", "AKA Frogs and Flies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "835759ff95c2cdc2324d7c1e7c5fa237", "20th Century Fox Video Games, Frank Cohen, Douglas 'Dallas North' Neubauer", "11011", "M.A.S.H (1983) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8372eec01a08c60dbed063c5524cdfb1", "", "", "Cross Force (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8388d6fe59c38c0b3a6ab2c58420036a", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (12-06-1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83b8c01c72306d60dd9b753332ebd276", "", "", "Bank Heist (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83bdc819980db99bf89a7f2ed6a2de59", "Atari, Carla Meninsky - Sears", "CX2637 - 49-75158", "Dodge 'Em (1980) (Atari) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83d15fb9843d9f84aa3710538403f434", "", "", "Gunfight 2600 - Release Candidate (2001) (MP) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83e1b9f22f29259679e1018bc04cc018", "Bit Corporation", "R320", "Fast Eddie (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83f05ececae8be59ba1e51135f4bdcbf", "", "", "Demo Image Series #13 - Mario (4K Interleaved Chronocolour) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83f50fa0fbae545e4b88bb53b788c341", "Atari, Larry Kaplan - Sears", "CX2643 - 6-99815", "Codebreaker (1978) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "83fafd7bd12e3335166c6314b3bde528", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00251", "Winter Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "840a5a2eaea24d95d289f514fd12f9bb", "", "", "GBImprov (Hack)", "Hack of Ghostbusters", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "841057f83ce3731e6bbfda1707cbca58", "Champ Games", "CG-04-N", "Super Cobra Arcade (NTSC)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "841b7bc1cad05f5408302308777d49dc", "Activision", "", "Unknown Activision Game (10-22-1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "84290e333ff7567c2380f179430083b8", "Imagic, Dave Johnson", "13211, EIX-004-04I", "Quick Step! (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "843435eb360ed72085f7ab9374f9749a", "Joe Grand", "", "SCSIcide (1.31) (Joe Grand)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "84535afb9a69712ec0af4947329e08b8", "CCE", "C-868", "Bingo (1983) (CCE) (PAL)", "AKA Dice Puzzle", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8454ed9787c9d8211748ccddb673e920", "Froggo", "FG1002", "Spiderdroid (1987) (Froggo)", "AKA Amidar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8490e1014c2baa0d3a3a08854e5d68b3", "Xonox, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "84db818cd4111542a15c2a795369a256", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "850ffd5849c911946b24544ea1e60496", "", "", "Invasion (07-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "851cc1f3c64eaedd10361ea26345acea", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85227160f37aaa29f5e3a6c7a3219f54", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8530caaaf40acbdcd118c282b5f8a37a", "", "", "This Planet Sucks Demo 2 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8538c5e3ee83267774480649f83fa8d6", "", "", "Escape Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "853c11c4d07050c22ef3e0721533e0c5", "", "", "Oink! (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85470dcb7989e5e856f36b962d815537", "Atari - Sculptured Software, Inc., Steve Aguirre", "CX26162", "Fatal Run (1989) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85478bb289dfa5c63726b9153992a920", "", "", "Candi (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "854b68b93e7123a3be42b5a2a41f75d7", "Atari, Carol Shaw", "CX2618, CX2618P", "3-D Tic-Tac-Toe (1980) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85502d69fe46b7f54ef2598225678b47", "Jone Yuan Telephonic Enterprise Co", "", "Super-Ferrari (Jone Yuan)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85564dd0665aa0a1359037aef1a48d58", "ITT Family Games", "554-33 367", "Laser Base (1983) (ITT Family Games) (PAL) [a]", "AKA The End of the World (Perry Rhodan-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8556b42aa05f94bc29ff39c39b11bff4", "Atari, Craig Nelson - Sears", "CX2617 - 49-75183", "Backgammon (1979) (Atari)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 80", "", "", "", "", "", "", "", "" }, + { "855a42078b14714bcfd490d2cf57e68d", "Atari, Suki Lee", "CX26113", "Miss Piggy's Wedding (1983) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8597f66dd37d9c855663804669d69d7a", "Tigervision, Warren Schwader", "7-003", "Threshold (1982) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85a4133f6dcf4180e36e70ad0fca0921", "CCE", "C-827", "Chopper Command (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85b1bca93e69f13905107cc802a02470", "Atari, Craig Nelson", "CX2617, CX2617P", "Backgammon (1979) (Atari) (PAL)", "Uses the Paddle Controllers", "Extremely Rare", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 80", "", "", "", "", "", "", "", "" }, + { "85bbefb90e16bf386b304c1e9a1f6084", "Champ Games", "CG-02-P", "Conquest Of Mars (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85e48d68c8d802e3ba9d494a47d6e016", "", "", "Ship Demo (V 15) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "85e564dae5687e431955056fbda10978", "Milton Bradley Company - Renaissance Technology, Ty Roberts", "4362", "Survival Run (1983) (Milton Bradley)", "AKA Cosmic Commander", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "86128001e69ab049937f265911ce7e8a", "Apollo - Games by Apollo, Steve Stringfellow", "AP-2005", "Lochjaw (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8619da7f6796cedff59e5aa20712fb4e", "Thomas Jentzsch", "", "Sadistroids (v1.2) (2003) (Thomas Jentzsch)", "Supports Driving Controller in right port", "", "", "", "", "", "", "", "", "", "DRIVING", "", "", "", "", "", "", "YES", "30", "", "", "", "" }, + { "862cf669cbced78f9ed31a5d375b2ebe", "", "", "Gunfight 2600 - Flicker acceptance (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8644352b806985efde499ae6fc7b0fec", "CCE", "C-801", "Mr. Postman (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8654d7f0fb351960016e06646f639b02", "Home Vision, R.J.P.G. - Gem International Corp. - VDI", "VCS83106", "Ski Hunt (1983) (Home Vision) (PAL)", "AKA Skiiing Hunt", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "866e5150c995c4ae5172e5207ba948c7", "Canal 3 - Intellivision", "", "Stampede (Canal 3) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "869abe0426e6e9fcb6d75a3c2d6e05d1", "", "", "Stampede (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "86b4aa76bbeb70e1a4f9211a9880ba8e", "", "", "Incoming (1 Player Version) (05-11-2002) (Ben Larson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8712cceec5644aacc2c21203d9ebe2ec", "Retroactive", "", "Qb (V0.10) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8726c17ee7b559cb7bf2330d20972ad0", "", "", "Cave Demo (21-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "873fb75a7788ba0f4ae715229a05545e", "", "", "Euchre (Improved Colors) (PAL) (26-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8747ba79cd39fa83a529bb26010db21b", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL) [different speed and colors]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8749a0d088df25218c149dc325abc7ca", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a5]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "874c76726f68c166fcfac48ce78eef95", "", "", "Red Pong Number 2 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8764462d7d19a33b0717af22b99fc88f", "CCE", "", "Sky Jinks (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "87662815bc4f3c3c86071dc994e3f30e", "Intellivision Productions - M Network, Patricia Lewis Du Long, Stephen Tatsumi", "", "Swordfight (1983) (Intellivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "876a953daae0e946620cf05ed41989f4", "Retroactive", "", "Qb (V2.08) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "877a5397f3f205bf6750398c98f33de1", "Erik Eid", "", "Euchre (Beta) (PAL) (12-09-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8786c1e56ef221d946c64f6b65b697e9", "20th Century Fox Video Games, David Lubar", "11015", "AKA Space Adventure", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8786f229b974c393222874f73a9f3206", "Activision, Larry Miller - Ariola", "EAX-021, EAX-021-04I - 711 021-720", "Spider Fighter (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8786f4609a66fbea2cd9aa48ca7aa11c", "Goliath", "5", "Open Sesame (1983) (Goliath) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "87b460df21b7bbcfc57b1c082c6794b0", "Dennis Debro", "", "Climber 5 (20-03-2003) (Dennis Debro)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "87b6a17132fc32f576bc49ea18729506", "Atari, Andrew Fuchs, Courtney Granner, Jeffrey Gusman, Mark R. Hahn", "CX2690", "Pengo (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "87bea777a34278d29b3b6029833c5422", "Thomas Jentzsch", "", "Polaris (1983) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "87e79cd41ce136fd4f72cc6e2c161bee", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "87f020daa98d0132e98e43db7d8fea7e", "20th Century Fox Video Games - Sirius, David Lubar", "11001", "Worm War I (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "883258dcd68cefc6cd4d40b1185116dc", "Activision, David Crane - Ariola", "EAZ-030, EAZ-030-04B, EAZ-030-04I - 711 030-725", "Decathlon (1983) (Activision) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8874b68751fd2ba6d3306a263ae57a7d", "Eric Mooney", "", "Invaders by Erik Mooney (Alpha 1) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8885d0ce11c5b40c3a8a8d9ed28cefef", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner - Sears", "CX2608 - 49-75165", "Super Breakout (1982 - 1981) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "888debb162d7d1ae71025b4ab794257f", "", "", "Interleaved ChronoColour - Nude Art (17-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88a6c9c88cb329ee5fa7d168bd6c7c63", "CCE", "C-1007", "Jungle Hunt (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88d300a38bdd7cab9edad271c18cd02b", "Funvision - Fund. Int'l Co.", "", "Pac Kong (Funvision) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88d7b6b3967de0db24cdae1c7f7181bd", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88d8a1accab58cf1abb043613cf185e9", "Ultravison", "", "Sabotage (Ultravison)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88dce4037471424bb38ab6841aaa8cab", "", "", "Double-Height 6-Digit Score Display (Two Background Color Change) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88ed87c011f699dd27321dbe404db6c8", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "88f74ec75ef696e7294b7b6ac5ca465f", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision) (16K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8905d54f48b8024fc718ed643e9033f7", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (05-24-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "890c13590e0d8d5d6149737d930e4d95", "Atari, David Crane - Sears", "CX2605 - 6-99822, 49-75109", "Outlaw (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8917f7c1ac5eb05b82331cf01c495af2", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8933976f2029c0d8492ebd8f4eb21492", "", "", "Synthcart Plus (09-02-2003) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8953bc11352d794431d3303e31d3b892", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (02-17-1983) (Tigervision) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "896ec58f26e930e02f5e4f046602c3a1", "", "", "Synthcart (Beta) (2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "898143773824663efe88d0a3a0bb1ba4", "Activision - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "AZ-033, AZ-033-04", "Space Shuttle (1983) (Activision) [FE]", "A Journey Into Space", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "898748d5eaac3164b0391a64ae1e0e32", "", "", "Hangman Man 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "898b5467551d32af48a604802407b6e8", "Bit Corporation", "PG208", "Snail Against Squirrel (1983) (BitCorp) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "89a65b83203980d5d4d60f52a584a5b8", "", "", "Marble Craze (PAL) (02-02-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "89a68746eff7f266bbf08de2483abe55", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1984) (Atari)", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "89afff4a10807093c105740c73e9b544", "", "", "Pooyan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "89eaba47a59cbfd26e74aad32f553cd7", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2001", "Spacechase (1982) (Apollo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a159ee58b2f0a54805162984b0f07e5", "Atari - Sculptured Software, Inc., Steve Aguirre", "CX26162", "Fatal Run (1989) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a183b6357987db5170c5cf9f4a113e5", "Atari - Roklan, Joe Gaucher", "CX2679", "RealSports Basketball (01-11-1983) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a42e2c7266439d8997a55d0124c912c", "", "", "Hangman Invader Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a49cf1785e3dea2012d331a3ad476e1", "", "", "Boulderdash (10 Blocks Wide) (02-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a6c84f481acf42abcb78ba5064ad755", "128-in-1 Junior Console", "", "Street Racer (128-in-1 Junior Console) (PAL) (4K)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 75", "", "", "", "", "", "", "", "" }, + { "8a8e401369e2b63a13e18a4d685387c6", "Activision, David Crane - Ariola", "EAG-008, PAG-008, EAG-008-04I - 711 008-720", "Laser Blast (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8a9d874a38608964f33ec0c35cab618d", "Chris Cracknell", "", "Rescue Bira Bira (Chris Cracknell)", "Hack of Jungle Fever", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8a9d953ac3db52a313a90d6a9b139c76", "", "", "Hangman Invader Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8aad33da907bed78b76b87fceaa838c1", "Atari, Larry Kaplan", "CX26163P", "Air-Sea Battle (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ac18076d01a6b63acf6e2cab4968940", "Atari, Dan Hitchens, Mimi Nyden", "CX2685", "Gravitar (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8af58a9b90b25907da0251ec0facf3b8", "Jone Yuan Telephonic Enterprise Co", "", "Cosmic Swarm (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8b04e9d132b8e30d447acaa6bd049c32", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8b40a9ca1cfcd14822e2547eaa9df5c1", "Parker Brothers - Western Technologies, Dave Hampton, Tom Sloper", "931517", "Q-bert (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8b504b417c8626167a7e02f44229f0e7", "Retroactive", "", "Qb (V1.00) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8b556c3d9ca8e5e6e665bd759b93ffae", "", "", "Synthcart (2002) (Paul Slocum) (PAL) [!]", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8b5b1e3a434ebbdc2c2a49dc68f46360", "CBS Electronics - Woodside Design Associates - Imaginative Systems Software, Garry Kitchen", "4L1700, 4L1701, 4L1702, 4L1802, 4L2274", "Donkey Kong (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8b7ca29a55432f886cee3d452fb00481", "Starpath Corporation, Stephen H. Landrum, Jon Leupp", "11 AR-4201", "Sword of Saros (1983) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8b8152d6081f31365406cb716bd95567", "Atari", "CX2626, CX2626P", "Miniature Golf (1979) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8b8789c6669a4cee86c579a65332f852", "Digivision", "", "Plaque Attack (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8bbfd951c89cc09c148bfabdefa08bec", "UA Limited", "", "Pleiades (1983) (UA Limited) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8bc0d2052b4f259e7a50a7c771b45241", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox) [a]", "AKA Thundarr the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8bd8f65377023bdb7c5fcf46ddda5d31", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8bebac614571135933116045204f0f00", "Thomas Jentzsch", "", "Missile Command (Trakball) (2002) (TJ) (PAL)", "Uses the Trakball Controller", "Homebrew", "", "", "", "", "", "", "", "TRAKBALL", "TRAKBALL", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8c103a79b007a2fd5af602334937b4e1", "Thomas Jentzsch", "", "Laser Base (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c136e97c0a4af66da4a249561ed17db", "", "", "Poker Squares (V0.27) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c146c61817edd376bc1354c7f1ddc63", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c1cc284edba691139d6626d062c606f", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (PAL60) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "8c2fa33048f055f38358d51eefe417db", "Home Vision - Gem International Corp. - VDI", "VCS83137", "Teddy Apple (1983) (Home Vision) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8c36ed2352801031516695d1eeefe617", "Epyx, Steven A. Baker, Tod Frye, Peter Engelbrite", "80561-00251", "Winter Games (1987) (Epyx) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c7e5e2329f4f4e06cbcc994a30fd352", "Data Age", "DA1004", "Airlock (1982) (Data Age) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c8a26ed57870daba8e13162d497bad1", "HES", "", "2 Pak Special - Dolphin, Oink (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c8b15b3259e60757987ed13cdd74d41", "Supergame", "71", "River Raid (1984) (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8c941fa32c7718a10061d8c328909577", "Digivision", "", "River Raid (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ccaa442d26b09139685f5b22bf189c4", "Retroactive", "", "Qb (V1.01) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8ccf63141a029603572d1056e772990e", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (NTSC) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8cd26dcf249456fe4aeb8db42d49df74", "Atari - Imagineering, Dan Kichen", "CX26139", "Crossbow (1988) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ce9126066f2ddd5173e9f1f9ce1494e", "Thomas Jentzsch", "", "Missile Command (Trakball) (2002) (TJ)", "Uses the Trakball Controller", "Homebrew", "", "", "", "", "", "", "", "TRAKBALL", "TRAKBALL", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8cf0d333bbe85b9549b1e6b1e2390b8d", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8d00a38f4c8f8800f1c237215ac243fc", "", "", "3-D Corridor (Green) (30-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8d1e2a6d2885966e6d86717180938f87", "Thomas Jentzsch", "", "Missile Command (Amiga Mouse) (2002) (TJ)", "Uses Amiga Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8d8b7d7b983f75debbdaac651e814768", "", "", "Demo Image Series #15 - Three Marios (PAL) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8d9a06101ebb0f147936356e645309b8", "", "", "Grid Pattern Demo 2 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8da51e0c4b6b46f7619425119c7d018e", "Atari - Imagineering, David Lubar", "CX26183", "Sentinel (1991) (Atari)", "Uses the Light Gun Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8db152458abaef3cfa7a4e420ddbda59", "", "", "Keystone Kapers (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8df4be9ddc54ac363b13dc57ceaf161a", "Scott Stilphen", "", "Asteroids SS (Scott Stilphen) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8e0ab801b1705a740b476b7f588c6d16", "Activision, David Crane", "AG-009, AG-009-04", "Freeway (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e42674972d6805068fc653e014370fd", "", "", "Skeleton (PAL) (15-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e48ea6ea53709b98e6f4bd8aa018908", "CBS Electronics, Stuart Ross", "", "Wings (06-03-1983) (CBS Electronics) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8e4cd60d93fcde8065c1a2b972a26377", "Imagic, Dan Oliver", "720118-2A, 13208, EIX-007-04I", "Laser Gates (1983) (Imagic) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e4fa8c6ad8d8dce0db8c991c166cdaa", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e512ad4506800458f99dec084fc2c64", "Bob Montgomery, Nathan Strum", "", "Reindeer Rescue (2005)", "2005 AtariAge Holiday Cart", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e7241bfc8380aac3c0ef1b6881cdded", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (09-01-81) (Atari) (Prototype)", "Time Freeze", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8e737a88a566cc94bd50174c2d019593", "Quelle", "343.173 1", "Feuerwehr im Einsatz (1983) (Quelle) (PAL)", "AKA Fire Fighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e822b39a71c84ac875f0107fb61d6f0", "", "", "Hangman Ghost Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e879aa58db41edb67cbf318b77766c4", "Thomas Jentzsch", "", "Cosmic Commuter (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8e887d1ba5f3a71ae8a0ea16a4af9fc9", "", "", "Skeleton (V1.1) (PAL) (24-10-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ed5a746c59571feb255eaa7d6d0cf98", "", "", "Carnival (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ed73106e2f42f91447fb90b6f0ea4a4", "Spectravision - Spectravideo", "SA-204", "Tapeworm (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8ee3f64dc0f349adc893fe93df5245d8", "", "", "Euchre (20-07-2001) (Eric Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8ef96ace4a1d6dfb65926c1e868b0188", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f33bce5ba1053dcf4cea9c1c69981e4", "", "", "Jawbreaker (Unknown) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f53a3b925f0fd961d9b8c4d46ee6755", "", "", "Astrowar (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f5ac5139419c5d49bacc296e342a247", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (12-22-1982) (Atari) (Prototype)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f60551db6d1535ef0030f155018c738", "", "", "Space War (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f613ea7c32a587d6741790e32872ddd", "", "", "Troll Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f88309afad108936ca70f8b2b084718", "Spectravision - Spectravideo - Quelle", "SA-203 - 413.223 9", "Cross Force (1982) (Spectravision) (PAL)", "AKA Kreuzfeuer (Cross Fire)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f90590dba143d783df5a6cff2000e4d", "", "", "Gopher (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8f98519a91dbbf4864f135a10050d9ed", "Silvio Mogno", "", "Rainbow Invaders (non-playable demo) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8fa47e5242776e841df7e708b12eb998", "", "", "Sea Hawk (Genesis)", "Genesis controller (C drops bomb)", "Hack of Sea Hawk", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8fbabaa87941cdf3a377c15e95bdb0f3", "", "", "Meteor Smasher (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8fe00172e7fff4c1878dabcf11bb8dce", "Quelle", "689.302 8", "Hili Ball (1983) (Quelle) (PAL)", "AKA Racquetball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "8febdd9142960d084ab6eeb1d3e88969", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "8fffc8f15bb2e6d24e211884a5479aa5", "Retroactive", "", "Qb (V1.00) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9007c3cbb55ce05ad7d1c34d4906750a", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (03-18-1983) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9048ccb7e0802cd8fa5bfc2609f292d8", "Tigervision, Robert H. O'Neil", "7-007", "Polaris (1983) (Tigervision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9057694dce8449521e6164d263702185", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90578a63441de4520be5324e8f015352", "Bit Corporation", "PGP204", "Open Sesame (4 Game in One) (1983) (BitCorp) (PAL)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9072c142728a3a3d994956d03bfacba2", "Fabrizio Zavagli", "", "Crash Dive (Fabrizio Zavagli) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90a3c3255f2a54225cdcb50831f8793a", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90b1799dddb8bf748ee286d22e609480", "", "", "Ship Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90b647bfb6b18af35fcf613573ad2eec", "AtariAge (Chris Walton)", "", "Juno First (2009)", "AtariVox supported", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "90ccf4f30a5ad8c801090b388ddd5613", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90d77e966793754ab4312c47b42900b1", "Imagic, Brad Stewart", "720105-2A, IA3400P, EIX-005-04I", "Fire Fighter (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "90f502cbf4438a95f69f848cef36eb64", "Digitel", "", "River Raid II (1985) (Digitel)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "910dd9bf98cc5bc080943e5128b15bf5", "", "", "Gunfight 2600 - Improved AI (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "911d385ee0805ff5b8f96c5a63da7de5", "Thomas Jentzsch", "", "Jammed (V0.1) (Demo) (2001) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "913d5d959b5021f879033c89797bab5e", "", "", "Robot Player Graphic (1996) (J.V. Matthews) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "914a8feaf6d0a1bbed9eb61d33817679", "Atari", "CX26163P", "Freeway Chicken (32 in 1) (1988) (Atari) (PAL)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91925abce3a29e33b6a8b81482f4f5af", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9193b6fff6897d43274741d4f9855b6d", "", "", "M.A.S.H (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91a3749ff7b7e72b7fa09e05396a0e7b", "", "", "Gunfight 2600 - Final Run Part 2 (2002) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91b007f33f9b790be64f57220ec52e80", "Jone Yuan Telephonic Enterprise", "", "Laser Blast (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91c2098e88a6b13f977af8c003e0bca5", "Atari - GCC", "CX2676", "Centipede (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91d1c82ceaf8af2add3973a3c34bc0cb", "", "", "Starfield Demo 1 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91f0a708eeb93c133e9672ad2c8e0429", "", "", "Oystron (V2.9) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "91fdb6541f70c40b16aabf8308123be8", "", "", "Interlacing Game (19-08-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9222b25a0875022b412e8da37e7f6887", "Panda", "106", "Dice Puzzle (1983) (Panda)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9245a84e9851565d565cb6c9fac5802b", "Bomb - Onbase", "CA282", "Great Escape (1983) (Bomb)", "AKA Asteroid Fire", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "927d422d6335018da469a9a07cd80390", "Activision, Carol Shaw - Ariola", "EAX-020, EAX-020-04B, EAX-020-04I - 711 020-720", "River Raid (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9281eccd7f6ef4b3ebdcfd2204c9763a", "Retroactive", "", "Qb (2.15) (Retroactive) (PAL)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9295570a141cdec18074c55dc7229d08", "Telegames", "7045 A015", "Bump 'n' Jump (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "929e8a84ed50601d9af8c49b0425c7ea", "Bit Corporation", "PG205", "Dancing Plate (1982) (BitCorp) (PAL)", "AKA Dishaster, Dancing Plates, Tanzende Teller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "92a1a605b7ad56d863a56373a866761b", "U.S. Games Corporation - Western Technologies, Dave Hampton", "VC2006", "Raft Rider (1983) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "92d1b6cb8a1b615266c4088a58464779", "Bit Corporation", "R320", "Fishing Derby (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "92d1f6ac179ebe5963868d6bc1bdda8d", "HES", "498", "Smash Hit Pak - Frogger, Boxing, Seaquest, Skiing, Stampede (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "92e72f7cc569584c44c9530d645ae04e", "Canal 3 - Intellivision", "", "Spider Fighter (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "931b91a8ea2d39fe4dca1a23832b591a", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9333172e3c4992ecf548d3ac1f2553eb", "Konami", "RC 101-X 02", "Strategy X (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93420cc4cb1af1f2175c63e52ec18332", "Tim Snider", "", "Blair Witch Project (Tim Snider) (Hack)", "Hack of Haunted House", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9364ad51c321e0f15c96a8c0aff47ceb", "Atari, Rob Fulop", "CX2638", "Missile Command (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "936ef1d6f8a57b9ff575dc195ee36b80", "", "", "Pac Kong (Unknown)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "936f555b4b1a2cd061b659ff63f4f5f2", "HES, David Lubar", "535", "My Golf (1990) (HES) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "937736d899337036de818391a87271e0", "Atari, Peter C. Niday", "CX26108", "Donald Duck's Speedboat (04-12-1983) (Atari) (Prototype)", "AKA Donald Duck's Regatta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "939ce554f5c0e74cc6e4e62810ec2111", "ZiMAG - Emag - Vidco", "711-111 - GN-020", "Dishaster (1983) (ZiMAG)", "AKA Dancing Plate", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "93acd5020ae8eb5673601e2edecbc158", "Chris Cracknell", "", "Video Time Machine (Chris Cracknell)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93b9229fc0ea4fb959d604f83f8f603c", "Thomas Jentzsch", "", "Amidar DS (Fast Enemies) (2003) (TJ) (Hack)", "Hack of Amidar", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93c4b910f7649b3e998bb6d8527c6f4a", "Sparrow - Enter-Tech, Paul Walters, Rick Harris, George Hefner, Barbara Ultis", "", "Arkyology (1983) (Sparrow) (Prototype) [fixed]", "Fix for un-initialized 'X' register", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93c52141d3c4e1b5574d072f1afde6cd", "Imagic, Mark Klein", "720112-1A, 03213", "Subterranea (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93c8d9d24f9c5f1f570694848d087df7", "Digivision", "", "Galaxian (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93c9f9239a4e5c956663dd7affa70da2", "Quelle", "626.610 0", "Billard (1983) (Quelle) (PAL)", "AKA Trick Shot", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "93db185c3b3dc382f3aecd6a2fea7fd9", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (PAL60) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93dc15d15e77a7b23162467f95a5f22d", "CCE", "", "Sky Jinks (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93e276172b521c4491097f8b1393eea7", "Atari", "", "Diagnostic Test Cartridge 4.2 (06-01-1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "93eb1795c8b1065b1b3d62bb9ec0ccdc", "JSK", "", "Custer's Viagra (JSK) (Hack)", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94102febc53b4a78342d11b645342ed4", "", "", "Joustpong (14-07-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9433770890f087bfcf3e50122694d8c0", "Omegamatrix", "", "Star Wars Arcade (Amiga Mouse) (Y Inverted) v4 (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9436b7ad131b5a1f7753ce4309ba3dee", "Kyle Pittman", "", "War of The Worlds (Kyle Pittman) (Hack)", "Hack of Defender", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "943798452ceba9357e2c56303cadb4f7", "Thomas Jentzsch, Paul Slocum", "", "Thrust+ Platinum (v1.28)", "", "New Release, supports BoosterGrip and Genesis (switched by Color/B+W)", "", "", "", "", "", "", "", "JOYSTICK", "DRIVING", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9446940866c9417f210f8552cf6c3078", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (PAL60) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94507dee401b0a072a481c00d7699ffe", "Thomas Jentzsch", "", "Missile Control - Atari Trak-Ball Hack v1.15 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9469d18238345d87768e8965f9f4a6b2", "CCE", "", "Ms. Pac-Man (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "947317a89af38a49c4864d6bdd6a91fb", "CBS Electronics, Bob Curtiss", "4L 2487 5000", "Solar Fox (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94b92a882f6dbaa6993a46e2dcc58402", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94d90f63678e086f6b6d5e1bc6c4c8c2", "Digivision", "", "Seaquest (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94e3fbc19107a169909e274187247a9d", "", "2402-044-01", "2-in-1 Freeway and Tennis (Unknown)", "", "", "", "", "2IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94e4c9b924286038527f49cdc20fda69", "Retroactive", "", "Qb (V2.12) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "94e7cc6342d11e508e7e8b2ddf53c255", "", "", "Missile Command (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "94ff6b7489ed401dcaaf952fece10f67", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-31-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "951e8cec7a1a1d6c01fd649e7ff7743a", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dark Chambers (1988) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9526e3db3bdfbc27989a9cbfd0ee34bf", "", "", "Atari Logo Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "95351b46fa9c45471d852d28b9b4e00b", "Atari, Tom Rudadahl", "CX26163P", "Golf (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "955c408265ad6994f61f9b66657bbae9", "", "", "Quadrun (Video Conversion) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "956496f81775de0b69a116a0d1ad41cc", "CCE", "", "Alien (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "956b99511c0f47b3a11d18e8b7ac8d47", "", "", "Bones (Arcade Golf Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "95956108289a917f80667eccd3ce98a9", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "95a69cf8c08ef1522b050529464f0bca", "", "", "Grid Pattern Demo 1 (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "95a89d1bf767d7cc9d0d5093d579ba61", "PlayAround - J.H.M.", "204", "Lady in Wading (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "95e1d834c57cdd525dd0bd6048a57f7b", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "95e542a7467c94b1e4ab24a3ebe907f1", "Suntek", "SS-021", "Dragon Defender (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "95fd6097dc27c20666f039cfe34f7c69", "", "", "Oh No! (Version 1) (17-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "961112b74a920a5242e233480326c356", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "962ffd3eaf865230a7a312b80e6c5cfd", "Imagic, Wilfredo 'Willy' Aguilar, Michael Becker, Rob Fulop", "13205", "Fathom (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "96662271ae50b6859017bffbdda75525", "Andrew Davie & Thomas Jentzsch", "", "Boulder Dash - Demo (2011)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "96670d0bf3610da2afcabd8e21d8eabf", "", "", "Boring Pitfall (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "966b11d3c147d894dd9e4ebb971ea309", "", "", "Marble Craze Song (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "966c955e4aaca7082d9ffb9a68e3f3ed", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9671b658286e276cc4a3d02aa25931d2", "", "", "Hangman Ghost Wordlist (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "968efc79d500dce52a906870a97358ab", "TNT Games - Sculptured Software, Adam Clayton", "26192", "BMX Air Master (1989) (TNT Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "969b968383d9f0e9d8ffd1056bcaef49", "Atari, Larry Kaplan", "CX2628, CX2628P", "Bowling (1979) (Atari) (PAL)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "96bcb3d97ce4ff7586326d183ac338a2", "", "", "Revenge of the Apes (Hack) [h2]", "Hack of Planet of the Apes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "96e798995af6ed9d8601166d4350f276", "20th Century Fox Video Games - Videa, David Ross", "11029", "Meltdown (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "96eccc2277043508a6c481ea432d7dd9", "Thomas Jentzsch", "", "Missile Command (Atari Mouse) (2002) (TJ) (PAL)", "Uses Atari ST Mouse Controller", "Homebrew", "", "", "", "", "", "", "", "ATARIMOUSE", "ATARIMOUSE", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "96f806fc62005205d851e758d050dfca", "", "", "Push (V0.05) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97184b263722748757cfdc41107ca5c0", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9718b85ac5a55cbc7348963c63ffa35a", "Robby", "", "Demon Attack (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "972486110933623039a3581db308fda6", "", "", "Xeno Plus (Hack)", "Hack of Xenophobe", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97327d6962f8c64e6f926f79cd01c6b9", "", "", "Jawbreaker (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "977294ae6526c31c7f9a166ee00964ad", "Atari - GCC, Douglas B. Macrae", "CX2677, CX2677P", "Dig Dug (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9784290f422e7aeeab4d542318bd9a1f", "AtariAge, Chris Walton", "1.0 (Release)", "Chetiry (2011) (AtariAge) (60k)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, + { "97842fe847e8eb71263d6f92f7e122bd", "Imagic, Wilfredo Aguilar, Michael Becker, Dennis Koble", "720113-1A, 03206", "Solar Storm (1983) (Imagic)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "97933c9f20873446e4c1f8a4da21575f", "", "", "Racquetball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "97a9bb5c3679d67f5c2cd17f30b85d95", "Atari", "", "Colors (1980) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97cd63c483fe3c68b7ce939ab8f7a318", "Thomas Jentzsch", "", "Robot City (V0.21) (15-09-2002) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97d0151beb84acbe82aa6db18cd91b98", "Steve Engelhardt", "", "Lunar Attack (2002) (Steve Engelhardt) (Hack)", "Hack of Z-Tack", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97d079315c09796ff6d95a06e4b70171", "Activision, Garry Kitchen", "AZ-032", "Pressure Cooker (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97e47512f89e79818d988d078dc90410", "Thomas Jentzsch", "", "Missile Control - Amiga Mouse Hack v1.15 (NTSC) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "97f4da9f1031486f4e588f1e53572e53", "SpiceWare - Darrell Spice Jr.", "", "Draconian", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9813b9e4b8a6fd919c86a40c6bda8c93", "Atari", "CX26177", "Ikari Warriors (1989) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9831efc7f4cb8ffb4df0082bab2f07a3", "Activision, Steve Cartwright - Ariola", "EAX-031, EAX-031-04B - 711 031-717", "Frostbite (1983) (Activision) (PAL) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9848b5ef7a0c02fe808b920a2ac566d2", "Skyworks Technology Inc.", "", "Baseball (2002) (Skyworks)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9853089672116117258097dbbdb939b7", "Hozer Video Games", "", "Gunfight 2600 - Cowboy Hair (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98555b95cb38e0e0b22b482b2b60a5b6", "", "", "Spinning Fireball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "98ba601a60172cb46c5bf9a962fd5b1f", "", "", "Gorilla Kong (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98ccd15345b1aee6caf51e05955f0261", "Retroactive", "", "Qb (V2.03) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "98e5e4d5c4dd9a986d30fd62bd2f75ae", "", "", "Air-Sea Battle (Unknown) (Hack) (4K)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98e6e34af45a0664597972c3bb31180f", "", "", "Space Instigators (V1.7) (17-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98e7caaab8ec237558378d2776c66616", "Bradford W. Mott", "", "HMOVE Test (Bradford W. Mott) (1998) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98ea10c47c13f1b3306c7b13db304865", "", "", "Jam Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98ec0fa4199b9c01f7b8fa3732e43372", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98ef1593624b409b9fb83a1c272a0aa7", "CCE", "C-831", "Cosmic Ark (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98f63949e656ff309cefa672146dc1b8", "Atari - Axlon, John Vifian", "CX26168", "Off the Wall (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "98fa3ad778a668a79449350de4b3b95b", "Thomas Jentzsch", "", "Thrust (V1.1) (2000) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9905f9f4706223dadee84f6867ede8e3", "HES", "", "Challenge (HES) (PAL)", "Surfer's Paradise if right difficulty = 'A'", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9912d06eea42200a198dd3e2be18c601", "Imagic, Michael Greene", "IA3312", "No Escape! (1982) (Imagic) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "991d57bbcd529ad62925098e0aec1241", "", "", "Gunfight 2600 - The Final Kernel (MP) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9945a22f60bbaf6d04a8d73b3cf3db75", "Activision, Dan Kitchen", "EAX-039-04B, EAX-039-04I", "Kung-Fu Master (1987) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9947f1ebabb56fd075a96c6d37351efa", "CBS Electronics", "4L 2737 0000", "Omega Race (1983) (CBS Electronics)", "Set right difficulty to 'A' for BoosterGrip in both ports", "", "", "", "", "", "A", "", "", "BOOSTERGRIP", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9962034ea7b3d4a905d0991804670087", "", "", "Grid Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9989f974c3cf9c641db6c8a70a2a2267", "Eckhard Stolberg", "", "Colours Selector (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "99a24d7bb31d49b720b422550b32c35f", "", "", "Hangman Ghost Biglist1 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "99ac89241365b692255ba95d745edd91", "Atari, Frank Hausman, Mimi Nyden, Steve Woita", "CX2686", "Quadrun (18-03-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "99f7c6c26046bbe95f1c604b25da8360", "SnailSoft", "", "Comitoid beta 2 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9a01115206f32eb0b539c7e5a47ccafa", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (07-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9a165c39af3f050fdee6583fdfcdc9be", "Zirok", "", "Mario Bros. (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9a21fba9ee9794e0fadd7c7eb6be4e12", "Atari - Imagineering, Dan Kitchen", "CX26177", "Ikari Warriors (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9a25b3cfe2bbb847b66a97282200cca2", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, + { "9a4274409216ff09ecde799f2a56ac73", "CCE", "C-801", "Mr. Postman (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ab72d3fd2cc1a0c9adb504502579037", "Epyx, Steven A. Baker, Peter Engelbrite", "80561-00286", "California Games (1987) (Epyx)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ad362179c2eea4ea115c7640b4b003e", "", "", "Barnstorming (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC50", "", "", "", "", "", "", "" }, + { "9ad36e699ef6f45d9eb6c4cf90475c9f", "Imagic, Dennis Koble", "720103-1A, 720103-1B, IA3203, IX-010-04", "Atlantis (1982) (Imagic)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9aeb5206c5bf974892a9cc59f1478db3", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9af615951e9719df2244bc77fc50cb95", "Dactari - Milmar", "", "Defender (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9afdfe1cff7f37f1c971fe3f0c900606", "Funvision - Fund. International Co.", "", "Plug Attack (Funvision)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9b150a42fc788960fbb4cbe250259ee2", "Kroko", "", "3E Bankswitch Test (TIA @ $40)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9b21d8fc78cc4308990d99a4d906ec52", "CCE", "C-838", "Immies & Aggies (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9b246683f44c963a50e41d6b485bee77", "", "", "Boring (PAL) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9bb136b62521c67ac893213e01dd338f", "Xonox - Beck-Tech", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9bd4e0d5f28ba6da417c26649171f8e4", "", "", "Hangman Pac-Man Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9be58a14e055b0e7581fc4d6c2f6b31d", "", "", "Adventure (Color Scrolling) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c27ef3bd01c611cdb80182a59463a82", "Arcadia Corporation, Kevin Norman", "AR-4103", "Killer Satellites (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c40bf810f761ffc9c1b69c4647a8b84", "", "", "2 in 1 - Frostbite, River Raid (Unknown)", "", "", "", "", "2IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c6d65bd3b477aace0376f705b354d68", "", "", "RPG Kernal (18-04-2003) (Paul Slocum) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9c6faa4ff7f2ae549bbcb14f582b70e4", "U.S. Games Corporation, Garry Kitchen, Paul Willson - Vidtec", "VC1002", "Sneak 'n Peek (1982) (U.S. Games)", "AKA Hide 'n Seek", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c6fd6ed3599978ab7b6f900484b9be6", "Andrew Wallace", "", "Laseresal 2002 (PAL60) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c729017dd2f9ccbadcb511187f80e6b", "", "", "J-Pac (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9c7fa3cfcaaafb4e6daf1e2517d43d88", "", "", "PIEROXM Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ca2deb61318eba4fb784d4bf7441d8b", "", "", "Purple Bar Demo 2 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9cbb07f1993a027bc2f87d5205457ec9", "", "", "Eckhard Stolberg's Scrolling Text Demo 1 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d0befa555f003069a21d2f6847ad962", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d1556ae5890398be7e3d57449774b40", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d2938eb2b17bb73e9a79bbc06053506", "Imagic, Michael Greene", "EIZ-002-04I", "Wing War (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d2f05d0fe8b2dfcf770b02eda066fc1", "", "", "Push (V0.06) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d33d31fb1de58c5460d8a67b57b36da", "", "", "Star Voyager (Genesis)", "Genesis controller (C is secondary lasers)", "Hack of Star Voyager", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d37a1be4a6e898026414b8fee2fc826", "M Network - INTV - APh Technological Consulting, David Rolfe", "MT5665", "Super Challenge Baseball (1982) (M Network)", "AKA Big League Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d4bc7c6fe9a7c8c4aa24a237c340adb", "Dennis Debro", "", "Climber 5 (16-04-2003) (Dennis Debro)", "For Philly Classic 4", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d522a3759aa855668e75962c84546f7", "Atari, Tom Rudadahl", "CX2634, CX2634P", "Golf (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9d7f04618bb4043f531d087e3aaa7ac8", "Parker Brothers, Larry Gelberg, Gary Goltz", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL) (16K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9de0d45731f90a0a922ab09228510393", "20th Century Fox Video Games - Sirius, Mark Turmell", "11003", "Fast Eddie (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9dec0be14d899e1aac4337acef5ab94a", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9e01f7f95cb8596765e03b9a36e8e33c", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9e135f5dce61e3435314f5cddb33752f", "Fabrizio Zavagli", "", "Space Treat Deluxe (2003)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9e192601829f5f5c2d3b51f8ae25dbe5", "PlayAround - J.H.M.", "201", "Cathouse Blues (1982) (PlayAround)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9e2c7299c69b602443d327c7dad51cbf", "Charles Morgan", "", "Xaxyrax Road (Charles Morgan) (Hack)", "Hack of Freeway", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9e437229136f1c5e6ef4c5f36178ed18", "Funvision - Fund. International Co.", "", "Grand Prize (Funvision)", "AKA Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9e5007131695621d06902ab3c960622a", "Sega", "", "Tac Scan (1983) (Sega) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "YES", "", "", "", "", "" }, + { "9e792a59f8795664cbaaff1ba152d731", "", "", "Bullet Demo (20-12-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9e904e2eaa471c050c491289b8b80f60", "", "", "How to Draw a Playfield II (1997) (Erik Mooney) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ea8ed9dec03082973244a080941e58a", "Eric Mooney, Piero Cavina", "", "INV+", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ec1b259a1bcffa63042a3c2b3b90f0a", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9eca521db1959156a115dee85a405194", "", "", "Fu Kung! (V0.08) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9ed0f2aa226c34d4f55f661442e8f22a", "", "", "Nuts (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9eeb40f04a27efb1c68ba1d25e606607", "Kyle Pittman", "", "Rambo II (2003) (Kyle Pittman) (Hack)", "Hack of Double Dragon", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9efa877a98dd5a075e058214da428abb", "Hozer Video Games", "", "SCSIcide (1.32) (Hozer Video Games)", "Uses the Paddle Controllers", "New Release", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "", "", "", "AUTO 65", "", "", "", "", "", "", "", "" }, + { "9efb4e1a15a6cdd286e4bcd7cd94b7b8", "20th Century Fox Video Games, John W.S. Marvin", "", "Planet of the Apes (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f2d58dce1b81c6ba201ed103507c025", "", "", "Fu Kung! (V0.02) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f48eeb47836cf145a15771775f0767a", "Atari, Warren Robinett", "CX2620", "Basic Programming (1979) (Atari)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9f5096a6f1a5049df87798eb59707583", "20th Century Fox Video Games, Mark Klein", "11036", "Entity, The (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f52271759f8a2004d207b2247ae0bb3", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (03-12-84) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9f59eddf9ba91a7d93bce7ee4b7693bc", "Thomas Jentzsch", "", "Montezuma's Revenge (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f8fad4badcd7be61bbd2bcaeef3c58f", "Parker Brothers, Charlie Heath", "PB5330", "Reactor (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "9f901509f0474bf9760e6ebd80e629cd", "Atari, Bob Whitehead - Sears", "CX2623 - 6-99819, 49-75108, 49-75125", "Home Run (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f93734c68f6479eb022cab40814142e", "", "", "Push (V0.07) (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9f982421b9b4320ede00fe4aa2e812f4", "Atari, Omegamatrix", "", "Super Breakout Menu (2020) (Hack)", "Hack of Super Breakout", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "9f9ee0f60c119c831e80694b6678ca1a", "Jeffry Johnston", "", "Radial Pong - Version 8 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9fa0c664b157a0c27d10319dbbca812c", "Chris Walton, Justin Hairgrove, Tony Morse", "", "Hunchy II (2005)", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "9fc2d1627dcdd8925f4c042e38eb0bc9", "Atari - GCC, John Allred, Mike Feinstein", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "E68E28752D3C54EDD3CCDA42C27E320C", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox)", "Genesis controller (B is jump and throw, C switches between players)", "Hack of Tomarc the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0028f057d496f22b549fd8deecc6f78", "Joe Grand", "", "SCSIcide Pre-release 6 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a00ec89d22fcc0c1a85bb542ddcb1178", "CCE", "C-1012", "Phoenix (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a00ee0aed5c8979add4c170f5322c706", "Barry Laws Jr.", "", "Egghead (Barry Laws Jr.) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0185c06297b2818f786d11a3f9e42c3", "", "", "International Soccer (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a025a8f83a42a4d6d46c4887e799bfac", "Hozer Video Games", "", "Gunfight 2600 - Descissions had to be made (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0297c4788f9e91d43e522f4c561b4ad", "Atari - CCW, Gary Stark", "CX26102", "Cookie Monster Munch (1983) (Atari) (PAL)", "Uses Kids/Keypad Controllers", "", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0563dd6d8215c38c488fbbd61435626", "", "", "Ship Demo (V 1501) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0675883f9b09a3595ddd66a6f5d3498", "Telegames - VSS", "6057 A227", "Quest for Quintana Roo (1988) (Telegames)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a075ad332942740c386f4c3814925ece", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (2 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0d502dc8b90b1d7daa5f6effb10d349", "", "", "Demo Image Series #5 - Sam (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a0e2d310e3e98646268200c8f0f08f46", "Atari, Ed Logg, Carol Shaw", "CX2639, CX2639P", "Othello (1981) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a100eff2d7ae61ca2b8e65baf7e2aae8", "David Marli", "", "Muncher (David Marli) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a11099b6ec24e4b00b8795744fb12005", "Activision - Bobco, Robert C. Polaro", "EAK-049-04B", "Rampage! (1989) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1403fef01641dcd3980cac9f24d63f9", "Dactari - Milmar", "", "Atlantis (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a14d8a388083c60283e00592b18d4c6c", "", "", "Tunnel Demo (28-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a15b5831a1fab52e4c416068c85ec011", "Hozer Video Games", "", "Gunfight 2600 - The Good, The Bad, The Ugly (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a174cece06b3abc0aec3516913cdf9cc", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (1980) (Sears) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1770ef47146ab7b12e2c4beccd68806", "Digitel", "", "Kaystone Kapers (1983) (Digitel)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a184846d8904396830951217b47d13d9", "Activision, Dan Kitchen", "AX-029", "Crackpots (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a189f280521f4e5224d345efb4e75506", "Atari - Thomas Jentzsch", "", "Obelix (1983) (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1bcbe0bfe6570da2661fc4de2f74e8a", "Imagic - Advanced Program Technology, Rob Fulop", "", "Actionauts (Microbots) (1984-2008) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1ca372388b6465a693e4626cc98b865", "Quelle", "176.543 7", "Der Vielfrass (1983) (Quelle) (PAL)", "AKA Fast Food", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1ead9c181d67859aa93c44e40f1709c", "American Videogame - Dunhill Electronics, Darrell Wagner, Todd Clark Holm, John Simonds", "", "Tax Avoiders (1986) (American Videogame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a1f9159121142d42e63e6fb807d337aa", "Quelle - Otto Versand", "700.223 1 - 781627", "Der moderne Ritter (1983) (Quelle) (PAL)", "AKA Fast Eddie", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a204cd4fb1944c86e800120706512a64", "Coleco, Rob Harris", "2511", "Smurfs Save the Day (1983) (Coleco)", "Uses the Kid Vid Controller", "", "", "", "", "", "", "", "", "", "KIDVID", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a20b7abbcdf90fbc29ac0fafa195bd12", "Quelle - Otto Versand", "719.383 2 - 649635, 781393, 781784, 986404", "Motocross (1983) (Quelle) (PAL)", "AKA Motorcross", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a20d931a8fddcd6f6116ed21ff5c4832", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a2170318a8ef4b50a1b1d38567c220d6", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) [a1]", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2276822c772f72073a8a40a72a1ca52", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (NTSC) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2424c1a0c783d7585d701b1c71b5fdc", "", "", "Video Pinball (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a25bb76e9e773117e567fd4300b1bb23", "", "", "Interleaved ChronoColour Demo (NTSC) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a28d872fc50fa6b64eb35981d0f4bb8d", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari) (4K)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a29df35557f31dfea2e2ae4609c6ebb7", "Atari", "", "Circus Atari (1980) (Atari) (Joystick)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a29fc854838e08c247553a7d883dd65b", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision) (16K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2a384d3a16d5be50afd12906f146827", "Bit Corporation", "R320", "Flash Gordon (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2aae759e4e76f85c8afec3b86529317", "", "", "Boom Bang (Unknown)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2d7cc2e5419a9e4ab91fdb26339b726", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2de0fc85548871279ed2a3c1325c13e", "George Veeder", "", "Cat and Mouse (George Veeder) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2eb84cfeed55acd7fece7fefdc83fbb", "", "", "Kool Aid Man (Fixed) (15-11-2002) (CT)", "HMOVE handling fixed in this version", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2f296ea2d6d4b59979bac5dfbf4edf0", "", "", "Warring Worms (28-01-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a2f9e3b6aaa23b6dc06099cdd5b51b31", "Nukey Shay", "", "Montezuma's Revenge (Genesis) (PAL60) (F6_Conversion)", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a302b922a8dbec47743f28b7f91d4cd8", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (Preview) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a30ece6dc4787e474fbc4090512838dc", "Zellers", "", "Circus (Zellers)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a310494ad5ba2b5b221a30d7180a0336", "", "", "Demo Image Series #6 - Mario (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a336beac1f0a835614200ecd9c41fd70", "Atari, Christopher H. Omarzu, Robert Vieira", "CX26121", "Zoo Keeper Sounds (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a34560841e0878c7b14cc65f79f6967d", "Multivision, Michael Case", "", "Harem (1982) (Multivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3486c0b8110d9d4b1db5d8a280723c6", "Atari, Alan J. Murphy, Robert C. Polaro", "CX26100", "Bugs Bunny (08-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a35d47898b2b16ec641d1dfa8a45c2b7", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3873d7c544af459f40d58dfcfb78887", "", "", "Tennis (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3b9d2be822eab07e7f4b10593fb5eaa", "", "", "GREGXM Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3c1c70024d7aabb41381adbfb6d3b25", "Telesys, Alex Leavens", "1005", "Stargunner (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3d7c299fbcd7b637898ee0fdcfc47fc", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (Preview) (1982) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "a3f2a0fcf74bbc5fa763b0ee979b05b1", "Quelle", "873.790 0", "Eishockey-Fieber (1983) (Quelle) (PAL)", "AKA Ice Hockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3f8aebb38182749cb8da85cfbc63d7c", "", "", "Tennis (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a3fee8ce15525ea00d45a06f04c215d1", "Aaron Curtis", "", "AStar (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a406d2f6d84e61d842f4cb13b2b1cfa7", "Tigervision, John Harris - Teldec", "7-002", "Jawbreaker (1982) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a412c8577b2d57b09185ae51739ac54f", "Arcadia Corporation, Dennis Caswell", "AR-4000", "Phaser Patrol (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a41450333f8dd0e96e5e9f0af3770ae9", "", "", "Basic Math (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a422194290c64ef9d444da9d6a207807", "M Network - APh Technological Consulting, Hal Finney", "MT5667", "Dark Cavern (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a428068d3e51498907d97cec40000515", "Bit Corporation", "R320", "Sky Alien (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a47878a760f5fa3aa99f95c3fdc70a0b", "", "", "Demo Image Series #5 - Baboon (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4790224bd5afabd53cbe93e46a7f241", "Activision, Bob Whitehead", "AG-019", "Sky Jinks (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a47e26096de6f6487bf5dd2d1cced294", "Atari", "CX2643", "Codebreaker (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a484638990de7b12c62947c79dafa4c6", "Thomas Jentzsch", "", "Marble Craze - Atari Mouse Hack v1.0 (PAL60) (TJ)", "Uses Atari Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a499d720e7ee35c62424de882a3351b6", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "009-01", "Up 'n Down (1984) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4aa7630e4c0ad7ebb9837d2d81de801", "", "", "Atari 2600 Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4ab331e8768eafdc20ce8b0411ff77a", "", "", "Demo Image Series #1 - Sam (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4b9423877a0b86ca35b52ca3c994ac5", "CCE", "C-805", "Sea Monster (1983) (CCE)", "O Monstro Marinho", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4b99aa5ed85cfdb7d101923147de035", "Jim Goebel", "", "Pac-Law (Jim Goebel) (Hack)", "Hack of Outlaw", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4c08c4994eb9d24fb78be1793e82e26", "Activision, Alan Miller", "AX-012, CAX-012, AX-012-04", "Ice Hockey (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4d026a5c200ef98518ebb77719fe8dc", "Kyle Pittman", "", "SpongeBob SquarePants (2003) (Kyle Pittman) (Hack)", "Hack of Revenge of the Beefsteak Tomatoes", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4e885726af9d97b12bb5a36792eab63", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4ecb54f877cd94515527b11e698608c", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26119", "Saboteur (12-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4f1cea2c8479284e2a2292f8d51b5fa", "", "", "Gunfight 2600 - The Final Kernel Part 2 (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a4ff39d513b993159911efe01ac12eba", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694", "Pole Position (1983) (Atari)", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a511f7ee13e4b35512f9217a677b4028", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2674", "E.T. - The Extra-Terrestrial (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a5262fe6d01d6a1253692682a47f79dd", "", "", "JKH Text Scrolling Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a537879d8e82e1061d3ad800479d3b84", "Andrew Wallace", "", "Brooni (2001) (Andrew Wallace) (PD) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a539b9fd1ba57e46442b3e9351e6383b", "", "", "River Raid (208 in 1) (Unknown) (PAL) (Hack) [a]", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a56b642a3d3ab9bbeee63cd44eb73216", "Carrere Video - JWDA, Sylvia Day, Todd Marshall, Robin McDaniel, Henry Will IV - Teldec - Prism", "USC2001", "Gopher (1983) (Carrere Video) (PAL)", "AKA Vossicht Whlmaus!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a5855d73d304d83ef07dde03e379619f", "Atari, David Crane", "", "Boggle (08-07-1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a58b11148c18d85e4c2aef4ff46ade67", "", "", "Video Chess (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a591b5e8587aae0d984a0f6fe2cc7d1c", "", "", "Globe Trotter Demo (24-03-2003) (Weston)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a5b7f420ca6cc1384da0fed523920d8e", "", "", "Adventure (New Graphics) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a5c96b046d5f8b7c96daaa12f925bef8", "Activision, Alan Miller - Ariola", "EAG-007, EAG-007-04I, PAG-007 - 711 007-720", "Tennis (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a5e9ed3033fb2836e80aa7a420376788", "Atari, Carla Meninsky", "CX2637, CX2637P", "Dodge 'Em (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a60598ad7ee9c5ccad42d5b0df1570a1", "Atari, Alan Miller", "CX26163P", "Surround (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a6127f470306eed359d85eb4a9cf3c96", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a6239810564638de7e4c54e66b3014e4", "Personal Games Company, Robert Anthony Tokar", "", "Birthday Mania (1984) (Personal Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a62e3e19280ff958407e05ca0a2d5ec7", "", "", "Hangman Ghost Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a6737c81542a99ee71cb5f5ff14703d9", "", "", "Scrolling Playfield 3 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a69f5b1761a8a11c98e706ec7204937f", "", "", "Pharaoh's Curse (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a6ed8d72ed691fd3aad5b6974fa17978", "Bit Corporation", "R320", "Bank Heist (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a74689a08746a667a299b0507e1e6dd9", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (1983) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7523db9a33e9417637be0e71fa4377c", "Videospielkassette - Ariola", "PGP238", "Gangster (Ariola) (PAL)", "AKA Outlaw", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7673809068062106db8e9d10b56a5b3", "Atari, Jerome Domurat, Andrew Fuchs, Dave Staugas, Robert Vieira", "CX26118, CX26118P", "Millipede (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a779b9fa02c62d00d7c31ed51268f18a", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7a58e9291aefa1064e933071f60d4ef", "Arcadia Corporation, Dennis Caswell", "1 AR-4000, AR-4100", "Phaser Patrol (1982) (Arcadia) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a7b584937911d60c120677fe0d47f36f", "M Network - INTV - APh Technological Consulting, Hal Finney", "MT5661", "Armor Ambush (1982) (M Network)", "AKA Tank Battle", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7b96a8150600b3e800a4689c3ec60a2", "Atari, Mike Lorenzen - Sears", "CX2630 - 49-75122", "Circus Atari (1980) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, + { "a7bf8353f77caca407ef85c2698fdff2", "Atari, Suki Lee - Sears", "CX2658 - 49-75128", "Math Gran Prix (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7cf2b9afdbb3a161bf418dbcf0321dc", "Barry Laws Jr.", "", "Attack Of The Mutant Space Urchins (2002) (Barry Laws Jr.) (Hack)", "Hack of Alien", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a7d2e9408bb7cd70139ecced407ff238", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a1]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7ed7dc5cbc901388afa59030fb11d26", "Atari, Warren Robinett", "CX2606, CX2606P", "Slot Racers (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a7ef44ccb5b9000caf02df3e6da71a92", "Atari, Ian Shepard - Sears", "CX2604 - 6-99812, 49-75106", "Space War (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8101cb667e50a46165c6fb48c608b6b", "", "", "Kung Fu Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a81697b0c8bbc338ae4d0046ede0646b", "CCE", "", "Gravitar (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a81b29177f258494b499fbac69789cef", "Greg Thompson", "", "Console Wars (Greg Thompson) (Hack)", "Hack of Space Jockey", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a83b070b485cf1fb4d5a48da153fdf1a", "Apollo", "AP-2011", "Pompeii (1983) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8435ec570141de5d833c4abec499e55", "", "", "Happy Birthday Demo (2001) (Dennis Debro) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8633050a686270fcf6c0cc4dcbad630", "Zirok", "", "Phoenix (Zirok)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a867b76098786c4091dba2fcee5084c3", "", "", "Dragrace (Hack)", "Hack of Dragster", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a875f0a919129b4f1b5103ddd200d2fe", "Atari, Dan Hitchens. Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) (PAL)", "AKA Adventure I, SwordQuest I - EarthWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8916734ff8c64ec3342f4c73fd5b57d", "Atari", "", "Stand Alone Test Cart (1982) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a89a3e0547d6887279c34aba4b17a560", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (1983) (Mattel) (Prototype)", "", "Prototype", "", "", "4K", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8a703e073183a89c94d4d99b9661b7f", "Franklin Cruz", "", "Spice Invaders (Franklin Cruz) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8b3ea6836b99bea77c8f603cf1ea187", "CCE", "C-861", "Boxing (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8c447efbec3a2b5d08b05a09999bd92", "", "", "MegaCart Menu", "", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8c48b4e0bf35fe97cc84fdd2c507f78", "Puzzy - Bit Corporation", "PG201", "Seamonster (1982) (Puzzy)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8d0a4a77cd71ac601bd71df5a060e4c", "", "", "Space Shuttle (1983) (Activision) [t2] (Fuel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8d4a9500b18b0a067a1f272f869e094", "", "", "Red And White Checkerboard Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a8e49d7e24ce293629ca29614862821b", "", "", "Enduro (Genesis)", "Genesis controller (B is acceleration, C is brakes)", "Hack of Enduro", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a91d0858a52de3a2e6468437212d93e8", "", "", "Q-bert (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a936d80083e99d48752ad15c2b5f7c96", "", "", "Room of Doom (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a93e8ea1f565c3c1e86b708cf0dc2fa9", "Jess Ragan", "", "Kabul! (Jess Ragan) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "a94528ae05dd051894e945d4d2349b3b", "Genus", "", "River Raid (Genus)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a94b8ca630f467b574b614808d813919", "HES", "773-883", "2 Pak Special - Space Voyage, Fire Alert (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a9531c763077464307086ec9a1fd057d", "Atari, John Dunn - Sears", "CX2631 - 49-75152", "Superman (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a957dbe7d85ea89133346ad56fbda03f", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "a97733b0852ee3096300102cb0689175", "CCE", "C-834", "Fast Eddie (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a9784c24cddb33bd0d14442b97784f3d", "Thomas Jentzsch", "", "Omega Race DC (2003) (TJ) (Omega Race Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a98b649912b6ca19eaf5c2d2faf38562", "", "", "This Planet Sucks (Greg Troutman) (PAL) [!]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a995b6cbdb1f0433abc74050808590e6", "Imagic, Rob Fulop, Bob Smith", "720106-1A, IA3600", "Riddle of the Sphinx (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a9cb638cd2cb2e8e0643d7a67db4281c", "M Network - INTV - APh Technological Consulting, Larry Zwick", "MT5861", "Air Raiders (1983) (M Network)", "AKA Air Battle", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a9d9e19d0c89fb31780b5d63e1f8c6a4", "AtariAge, Chris Spry", "CX26201", "Zippy the Porcupine (2014) (Sprybug) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "a9e3c23599c0d77151602f8e31daf879", "", "", "Kung Fu Master (Genesis)", "Genesis controller (C is extra kick modes)", "Hack of Kung Fu Master", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aa1c41f86ec44c0a44eb64c332ce08af", "Spectravideo, David Lubar", "SA-218", "Bumper Bash (1983) (Spectravideo)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "PADDLES", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aa2c4b32656bde9a75042a4d158583e1", "", "", "Oystron X (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aa5cfe3b20395aba1d479135943ad85c", "", "", "Defender (Hack) (Unknown)", "", "Hack of Defender", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aa7bb54d2c189a31bb1fa20099e42859", "CBS Electronics, Ed English", "4L4478", "Mr. Do! (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "aa8c75d6f99548309949916ad6cf33bc", "Bob Montgomery (aka vdub_bobby)", "", "Squish 'Em (2007)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aa8e4b2cb8a78ffe6b20580033f4dec9", "", "", "Bitmap Demo (13-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aaac0d277eda054861e613c59c2e4ff2", "JWDA, Todd Marshall", "", "Music Demo (JWDA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aab840db22075aa0f6a6b83a597f8890", "Home Vision, R.J.P.G. - Gem International Corp. - VDI", "VCS83124", "Racing Car (1983) (Home Vision) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aad61898633f470ce528e3d7ef3d0adb", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a1]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aad91be0bf78d33d29758876d999848a", "Activision, David Crane", "AX-018, AX-018-04", "Pitfall! (1981) (Activision) (Prototype)", "Pitfall Harry's Jungle Adventure (Jungle Runner)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aaea37b65db9e492798f0105a6915e96", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Tug of War (2 of 3) (1983) (Arcadia)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "02", "", "", "", "", "", "", "", "" }, + { "aafc79ffc32c4c9b2d73c8ada7602cfe", "", "", "Planet Patrol (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab10f2974dee73dab4579f0cab35fca6", "ITT Family Games", "", "Wilma Wanderer (1983) (ITT Family Games) (PAL)", "AKA Lilly Adventure", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab2cfcaad3daaf673b2b14fdbb8dac33", "M Network - INTV, David Akers, Joe King, Patricia Lewis Du Long, Jeff Ratcliff", "MT7045", "Bump 'n' Jump (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab2ea35dcc1098c87455bb8210b018cf", "", "", "Fu Kung! (V0.04 Single Line Resolution) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab301d3d7f2f4fe3fdd8a3540b7a74f5", "Jone Yuan Telephonic Enterprise Co", "", "IQ 180 (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab434f4c942d6472e75d5490cc4dd128", "HES", "773-875", "2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab48c4af46c8b34c3613d210e1206132", "Andrew Davie & Thomas Jentzsch", "", "Boulder Dash - Demo V2 (2014)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab4ac994865fb16ebb85738316309457", "Atari, Alan Miller - Sears", "CX2624 - 6-99826, 49-75113", "Basketball (1978) (Atari)", "Console ports are swapped", "Common", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab56f1b2542a05bebc4fbccfc4803a38", "Activision - Imagineering, Dan Kitchen, David Lubar", "AK-048-04", "River Raid II (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab5bf1ef5e463ad1cbb11b6a33797228", "Imagic, Rob Fulop", "720104-1A, 720104-1B, IA3204", "Cosmic Ark (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab60ea7b707c58d356cad858eb18db43", "", "", "Tazer (John K. Harvey)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ab8d318da4addd39c65b7f9c408df2a6", "", "", "Star Trek (Genesis)", "Genesis controller (B is phaser, C is warp)", "Hack of Star Trek", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "abb740bea0a6842831b4f53112fb8145", "", "", "Qb (V1.01) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "abb741c83f665d73c86d90a7d9292a9b", "Telegames", "", "Space Attack (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "abc64037ca5d5b04ae8a7eedbca3ed74", "", "", "Green and Yellow Number 1 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "abe40542e4ff2d1c51aa2bb033f09984", "Absolute Entertainment, David Crane", "EAZ-042-04B, EAZ-042-04I", "Skate Boardin' (1987) (Absolute) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac05c0e53a5e7009ddd75ed4b99949fc", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac0ddbcff34d064009591607746e33b8", "Thomas Jentzsch", "", "Atlantis FH (2003) (TJ) (Hack)", "Hack of Atlantis", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac26d7d37248d1d8eac5eccacdbef8db", "", "", "Snail Against Squirrel (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac3dd22dd945724be705ddd2785487c2", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (06-15-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac53b83e1b57a601eeae9d3ce1b4a458", "Retroactive", "", "Qb (2.15) (Retroactive) (NTSC)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ac5f78bae0638cf3f2a0c8d07eb4df69", "", "", "Minesweeper (V.99) (Soren Gust) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac7c2260378975614192ca2bc3d20e0b", "Activision, David Crane", "AG-930-04, AZ-030", "Decathlon (1983) (Activision)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ac9adbd6de786a242e19d4bec527982b", "Activision, Alan Miller - Ariola", "EAG-012-04I, EAX-012, EAX-012-04B - 711 012-720", "Ice Hockey (1981) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aca09ffea77174b148b96b205109db4d", "Activision, Alan Miller", "AG-007, CAG-007", "Tennis (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "acaa27d214039d89d7031609aafa55c3", "", "", "Sprite Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "acb6787b938079f4e74313a905ec3ceb", "", "", "Chronocolor Donkey Kong (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "acb7750b4d0c4bd34969802a7deb2990", "Parker Brothers, Ed Temple", "PB5310", "Amidar (1982) (Parker Bros)", "", "Uncommon", "", "", "", "A", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "acb962473185d7a652f90ed6591ae13b", "Imagic, Dennis Koble", "IA3203, IX-010-04", "Atlantis (1982) (Imagic) (16K)", "AKA Lost City of Atlantis", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ace319dc4f76548659876741a6690d57", "Atari, Steve Wright", "CX2616", "Pele's Soccer (1981) (Atari)", "AKA Pele's Championship Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ad2e6bfb3b9b9b36ba8bf493ce764c49", "", "", "2600 Collison Demo 1 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ad42e3ca3144e2159e26be123471bffc", "Atari", "CX26163P", "Human Cannonball (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ad72d616030a17634ff29ce8680d3c4c", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ad7e97c19bd25d5aa3999430845c755b", "", "", "Sprite Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ad8072675109d13fdd31a2e0403d5cff", "Funvision - Fund. International Co.", "", "Tank City (Funvision)", "AKA Thunderground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "adb770ff70e9adf08bbb907a7eccd240", "", "", "Inv Demo 3 (2001) (Erik Mooney) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "adb79f9ac1a633cdd44954e2eac14774", "Digivision", "", "Frostbite (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "adf1afac3bdd7b36d2eda5949f1a0fa3", "Quelle - Otto Versand", "495.463 2 - 746381", "Angriff der Luftflotten (1983) (Quelle) (PAL)", "AKA Paris Attack, M.A.D.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "adfbd2e8a38f96e03751717f7422851d", "Champ Games", "CG-01-N", "Lady Bug (NTSC)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ae047e9468bda961d8e9e9d8ff52980f", "", "", "Tunnel Demo (Red Spiral) (30-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae0d4f3396cb49de0fabdff03cb2756f", "Retroactive", "", "Qb (V2.02) (PAL) (2001) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ae10527840a1ac24de43730645ed508d", "Charles Morgan", "", "Planet Invaders (Charles Morgan) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae18c11e4d7ed2437f0bf5d167c0e96c", "", "", "Multi-Color Demo 3 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae2f1f69bb38355395c1c75c81acc644", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-23-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ae465044dfba287d344ba468820995d7", "", "", "Inca Gold (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae4be3a36b285c1a1dff202157e2155d", "Spectravideo", "SA-210", "Master Builder (1983) (Spectravideo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae682886058cd6981c4b8e93e7b019cf", "Retroactive", "", "Qb (V0.12) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ae6cb335470788b94beb5787976e8818", "", "", "Mortal Kurling (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae83541cf4a4c0bce0adccd2c1bf6288", "", "", "Maze 003 Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ae97cf8ed21f4154b4360a3cf6c95c5e", "", "", "Teleterm 2600 (John K. Harvey) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aeb104f1e7b166bc0cbaca0a968fde51", "", "", "Ms. Pac-Man (1999) (Hack)", "Hack of Ms. Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aec9b885d0e8b24e871925630884095c", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype)", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aed0b7bd64cc384f85fdea33e28daf3b", "Atari, Jim Huether, Alan J. Murphy, Robert C. Polaro", "CX2666", "RealSports Volleyball (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "aed82052f7589df05a3f417bb4e45f0c", "Atari, Warren Robinett - Sears", "CX2606 - 6-99825, 49-75112", "Slot Racers (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "af6ab88d3d7c7417db2b3b3c70b0da0a", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "af6f3e9718bccfcd8afb421f96561a34", "Atari, Tod Frye", "CX2695", "Xevious (01-18-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "afb3bc45c6a82739cc82582127cd96e6", "Atari - Sculptured Software, Adam Clayton", "CX26151, CX26151P", "Dungeon (11-22-1985) (Atari) (Prototype)", "Dark Chambers Beta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "afc194534c1b346609ef05eff6d3cef6", "Jone Yuan Telephonic Enterprise Co", "", "Boxing (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "afd2cf258d51ae4965ee21abba3627ab", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (12-08-1982) (Atari) (Prototype)", "Uses the Keypad Controller", "Prototype", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "afe4eefc7d885c277fc0649507fbcd84", "Atari", "CX26163P", "Ant Party (32 in 1) (1988) (Atari) (PAL)", "AKA Cosmic Swarm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "afe776db50e3378cd6f29c7cdd79104a", "Thomas Jentzsch", "", "Bobby is Going Home (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "afe88aae81d99e0947c0cfb687b16251", "Apollo - Games by Apollo", "AP-2006", "Infiltrate (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "aff8cba0f2d2eb239953dd7116894a08", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (3 of 3) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b00088418fc891f3faa3d4ddde6ace94", "", "", "Unknown Title (bin00007 (200102)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b00a8bc9d7fe7080980a514005cbad13", "K-Tel Vision", "", "Vulture Attack (1982) (K-Tel Vision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b00e8217633e870bf39d948662a52aac", "Konami", "RC 102-X 02", "Marine Wars (1983) (Konami)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b011d8fdc450597c0762c2c0010a9b17", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (NTSC) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b049fc8ac50be7c2f28418817979c637", "Activision - Imagineering, Dan Kitchen, David Lubar", "EAK-048-04, EAK-048-04B", "River Raid II (1988) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b06050f686c6b857d0df1b79fea47bb4", "Activision", "AIZ-001", "Moonsweeper (1988) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b061e98a4c854a672aadefa233236e51", "Atari, Warren Robinett", "CX2620, CX2620P", "Basic Programming (1979) (Atari) (PAL)", "Uses Keypad Controllers", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b095009004df341386d22b2a3fae3c81", "", "", "Sub-Scan (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b09b79c9628878be051e89f7f1e77378", "Activision, Larry Kaplan, David Crane - Ariola", "EAG-010, PAG-010 - 711 010-720", "Kaboom! (1981) (Activision) (PAL) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "b0a9c6f6c8014c4023e0341ba11ca35e", "The Atari 2600 Connection - John K. Harvey, Tim Duarte", "v75", "Mean Santa (2009) (PAL)", "Released in 2019", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b0ba51723b9330797985808db598fc31", "Atari, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b0c47e426c7f799aee2c40422df8f56a", "", "", "Space Treat (PAL) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b0c9cf89a6d4e612524f4fd48b5bb562", "Atari - GCC", "CX2663", "Combat Two (1982) (Atari) (Prototype)", "AKA Super Combat", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b0e1ee07fbc73493eac5651a52f90f00", "Colin Hughes", "", "Tetris 2600 (Colin Hughes)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b1276417fb0f79bc52e741bb8f4d8360", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (NTSC) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b129d7541cff79ebe33852a83057c524", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (NTSC) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b12a7f63787a6bb08e683837a8ed3f18", "Imagic, Rob Fulop", "720000-200, 720101-1B, 720101-1C, IA3200, IA3200C, IX-006-04", "Demon Attack (1982) (Imagic) [fixed]", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1339c56a9ea63122232fe4328373ac5", "Goliath - Hot Shot", "83-215", "Dream Flight (1983) (Goliath) (PAL)", "AKA Nightmare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1486e12de717013376447ac6f7f3a80", "Spectravideo, Mark Turmell, Quelle", "SA-217, SA-217C - 413.723 8", "Gas Hog - Piraten Schiff (1983) (Spectravideo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b15026b43c6758609667468434766dd8", "Retroactive", "", "Qb (0.06) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b16cd9784589219391c839cb68c47b9c", "Video Soft, Jerry Lawson, Dan McElroy", "", "Golf Diagnostic (1983) (Video Soft) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b17b9cc4103844dcda54f77f44acc93a", "Quelle", "377.943 6", "Stopp die Gangster (1983) (Quelle) (PAL)", "AKA Gangster Alley", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b182d9708e00709830caab9cf8205ca0", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1a6c96e9093352106bc335e96caa154", "Joe Grand", "", "SCSIcide Pre-release 1 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1b20536aef4eed9c79dc5804f077862", "", "", "Euchre (NTSC) (09-11-2001) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1c14b5ac896400cc91c8e5dd67acb59", "", "", "River Raid (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1d1e083dc9e7d9a5dc1627869d2ade7", "CCE", "C-1004", "Mario's Bros. (1983) (CCE)", "AKA Mario Bros.", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b1e2d5dc1353af6d56cd2fe7cfe75254", "Atari - Axlon, Steve DeFrisco", "CX26171", "MotoRodeo (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b1fd0b71de9f6eeb5143a97963674cb6", "", "", "Multi-Color Demo 7 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b227175699e372b8fe10ce243ad6dda5", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [a1]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b23ebf427713dd0198b7ef47dbd07ef4", "Jone Yuan Telephonic Enterprise Co", "", "Sky Diver (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b24f6a5820a4b7763a3d547e3e07441d", "CCE", "C-823", "Demon Attack (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b25841173f058380b1771aacd5e7cdf3", "Bit Corporation", "PG205", "Dancing Plate (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b26506fbf411009e5e3f7365f442960e", "Atari, Alan Miller", "CX2642", "Hunt & Score (1978) (Atari) (PAL) (4K)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2737034f974535f5c0c6431ab8caf73", "CBS Electronics, Richard K. Balaska Jr., Andy Frank, Stuart Ross", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2761efb8a11fc59b00a3b9d78022ad6", "Atari, Bob Whitehead - Sears", "CX2651 - 99805, 49-75602", "Blackjack (1977) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b290c2b139344fcff5b312c71b9ac3b2", "Atari", "CX26163P", "UFO (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b29359f7de62fed6e6ad4c948f699df8", "Goliath", "3", "Phantom Tank (1983) (Goliath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2a6f31636b699aeda900f07152bab6e", "", "", "Space Instigators (Public Release 2) (06-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2ab209976354ad4a0e1676fc1fe5a82", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a3]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2d1e63f7f22864096b7b6c154151d55", "Fabrizio Zavagli", "", "Bounce! (17-03-2003) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b2d3bcee001cff2bd2d8a21b2cb55109", "Atari - GCC, Mike Feinstein, Kevin Osborn", "CX2691", "Joust (08-09-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b2d5d200f0af8485413fad957828582a", "Atari - Bobco, Robert C. Polaro", "CX26155P", "Sprint Master (1988) (Atari) (PAL)", "AKA Sprint 88, Sprint 2000", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b2f0d7217147160b2f481954cedf814b", "", "", "Marquee Drawer (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b3017e397f74efd53caf8fae0a38e3fe", "Retroactive", "", "Qb (2.12) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b311ab95e85bc0162308390728a7361d", "Parker Brothers - Roklan, Joe Gaucher", "PB5080", "Gyruss (1984) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b31dc989f594764eacfa7931cead0050", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (2 of 3) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b31e9487efc06f18dfc3d7ebadf54416", "Omegamatrix", "", "Star Wars Arcade (Atari Mouse) v4 (PAL60) (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b31f178aa0d569cccac7959f84e0a724", "Atari, Jerome Domurat, Steve Woita", "CX2699", "Taz (07-13-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b3203e383b435f7e43f9492893c7469f", "Gameworld", "133-003", "Sssnake (1983) (Gameworld) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b36040a2f9ecafa73d835d804a572dbf", "Digitel", "", "Pac Man (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b37f0fe822b92ca8f5e330bf62d56ea9", "Xonox - K-Tel Software - Beck-Tech, Steve Beck", "6210, 7210, 06003. 99001", "Spike's Peak (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b392964e8b1c9c2bed12246f228011b2", "", "", "Name This Game (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b4030c38a720dd84b84178b6ce1fc749", "M Network - APh Technological Consulting, Kevin Miller", "MT5687", "International Soccer (1982) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b40dea357d41c5408546e4e4d5f27779", "Digivision", "", "Spider Fighter (Digivision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b41fdd4a522e1d5a2721840028684ac2", "", "", "Green and Yellow Number 1 Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b42df8d92e3118dc594cecd575f515d7", "Mystique - American Multiple Industries", "1003", "Burning Desire (1982) (Mystique) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b438a6aa9d4b9b8f0b2ddb51323b21e4", "Telegames", "5861 A030", "Bogey Blaster (1988) (Telegames) (PAL)", "AKA Air Raiders", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b451307b8b5e29f1c5f2cf064f6c7227", "", "", "Demo Image Series #6 - Mario (Fixed) (26-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b49331b237c8f11d5f36fe2054a7b92b", "", "", "Condor Attack (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b4a4c87840613f102acb5b3a647d0a67", "", "", "Mobile 48 Sprite Kernel (04-01-2003) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b4daedb43511521db9036d503b3c1b69", "", "", "Sokoban (01-01-2003) (Adam Wozniak) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b4e2fd27d3180f0f4eb1065afc0d7fc9", "Avalon Hill, Jean Baer, Bill 'Rebecca Ann' Heineman, William O. Sheppard", "5002002", "London Blitz (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b4f05e544834d0238a0c263491775edf", "Starpath Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (Preview) (1982) (Starpath) (PAL)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b4f31ea8a6cc9f1fd4d5585a87c3b487", "Mystique - American Multiple Industries, Joel H. Martin", "", "Beat 'Em & Eat 'Em (1982) (Mystique) (PAL)", "Uses the Paddle Controller (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "b4f87ce75f7329c18301a2505fe59cd3", "Videospielkassett - Ariola", "PGP232", "Autorennen (Ariola) (PAL)", "AKA Grand Prix", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b50ae55aac93fbed258bc5a873edd2cb", "Recompile", "", "E.T. The Extra-Terrestrial (Recompile) (Hack)", "www.neocomputer.org/projects/et", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b5110f55ed99d5279f18266d001a8cd5", "Eckhard Stolberg", "", "Auto-mobile Demo (2001) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b56264f738b2eb2c8f7cf5a2a75e5fdc", "Atari - GCC, John Allred, Douglas B. Macrae, Betty Ryan Tylko", "CX2694, CX2694P", "Pole Position (1983) (Atari) (PAL)", "AKA RealSports Driving", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b5657d4c1c732fbb6af150668464247f", "Arcadia Corporation, Stephen H. Landrum", "AR-4400", "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b59417d083b0be2d49a7d93769880a4b", "Pet Boat", "", "Donkey Kong (1983) (Pet Boat) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b59fd465abf76f64c85652ff29d5952d", "VentureVision, Dan Oliver", "", "Innerspace (1983) (VentureVision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b5a1a189601a785bdb2f02a424080412", "Imagic, Dennis Koble", "720021-1A, IA3410", "Shootin' Gallery (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b5cb9cf6e668ea3f4cc2be00ea70ec3c", "CommaVid, Irwin Gaines - Ariola", "CM-005 - 712 005-720", "Mines of Minos (1982) (CommaVid) (PAL)", "AKA Im Labyrinth des Roboters", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b5cdbab514ea726a14383cff6db40e26", "Video Gems", "VG-04", "Mission Survive (1983) (Video Gems) (PAL) [a]", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b5efe0271d2214e4d5dc798881486884", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (06-14-1990) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b6166f15720fdf192932f1f76df5b65d", "Amiga - Video Soft", "3130", "Off Your Rocker (1983) (Amiga) (Prototype)", "Uses the Amiga Joyboard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b64426e787f04ff23ee629182c168603", "Dynacom", "", "Plaque Attack (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b65d4a38d6047735824ee99684f3515e", "Dynacom", "", "MegaBoy (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b676a9b7094e0345a76ef027091d916b", "Thomas Jentzsch", "", "Mission Survive (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b6812eaf87127f043e78f91f2028f9f4", "Simage", "", "Eli's Ladder (1984) (Simage)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b6821ac51c4c1dcb283f01be2f047dc1", "Thomas Jentzsch", "", "Rubik's Cube 3D Demo (25-11-2002) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b6960be26bee87d53ba4e2e71cfe772f", "", "", "3-D Corridor (Spiral Words) (31-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b6d52a0cf53ad4216feb04147301f87d", "Imagic, Michael Greene", "720055-1A, IA3312", "No Escape! (1983) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b6e40bce550672e5495a8cdde7075b8b", "Arcadia Corporation, Steve Mundry, Scott Nelson", "AR-4401", "Survival Island (1 of 3) (1983) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b702641d698c60bcdc922dbd8c9dd49c", "Atari, Ian Shepard", "CX26163P", "Space War (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b719ada17771a8d206c7976553825139", "Ron Corcoran", "", "DUP Space Invaders (Ron Corcoran) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b731d35e4ac6b3b47eba5dd0991f452f", "Thomas Jentzsch", "", "Rubik's Cube 3D Demo (Final) (08-01-2003) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7345220a0c587f3b0c47af33ebe533c", "Quelle", "176.433 1", "Landungskommando (1983) (Quelle) (PAL)", "AKA Strategy X", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b76fbadc8ffb1f83e2ca08b6fb4d6c9f", "Activision, Bob Whitehead", "AG-005, CAG-005, AG-005-04", "Skiing (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b77468d586957d1b7fb4cccda2684f47", "Atari", "CX26163P", "Boxing (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7903268e235310dc346a164af4c7022", "Thomas Jentzsch", "", "Cat Trax (Thomas Jentzsch) (PAL60)", "NTSC Conversion", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b79fe32320388a197ac3a0b932cc2189", "Imagic, Bob Smith", "13207, EIZ-001-04I", "Moonsweeper (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b7a7e34e304e4b7bc565ec01ba33ea27", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b7b1d3ce07e75976c43a2dca3866237e", "Atari", "CX26163P", "Freeway Chicken (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Freeway", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7d0aae399781b3c18679debda6d32b1", "Thomas Jentzsch", "", "Three.s (v1.02)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7d7c76e37f372f4e4979b380ed95a58", "AtariAge - Michael Haas", "RC2", "Flappy (2014) (AtariAge) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7e459d5416eeb196aaa8e092db14463", "", "", "Push (V0.02) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b7f184013991823fc02a6557341d2a7a", "", "", "Blue Rod Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b80d50ecee73919a507498d0a4d922ae", "20th Century Fox Video Games - Sirius Software, David Lubar", "11008", "Fantastic Voyage (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b816296311019ab69a21cb9e9e235d12", "Atari, Bob Whitehead - Sears", "CX2652 - 6-99816, 49-75151", "Casino (1979) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b822fba8b7c8a97ea4e92aeb2c455ef9", "Dactari", "", "Freeway (Dactari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b83579c4450fcbdf2b108903731fa734", "", "", "Mission 3,000 A.D. (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b83df1f32b4539c324bdf94851b4db55", "Angelino", "", "One On One by Angelino (Basketball Hack)", "Hack of Basketball (1978) (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b86552198f52cfce721bafb496363099", "Apollo, Tim Martin", "AP-2007", "Kyphus (1982) (Apollo) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b86a12e53ab107b6caedd4e0272aa034", "Funvision - Fund. International Co.", "", "Treasure Hunting (Funvision)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b879e13fd99382e09bcaf1d87ad84add", "Zellers", "", "Time Warp (Zellers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b8865f05676e64f3bec72b9defdacfa7", "Activision, David Crane", "AG-004", "Fishing Derby (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b897f9e3f939b9f21566d56db812a84e", "Atari, Jim Huether", "CX26163P", "Flag Capture (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b8e715223ba65cf716b3620a90ca3ec1", "Parker Brothers", "PB5820", "Mr. Do!'s Castle (1984) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b8ed78afdb1e6cfe44ef6e3428789d5f", "Data Age, J. Ray Dettling", "112-007", "Bermuda Triangle (1983) (Data Age)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b9232c1de494875efe1858fc8390616d", "Panda", "110", "Harbor Escape (1983) (Panda)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b9336ed6d94a5cc81a16483b0a946a73", "Atari, Jerome Domurat, Michael Sierchio", "CX2667, CX2667P", "RealSports Soccer (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b955eb0e2baf7a437c186bddd4c49958", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (PAL60) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b958d5fd9574c5cf9ece4b9421c28ecd", "Piero Cavina", "", "Multi-Sprite Game V1.0 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b95a6274ca0e0c773bfdc06b4c3daa42", "Paul Slocum", "", "3-D Corridor (29-03-2003) (Paul Slocum)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b98cc2c6f7a0f05176f74f0f62c45488", "Spectravideo", "SV-010", "CompuMate (1983) (Spectravideo)", "", "", "", "", "CM", "", "", "", "", "COMPUMATE", "COMPUMATE", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "b9b4612358a0b2c1b4d66bb146767306", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b9d1e3be30b131324482345959aed5e5", "Activision - Boston Design Center, Rex Bradford", "", "Kabobber (07-25-1983) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "b9f6fa399b8cd386c235983ec45e4355", "Parker Brothers, John Emerson", "931511", "Action Force (1983) (Parker Bros) (PAL)", "AKA G.I. Joe - Cobra Strike", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, + { "b9f9c0fed0db08c34346317f3957a945", "SuperVision", "405, 427, 806, 808, 813, 816", "Chopper Command (SuperVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ba257438f8a78862a9e014d831143690", "U.S. Games Corporation - JWDA, Todd Marshall, Robin McDaniel, Henry Will IV", "VC2002", "Squeeze Box (1983) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ba317f83cdfcd58cbc65aac1ccb87bc5", "Thomas Jentzsch", "", "Jammed (2001) (XYPE) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ba3a17efd26db8b4f09c0cf7afdf84d1", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ba3b0eebccc7b791107de5b4abb671b4", "Thomas Jentzsch", "", "Thrust (V0.9) (2000) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ba657d940a11e807ff314bba2c8b389b", "Activision, John Van Ryzin", "AG-038-04", "Cosmic Commuter (1984) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bac28d06dfc03d3d2f4a7c13383e84ee", "Supergame", "", "Demon Attack (Supergame)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bae1a23f9b6acdadf465cfb330ba0acb", "Atari - GCC, Doug Macrae", "CX2677", "Dig Dug (1983) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bae66907c3200bc63592efe5a9a69dbb", "Spectravision - Spectravideo - Quelle", "SA-201 - 412.783 3", "Gangster Alley (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "baf4ce885aa281fd31711da9b9795485", "Atari, Douglas Neubauer", "CX26176", "Radar Lock (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb18189021d58362d9e4d317cd2e28b7", "Activision, David Crane - Ariola", "EAG-001, PAG-001, EAG-001-04B, EAG-001-04I - 711 001-715", "Dragster (1980) (Activision) (PAL) (4K)", "AKA Dragster Rennen", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb2b83fff97604f74ada565e0b5bae94", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (PAL60) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb5049e4558daade0f87fed69a244c59", "Atari, Brad Stewart", "CX2649, CX2649P", "Asteroids (1981) (Atari) (PAL) [no copyright]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "bb579404924c40ca378b4aff6ccf302d", "", "", "Lightbulb Lightens, The (PD) (Non Functional)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb6a5a2f7b67bee5d1f237f62f1e643f", "", "", "Demo Image Series #5 - Animegirl (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb745c893999b0efc96ea9029e3c62ca", "Play Video", "", "Planet Patrol (1982) (Play Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb756aa98b847dddc8fc170bc79f92b2", "", "", "Golf (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bb9112d478a1a922d2c289a752bba695", "Omegamatrix", "", "SpaceMaster X-7 (Amiga Mouse) (Omegamatrix)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bbf8c7c9ed280151934aabe138e41ba7", "Amiga", "1130", "Power Play Arcade Video Game Album V (1984) (Amiga) (Prototype)", "Mogul Maniac, Surf's Up, Off Your Rocker, S.A.C. Alert", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc24440b59092559a1ec26055fd1270e", "", "", "Private Eye (1984) (Activision) [a]", "", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc3057a35319aae3a5cd87a203736abe", "CCE", "C-845", "Time Warp (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc33c685e6ffced83abe7a43f30df7f9", "Dynacom", "", "Seaquest (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc4cf38a4bee45752dc466c98ed7ad09", "Atari, Douglas Neubauer, Mimi Nyden", "CX26136", "Solaris (1986) (Atari) (PAL)", "AKA Universe, Star Raiders II, The Last Starfighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc526185ad324241782dc68ba5d0540b", "", "", "Dodge Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc5389839857612cfabeb810ba7effdc", "Atari, Tod Frye", "CX2671", "SwordQuest - WaterWorld (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc703ea6afb20bc089f04d8c9d79a2bd", "", "", "Gunfight 2600 - Not mergeable with Colbert wizardry... (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bc97d544f1d4834cc72bcc92a37b8c1b", "", "", "Sky Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bcb31f22856b0028c00d12f0e4c0a952", "Canal 3 - Intellivision", "", "Thunderground (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bcb73b534ed7c613ac379ecd726effb5", "Bob Montgomery (aka vdub_bobby)", "", "Squish 'Em (2007) (PAL60)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bccb4e2cfad5efc93f6d55dc992118ce", "Activision, Carol Shaw", "AX-020, AX-020-04", "River Raid (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bce4c291d0007f16997faa5c4db0a6b8", "Quelle", "292.651 7", "Weltraumtunnel (1983) (Quelle) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bce93984b920e9b56cf24064f740fe78", "Atari", "CX26163P", "Checkers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bcef7880828a391cf6b50d5a6dcef719", "Rainbow Vision - Suntek", "SS-009", "Bermuda, The (1983) (Rainbow Vision) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bd1bd6f6b928df17a702def0302f46f4", "", "", "Binary To Decimal Routine (2001) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bd39598f067a1193ae81bd6182e756d1", "Telegames", "", "Night Stalker (1988) (Telegames) (PAL)", "AKA Dark Cavern", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bd430c2193045c68d1a20a018a976248", "", "", "Pac Ghost Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bd551ff1264f5c367a3ad7cf0d2f266c", "Bit Corporation", "R320", "SpaceMaster X-7 (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bda1463e02ae3a6e1107ffe1b572efd2", "Atari, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bdb4b584ddc90c9d2ec7e21632a236b6", "Atari Freak 1", "", "Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack)", "Hack of Pac-Man Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bdbaeff1f7132358ea64c7be9e46c1ac", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11105", "Mega Force (1982) (20th Century Fox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bdc381baf7c252c63739c5e9ed087a5c", "", "", "Vertical Ship Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bdecc81f740200780db04a107c3a1eba", "Quelle", "874.254 6", "Super-Cowboy beim Rodeo (1983) (Quelle) (PAL)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bdf1996e2dd64baf8eff5511811ca6ca", "Tron", "", "H.E.R.O. (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be060a704803446c02e6f039ab12eb91", "Parker Brothers, Rex Bradford, Sam Kjellman", "931501", "Star Wars - The Empire Strikes Back (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be1922bd8e09d74da471287e1e968653", "Cropsy", "", "Hangman Pacman Demo (Cropsy) (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be2870a0120fd28d25284e9ccdcbdc99", "", "", "Tomb Raider 2600 [REV 01] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be35d8b37bbc03848a5f020662a99909", "Atari, Joe Decuir, Steve Mayer, Larry Wagner - Sears", "CX2601 - 99801, 6-99801, 49-75124", "Combat (1977) (Atari) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be3f0e827e2f748819dac2a22d6ac823", "Puzzy - Bit Corporation", "PG202", "Space Tunnel (1982) (Puzzy)", "AKA Le Tunnel de L'Estace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be41463cd918daef107d249f8cde3409", "", "", "Berzerk (Voice Enhanced) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be561b286b6432cac71bccbae68002f7", "", "", "Counter Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "be929419902e21bd7830a7a7d746195d", "Activision, Garry Kitchen", "AX-025, AX-025-04", "Keystone Kapers (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "becd908f9d7bb361982c3dc02d6475c6", "Kyle Pittman", "", "THX-1138 (Kyle Pittman) (Hack)", "Hack of Berserk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bedfbde71fb606601f936b5b057f26f7", "Activision, Garry Kitchen - Ariola", "EAX-025, EAX-025-04I - 711 025-725", "Keystone Kapers (1983) (Activision) (PAL) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "befce0de2012b24fd6cb8b53c17c8271", "", "", "Push (V0.03) (No Illegal Opcodes) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bf1970b692275b42c4ec0683588eb062", "Thomas Jentzsch", "", "Reactor - Amiga Mouse Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bf52327c2197d9d2c4544be053caded1", "HES - Activision", "AG-930-04, AZ-030", "Decathlon (HES) (PAL) (16K)", "AKA Activision Decathlon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bf84f528de44225dd733c0e6a8e400a0", "CCE", "", "Demons to Diamonds (CCE)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 57", "", "", "", "", "", "", "", "" }, + { "bf976cf80bcf52c5f164c1d45f2b316b", "Atari, Tod Frye, Mimi Nyden", "CX2657", "SwordQuest - FireWorld (1982) (Atari) (PAL)", "AKA Adventure II, SwordQuest II - FireWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bfa58198c6b9cd8062ee76a2b38e9b33", "", "", "20 Sprites at Once Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bfb73aabb2489316cd5882c3cd11d9f9", "AtariAge, Chris Walton & Thomas Jentzsch", "165", "Star Castle Arcade (2014) (AtariAge)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "bff8f8f53a8aeb1ee804004ccbb08313", "", "", "Droid Demo 22 (David Conrad Schweinsberg) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "bffe34516aaa3cbf5d307eab382a7e95", "", "", "Euchre (Release Candidate) (PAL) (28-09-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c00734a2233ef683d9b6e622ac97a5c8", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26133", "A-Team, The (03-30-1984) (Atari) (Prototype)", "AKA Saboteur", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c00b65d1bae0aef6a1b5652c9c2156a1", "Atari, Joe Decuir - Sears", "CX2621 - 99806, 6-99806, 49-75104", "Video Olympics (1977) (Atari) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "c02e1afa0671e438fd526055c556d231", "Atari", "", "A-Team (Atari) (Prototype) (PAL60)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c032c2bd7017fdfbba9a105ec50f800e", "Activision, Charlie Heath", "", "Thwocker (04-09-1984) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c033dc1d7b6fde41b9cadce9638909bb", "", "", "Skeleton (V1.1) (06-09-2002) (Eric Ball)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c0589bb73858924389077fa3c2e9441a", "SOLID Corp. (D. Scott Williamson)", "CX2655-014", "Star Castle 2600 (SolidCorp) [014]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c05f367fa4767ceb27abadf0066df7f4", "Thomas Jentzsch", "", "TomInv (31-07-2001) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c08d0cee43077d3055febb00e5745c1d", "HES - Activision", "", "Super Hit Pak - River Raid, Sky Jinks, Grand Prix, Fishing Derby, Checkers (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c0a68837c60e15d1fc5a40c9a62894bc", "Arcadia Corporation, Kevin Norman", "7 AR-4103", "Killer Satellites (1983) (Arcadia) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c0c7eddefce9015346db88ade3e1e096", "CBS Electronics, Bob Curtiss", "4L 2487 5000", "Solar Fox (1983) (CBS Electronics) (Prototype) (4K)", "RAM must be zero'ed to start correctly", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c0d2434348de72fa6edcc6d8e40f28d7", "SEGA - Beck-Tech, Steve Beck", "010-01", "Tapper (1984) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1034a5bfb0bb13cc5bdf86cc58989a7", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (1982) (Atari) (Prototype) (4K) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c118854d670289a8b5d5156aa74b0c49", "Jone Yuan Telephonic Enterprise Co", "", "Skiing (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c11e8473c652619ac6166900150ce215", "AtariAge, Chris Walton", "1.0 (Release)", "Chetiry (2011) (AtariAge) (60k) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "50", "", "", "", "" }, + { "c126656df6badfa519cc63e681fb3596", "Ron Corcoran", "", "Space Invaders (2002) (Ron Corcoran) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c15042e54c7408498f051d782aaa8945", "Omegamatrix", "", "Millipede (Atari Trak-Ball) v6.5 (Omegamatrix)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c150c76cbde2c9b5a97eb5399d46c64f", "", "", "Unknown Title (xxx00000 (200203)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c16c79aad6272baffb8aae9a7fff0864", "U.S. Games Corporation - JWDA, Sylvia Day, Todd Marshall, Robin McDaniel, Henry Will IV", "VC2001", "Gopher (1982) (U.S. Games)", "AKA Gopher Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c16fbfdbfdf5590cc8179e4b0f5f5aeb", "", "", "Wall Break (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c17bdc7d14a36e10837d039f43ee5fa3", "Spectravision - Spectravideo", "SA-203", "Cross Force (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1a83f44137ea914b495fc6ac036c493", "Atari, Carla Meninsky", "CX2660", "Star Raiders (1982) (Atari) (PAL)", "Uses Joystick (left) and Keypad (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1b038ce5cb6d85e956c5509b0e0d0d8", "", "", "Rotating Colors Demo 2 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1b1049b88bcd98437d8872d1d62ba31", "", "", "Demo Image Series #4 - Donald (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1b7aeabc3ec41556d924c8372a9ba5b", "Atari, Robert C. Polaro", "", "Dukes of Hazard (1980) (Atari) (Prototype)", "AKA Stunt Cycle", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1cb228470a87beb5f36e90ac745da26", "Activision, Bob Whitehead", "AX-015, AX-015-04", "Chopper Command (1982) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1e6e4e7ef5f146388a090f1c469a2fa", "Bomb - Onbase", "CA283", "Z-Tack (1983) (Bomb)", "AKA Base Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1f209d80f0624dada5866ce05dd3399", "Telegames", "", "Deadly Discs (1988) (Telegames) (PAL)", "AKA TRON - Deadly Discs", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c1fdd44efda916414be3527a47752c75", "Parker Brothers, John Emerson", "PB5920", "G.I. Joe - Cobra Strike (1983) (Parker Bros)", "Uses the Paddle (left) and Joystick (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c20f15282a1aa8724d70c117e5c9709e", "Video Gems", "VG-02", "Surfer's Paradise (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c21450c21efb7715746e9fa87ad6f145", "Hozer Video Games", "", "Gunfight 2600 - It could've been soooo cool, but... (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c216b91f5db21a093ded6a5aaec85709", "Jone Yuan Telephonic Enterprise Co", "", "Dragster (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c221607529cabc93450ef25dbac6e8d2", "Eckhard Stolberg", "", "Color Test (26-09-2002) (Eckhard Stolberg)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c225379e7c4fb6f886ef9c8c522275b4", "Video Mania", "", "Frostbite (1983) (Video Mania)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c225abfb584960efe1f359fc94b73379", "", "", "Joustpong (21-09-2002) (Kirk Israel) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2410d03820e0ff0a449fa6170f51211", "", "", "Pac-Man (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c246e05b52f68ab2e9aee40f278cd158", "Thomas Jentzsch", "", "Star Wars - Ewok Adventure (Thomas Jentzsch) (Prototype)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2778507b83d9540e9be5713758ff945", "", "", "Island Flyer Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c28b29764c2338b0cf95537cc9aad8c9", "", "", "Multi-Color Demo 4 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c29d17eef6b0784db4586c12cb5fd454", "Jone Yuan Telephonic Enterprise Co", "", "River Raid (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c29f8db680990cb45ef7fef6ab57a2c2", "Parker Brothers - Roklan, Paul Crowley, Bob Curtiss", "931505", "Super Cobra (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2a37f1c7603c5fd97df47d6c562abfa", "Roger Williams", "", "Bar-Score Demo (2001) (Roger Williams)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2b5c50ccb59816867036d7cf730bf75", "Salu - Avantgarde Software, Michael Buetepage", "460741", "Ghostbusters II (1992) (Salu) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c2bcd8f2378c3779067f3a551f662bb7", "Activision, Bob Whitehead - Ariola", "EAG-002, EAG-002-04I, PAG-002 - 711 002-715", "Boxing (1980) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2c7a11717e255593e54d0acaf653ee5", "", "", "Chopper Command (208 in 1) (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2c8eb642765137bb82b83a65232961f", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (PAL) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2dea467f4a02fa1f06d66f52bc12e6e", "Thomas Jentzsch", "", "Missile Command Atari Trak-Ball Hack v1.3 (NTSC) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c2fbef02b6eea37d8df3e91107f89950", "Champ Games", "CG-02-N", "Conquest Of Mars (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c31a17942d162b80962cb1f7571cd1d5", "Home Vision - Gem International Corp. - VDI", "VCS83112", "Sky Alien (1983) (Home Vision) (PAL)", "AKA Sky Aliem", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3205e3707f646e1a106e09c5c49c1bf", "", "", "Unknown Title (bin00003 (200206)) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3472fa98c3b452fa2fd37d1c219fb6f", "Atari, Carla Meninsky - Sears", "CX2637 - 49-75158", "Dodge 'Em (1980) (Atari) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c370c3268ad95b3266d6e36ff23d1f0c", "Atari, Alan Miller", "CX2641, CX2641P", "Surround (1977) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3a9550f6345f4c25b372c42dc865703", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (1989) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3aeb796fdaf9429e8cd6af6346f337e", "", "", "If It's Not One Thing It's Another (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3bbc673acf2701b5275e85d9372facf", "Atari, Robert C. Polaro", "CX26157", "Stunt Cycle (07-21-1980) (Atari) (Prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3e4aa718f46291311f1cce53e6ccd79", "", "", "Hangman Ghost 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3ef5c4653212088eda54dc91d787870", "Activision, Bob Whitehead", "AG-002, CAG-002, AG-002-04", "Boxing (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c3f53993ade534b0982ca3a286c85bb5", "", "", "Full Screen Bitmap Drawing System (12-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c4060a31d61ba857e756430a0a15ed2e", "Thomas Jentzsch", "", "Pick 'n Pile (2003) (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c41e7735f6701dd50e84ee71d3ed1d8f", "Dynacom", "", "Spider Fighter (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c43bd363e1f128e73ba5f0380b6fd7e3", "Atari, Chris Crawford", "", "Wizard (1980) (Atari) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c446288fe62c0c2737639fd788ae4a21", "", "", "Mark's Sound Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c450a285daa7a3b65188c2c3cf04fb3e", "Wizard Video Games", "007", "Halloween (1983) (Wizard Video Games) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c469151655e333793472777052013f4f", "", "", "Base Attack (Unknown) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c471b97446a85304bbac021c57c2cb49", "First Star Software, Alex Leavens, Shirley Ann Russell", "", "Boing! (1983) (First Star Software) (PAL)", "AKA Bubbles, Soap Suds, The Emphysema Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c47244f5557ae12c61e8e01c140e2173", "Atari - GCC, Mike Feinstein, John Allred", "CX2688, CX2688P", "Jungle Hunt (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c47b7389e76974fd0de3f088fea35576", "Funvision - Fund. International Co.", "", "Mighty Mouse (Funvision)", "AKA Gopher", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c482f8eebd45e0b8d479d9b71dd72bb8", "Retroactive", "", "Push (V0.03) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c49fe437800ad7fd9302f3a90a38fb7d", "Atari, Dan Hitchens, Mimi Nyden", "CX2697, CX2697P", "Mario Bros. (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c4b73c35bc2f54b66cd786f55b668a82", "Arcadia Corporation, Stephen Harland Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c4bbbb0c8fe203cbd3be2e318e55bcc0", "", "", "Atlantis (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c4bc8c2e130d76346ebf8eb544991b46", "Imagic", "", "Imagic Selector ROM (1982) (Imagic) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c4d888bcf532e7c9c5fdeafbb145266a", "", "", "Space Robot (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c504a71c411a601d1fc3173369cfdca4", "Retroactive", "", "Qb (V2.02) (Stella) (2001) (Retroactive)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c5124e7d7a8c768e5a18bde8b54aeb1d", "Imagic, Rob Fulop", "720104-2A, IA3204P, EIX-008-04I", "Cosmic Ark (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c517144e3d3ac5c06f2f682ebf212dd7", "Tigervision - Teldec", "7-008 - 3.60006 VG", "Miner 2049er (1983) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c529e63013698064149b9e0468afd941", "", "", "S.I.PLIX 2 (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "c52d9bbdc5530e1ef8e8ba7be692b01e", "Atari, Robert C. Polaro", "CX26130", "Holey Moley (02-29-1984) (Atari) (Prototype)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5301f549d0722049bb0add6b10d1e09", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari)", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "c5387fc1aa71f11d2fa82459e189a5f0", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp) (PAL)", "AKA Weltraum-Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c53c0d10c74325deae9ba84074281983", "The Atari 2600 Connection - John K. Harvey, Tim Duarte", "v75", "Mean Santa (2009)", "Released in 2019", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c541a5f6fc23b40a211196dd78233780", "Atari, Carla Meninsky - Sears", "CX2660 - 49-75187", "Star Raiders (1981) (Atari) (Prototype) (4K)", "Uses Joystick (left) and Keypad (right) Controllers", "Prototype", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c54b4207ce1d4bf72fadbb1a805d4a39", "Billy Eno", "", "Sniper (Feb 30) (2001) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c560a3ecb7b751021953819efcfe5b41", "Omegamatrix", "", "Ghostbusters (Genesis)", "Genesis controller", "", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c569e57dca93d3bee115a49923057fd7", "", "", "Pac-Space (Pac-Man Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c58708c09ccb61625cda9d15ddcd8be6", "SPIKE the Percussionist", "", "NOIZ Invaders (SPIKE) (2002) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5930d0e8cdae3e037349bfa08e871be", "Atari, Howard Scott Warshaw - Sears", "CX2655 - 49-75167", "Yars' Revenge (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c59633dbebd926c150fb6d30b0576405", "Telegames", "5861 A030", "Bogey Blaster (1988) (Telegames)", "AKA Air Raiders", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5a76bafc4676edb76e0126fb9f0fb2d", "Charles Morgan", "", "Zero Patrol (Charles Morgan) (Hack)", "Hack of Moon Patrol", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5bab953ac13dbb2cba03cd0684fb125", "SpiceWare - Darrell Spice Jr.", "", "Stay Frosty (SpiceWare)", "Part of Stella's Stocking 2007 Xmas compilation", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c5bf03028b2e8f4950ec8835c6811d47", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a2]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5c7cc66febf2d4e743b4459de7ed868", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1983) (Atari) (PAL) [a]", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5d2834bf98e90245e545573eb7e6bbc", "CCE", "", "Snoopy and the Red Baron (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5dd8399257d8862f3952be75c23e0eb", "Atari - GCC", "CX2680", "RealSports Tennis (1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5f71dfbdca9cc96b28643ff4d06aa6f", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c5fe45f2734afd47e27ca3b04a90213c", "Atari, Brad Stewart", "CX2622, CX2622P", "Breakout (1978) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "c63a98ca404aa5ee9fcff1de488c3f43", "Atari", "CX26145", "Venture (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c6556e082aac04260596b4045bc122de", "Atari - GCC, Dave Payne", "CX2669", "Vanguard (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6688781f4ab844852f4e3352772289b", "Atari, Tod Frye", "CX2695", "Xevious (08-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c67ff409f28f44883bd5251cea79727d", "", "", "Gunfight 2600 - Music & Bugfixes 1 (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c689148ad9275667924ab334107b517e", "Jone Yuan Telephonic Enterprise Co", "", "Space Raid (Jone Yuan)", "AKA MegaMania", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c68a6bafb667bad2f6d020f879be1d11", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6ae21caceaad734987cb24243793bd5", "CCE", "", "Frostbite (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6c63da3bc2e47291f63280e057061d0", "128-in-1 Junior Console", "", "Human Cannonball (128-in-1 Junior Console) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6d48c6ae6461e0e82753540a985ac9e", "Ed Federmeyer", "", "Edtris (1994) (Ed Federmeyer)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6d7fe7a46dc46f962fe8413c6f53fc9", "Parker Brothers, Mark Lesser", "PB5950", "Lord of the Rings (1983) (Parker Bros) (Prototype) [a]", "Journey to Rivendell (The Lord of the Rings I)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c6db733e0b108c2580a1d65211f06dbf", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (07-09-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c738fc3f5aae1e8f86f7249f6c82ac81", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari) (16K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, + { "c73ae5ba5a0a3f3ac77f0a9e14770e73", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c745487828a1a6a743488ecebc55ad44", "Rainbow Vision - Suntek", "SS-002", "Galactic (1983) (Rainbow Vision) (PAL)", "AKA The Challenge of.... Nexar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c74bfd02c7f1877bbe712c1da5c4c194", "Thomas Jentzsch", "", "River Raid Tanks (Thomas Jentzsch) (Hack)", "Hack of River Raid", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7600d72247c5dfa1ec1a88d23e6c85e", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (1 of 3) (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c77c35a6fc3c0f12bf9e8bae48cba54b", "Xonox - K-Tel Software - Action Graphics, Michael Schwartz, David Thiel", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox)", "", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c77d3b47f2293e69419b92522c6f6647", "Panda", "101", "Tank Brigade (1983) (Panda)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7900a7fe95a47eef3b325072ad2c232", "Larry Petit", "", "Super Congo Bongo (2003) (Larry Petit) (Hack)", "Hack of Bongo", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7d5819b26b480a49eb26aeb63cc831e", "Bit Corporation", "PGP210", "Ice Hockey (4 Game in One Light Green) (1983) (BitCorp) (PAL)", "AKA Hockey, Hockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7e43ad79c5e5c029d9f5ffde23e32cf", "", "", "PAL-NTSC Detector (15-11-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7eab66576696e11e3c11ffff92e13cc", "Atari - GCC", "CX2680, CX2680P", "RealSports Tennis (1983) (Atari) (PAL) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c7f13ef38f61ee2367ada94fdcc6d206", "Parker Brothers - Roklan, Joe Gaucher", "PB5370", "Popeye (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c82ec00335cbb4b74494aecf31608fa1", "CCE", "", "E.T. - The Extra-Terrestrial (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c830f6ae7ee58bcc2a6712fb33e92d55", "Atari, Michael Kosaka", "CX2687", "Tempest (01-05-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c866c995c0d2ca7d017fef0fc0c2e268", "Retroactive", "", "Qb (2.00) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c880c659cdc0f84c4a66bc818f89618e", "Thomas Jentzsch", "", "Open Sesame (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c89c3138a99fd1fd54367d65f75b0244", "Atari, Omegamatrix", "", "Space Invaders Menu (2020) (PAL) (Hack)", "Hack of Space Invaders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c8c7da12f087e8d16d3e6a21b371a5d3", "", "", "Demo Image Series #9 - Genius (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c8e90fc944596718c84c82b55139b065", "Atari - Roklan, Bob Curtiss", "", "Firefox (1983) (Atari) (Prototype) [a]", "AKA Combat II, Fighter Command", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c8fa5d69d9e555eb16068ef87b1c9c45", "Atari", "CX26144", "Donkey Kong Junior (1987) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c90788d9aa71a78bcc78c015edb22c54", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (PAL60) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c9196e28367e46f8a55e04c27743148f", "Atari", "CX26163P", "Stampede (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c92cfa54b5d022637fdcbdc1ef640d82", "Retroactive", "", "Qb (V2.05) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c98e8c918a40b4d3a243dd6c49196330", "AtariAge, Omegamatrix", "", "Venture Reloaded (2019) (AtariAge) (PAL60) (Hack)", "Transformative hack of Venture", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "c9b7afad3bfd922e006a6bfc1d4f3fe7", "Atari, Larry Kaplan - Sears", "CX2628 - 6-99842, 49-75117", "Bowling (1979) (Atari)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c9c25fc536de9a7cdc5b9a916c459110", "Activision, Mike Lorenzen", "AX-023", "Oink! (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c9d02d3cfeef8b48fb71cb4520a4aa84", "", "", "Euchre (More for less) (PAL) (22-08-2002) (Erik Eid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c9e721eb29c940c2e743485b044c0a3f", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "c9f6e521a49a2d15dac56b6ddb3fb4c7", "Parker Brothers, Rex Bradford", "PB5000", "Star Wars - Jedi Arena (1983) (Parker Bros)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 50", "", "", "", "", "", "", "", "" }, + { "ca09fa7406b7d2aea10d969b6fc90195", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ca4f8c5b4d6fb9d608bb96bc7ebd26c7", "M Network - INTV - APh Technological Consulting, Hal Finney, Glenn Hightower, Peter Kaminski", "MT4317", "Adventures of TRON (1983) (M Network)", "AKA Tron Joystick", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ca50cc4b21b0155255e066fcd6396331", "Suntek", "SS-031", "UFO Patrol (1983) (Suntek) (PAL)", "AKA X'Mission", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ca53fc8fd8b3c4a7df89ac86b222eba0", "CCE", "C-812", "Pac Man (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ca54de69f7cdf4d7996e86f347129892", "PlayAround - J.H.M.", "201", "Philly Flasher (1982) (PlayAround)", "Uses the Paddle Controllers, AKA Beat 'Em & Eat 'Em", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 45", "", "", "", "", "", "", "", "" }, + { "ca7aaebd861a9ef47967d31c5a6c4555", "Atari, Bob Whitehead", "CX26163P", "Homerun (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ca7abc774a2fa95014688bc0849eee47", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (1984) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ca7f166a94eed1a349dec6d6a358bcad", "Activision, Alan Miller - Ariola", "EAG-007, EAG-007-04I, PAG-007 - 711 007-720", "Tennis (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cac9928a84e1001817b223f0cecaa3f2", "Amiga - Video Soft, Jerry Lawson, Dan McElroy", "", "3-D Genesis (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cad982c9b45bc5eff34e4ea982d5f1ca", "", "", "Song (17-02-2003) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cade123747426df69570a2bc871d3baf", "Gakken", "011", "Marine Wars (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cae8f83c06831ec7bb6a3c07e98e9342", "Colin Hughes", "", "Tetris 2600 (Colin Hughes) [o1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cb18d8d5fbdcb1cd7bd36c5423348859", "", "", "RAM-Pong (NTSC) v1.0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb24210dc86d92df97b38cf2a51782da", "Video Gems", "VG-01", "Missile Control (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb4a7b507372c24f8b9390d22d54a918", "ITT Family Games", "554-37 338", "Peter Penguin (1983) (ITT Family Games) (PAL)", "AKA Frisco (Pumuckl-Serie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb8399dc0d409ff1f531ef86b3b34953", "", "", "Demo Image Series #12 - Luigi And Mario (01-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb9626517b440f099c0b6b27ca65142c", "Atari, Larry Kaplan - Sears", "CX2664 - 6-99818", "Brain Games (1978) (Atari) (4K)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb96b0cf90ab7777a2f6f05e8ad3f694", "Silvio Mogno", "", "Rainbow Invaders", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cb9b2e9806a7fbab3d819cfe15f0f05a", "Parker Brothers - JWDA, Todd Marshall, Robin McDaniel, Ray Miller", "931513", "Star Wars - Death Star Battle (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cba56e939252b05df7b7de87307d12ca", "", "", "Playfield Text Demo (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cbad928e10aeee848786cc55394fb692", "", "", "Fu Kung! (V0.06a Cuttle Cart Compatible) (15-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cbb0ee17c1308148823cc6da85bff25c", "", "", "Rotating Colors Demo 1 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cbc373fbcb1653b4c56bfabba33ea50d", "CCE", "", "Super Voleyball (CCE)", "AKA RealSports Volleyball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cbced209dd0575a27212d3eee6aee3bc", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2003", "Racquetball (1982) (Apollo) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cbd981a23c592fb9ab979223bb368cd5", "Atari, Carla Meninsky - Sears", "CX2660 - 49-75187", "Star Raiders (1982) (Atari)", "Uses Joystick (left) and Keypad (right) Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cbe5a166550a8129a5e6d374901dffad", "Atari, Carla Meninsky - Sears", "CX2610 - 49-75127", "Warlords (1981) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, + { "cbeafd37f15e0dddb0540dbe15c545a4", "", "", "Black and White Fast Scolling Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc03c68b8348b62331964d7a3dbec381", "Jone Yuan Telephonic Enterprise Co", "", "Marauder (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc12581e079cd18330a89902625b8347", "Dave Neuman", "", "Space Battle (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc1939e4769d0c157ace326efcfdcf80", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (3 of 4) (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc2973680c150886cce1ed8693c3aca2", "Quelle", "874.254 6", "Super-Cowboy beim Rodeo (1983) (Quelle) (PAL) (4K)", "AKA Stampede", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc3d942c6958bd16b1c602623f59e6e1", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc7138202cd8f6776212ebfc3a820ecc", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (03-30-1983) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc724ebe74a109e39c0b2784ddc980ca", "Atari, Jerome Domurat, Dave Staugas", "CX2682", "Krull (05-27-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cc74ddb45d7bc4d04c2e6f1907416699", "", "", "Colour Display Programme (1997) (Chris Cracknell)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cca33ae30a58f39e3fc5d80f94dc0362", "", "", "Okie Dokie (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ccb56107ff0492232065b85493daa635", "Bit Corporation", "PG206 [demonstration cartridge]", "Bobby Is Going Home (1983) (BitCorp) (PAL) [demo cart]", "AKA Bobby geht Heim", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ccb5fa954fb76f09caae9a8c66462190", "Answer Software Corporation - TY Associates, Mike Wentz", "ASC1001", "Malagai (1983) (Answer Software)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ccb807eb79b0ed0f5fdc460445ef703a", "", "", "Superman (Stunt_Cycle_Rules!) (Hack)", "Hack of Superman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ccbd36746ed4525821a8083b0d6d2c2c", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [no copyright]", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cccfe9e9a11b1dad04beba46eefb7351", "", "", "Poker Squares (V0.25) (PAL) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ccd6ce508eee4b3fca67212833edcd85", "Otto Versand", "746422", "Hot Wave (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Ram It", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ccd92a269a4c2bd64d58cf2c0114423c", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675", "Ms. Pac-Man (09-20-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd032ab6764b55438a7b0bfb5e78595a", "", "", "Hangman Pac-Man 4letter (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd139ae6d09f3665ad09eb79da3f9e49", "Eric Mooney", "", "Invaders by Erik Mooney (4-24-97) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd34b3b3ef9e485201e841ba71beb253", "Bradford W. Mott", "", "Hit HMOVE At Various Cycles After WSYNC Test (Bradford W. Mott) (1998) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd38ad19f51b1048d8e5e99c86a2a655", "", "", "Demo Image Series #5 - Flag (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd399bc422992a361ba932cc50f48b65", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (Preview) (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd3e26786136a4692fd2cb2dfbc1927e", "", "", "Multiple Moving Objects Demo 2 (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd4423bd9f0763409bae9111f888f7c2", "Jone Yuan Telephonic Enterprise Co", "", "River Raid (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd4ded1ede63c4dd09f3dd01bda7458c", "Future Video Games", "", "Laser Gate (Future Video Games) (PAL)", "AKA Innerspace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd568d6acb2f14477ebf7e59fb382292", "Videospielkassette - Ariola", "PGP235", "Fussball (Ariola) (PAL)", "AKA International Soccer", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd5af682685cfecbc25a983e16b9d833", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX26133", "A-Team, The (05-08-1984) (Atari) (Prototype)", "AKA Saboteur", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd88ef1736497288c4533bcca339f881", "SEGA - Teldec", "005-10", "Buck Rogers - Planet of Zoom (1983) (SEGA) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cd8fa2e9f6255ef3d3b9b5a4f24a54f7", "", "", "Daredevil (V2) (Stunt_Cycle_Rules!) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cd98be8a48ebf610c9609a688b9c57f2", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Arcadia) (Prototype)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cd9fea12051e414a6dfe17052067da8e", "Paul Slocum", "", "Marble Craze Demo (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cda38714267978b9a8b0b24bee3529ae", "", "", "Space Instigators (V1.6) (17-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cdadb57b34438805ee322ff05bd3d43e", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cdb81bf33d830ee4ee0606ee99e84dba", "Arcadia Corporation, Scott Nelson", "AR-4300", "Fireball (1982) (Arcadia) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "cdc1a5c61d7488eadc9aba36166b253d", "Retroactive", "", "Qb (V0.12) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cddabfd68363a76cd30bee4e8094c646", "Computer Magic - CommaVid, John Bronstein", "CM-001", "MagiCard (1981) (CommaVid)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce17325834bf8b0a0d0d8de08478d436", "", "", "Boring Freeway (Hack)", "Hack of Freeway", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce1cbe159b9ae5992dacf09371de5e13", "Atari - GCC, Kevin Osborn", "CX2689", "Kangaroo (01-19-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce243747bf34a2de366f846b3f4ca772", "Home Vision - Gem International Corp. - VDI", "", "Jacky Jump (1983) (Home Vision) (PAL)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce4bbe11d682c15a490ae15a4a8716cf", "", "", "Okie Dokie (Older) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce5524bb18e3bd8e092273ef22d36cb9", "Carrere Video - JWDA, Todd Marshall, Wes Trager, Henry Will IV - Teldec - Prism", "USC1004", "Commando Raid (1983) (Carrere Video) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce5cc62608be2cd3ed8abd844efb8919", "Atari - Bobco, Robert C. Polaro", "CX2663", "Road Runner (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce64812eb83c95723b04fb56d816910b", "Retroactive", "", "Qb (V2.04) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ce6c4270f605ad3ce5e82678b0fc71f8", "", "", "Vertical Rainbow Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce82a675c773ff21e0ffc0a4d1c90a71", "", "", "Defender 2 (Genesis)", "Genesis controller (C is smartbomb)", "Hack of Defender 2", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ce8467ae2a3a5bc88ca72a2ce44ce28c", "SOLID Corp. (D. Scott Williamson)", "CX2655-015", "Star Castle 2600 (SolidCorp) (PAL) [015]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ce89529d6e98a13ddf3d84827bbdfe68", "", "", "Kung Fu Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ce904c0ae58d36d085cd506989116b0b", "Telegames", "5687 A279", "International Soccer (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cea9f72036dc6f7af5eff52459066290", "Retroactive", "", "Qb (2.07) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ceba7965a93c689bdecdb46a5b2ac0c1", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Half-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cedbd67d1ff321c996051eec843f8716", "Ultravision", "1044", "Karate (1982) (Ultravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cef01595000627ee50863d4290372c27", "", "", "Many Blue Bars and Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cef2287d5fd80216b2200fb2ef1adfa8", "Milton Bradley Company", "4363", "Spitfire Attack (1983) (Milton Bradley)", "AKA Flight Commander)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cf0c593c563c84fdaf0f741adb367445", "Retroactive", "", "Qb (V0.05) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cf3a9ada2692bb42f81192897752b912", "", "", "Air Raiders (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cf3c2725f736d4bcb84ad6f42de62a41", "Rainbow Vision - Suntek", "SS-009", "Bermuda, The (1983) (Rainbow Vision) (PAL) [a]", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cf507910d6e74568a68ac949537bccf9", "SEGA, Jeff Lorenz", "003-01", "Thunderground (1983) (SEGA)", "AKA Underground", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cf63ffac9da89ef09c6c973083061a47", "CCE", "C-859", "MASH (1983) (CCE)", "AKA M.A.S.H", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cf9069f92a43f719974ee712c50cd932", "Video Gems", "VG-04", "Mission Survive (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cfad2b9ca8b8fec7fb1611d656cc765b", "Bit Corporation", "PG207", "Mission 3,000 A.D. (1983) (BitCorp) (PAL) [demo cart]", "demonstration cartridge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cfb3260c603b0341d49ddfc94051ec10", "Dactari - Milmar", "", "Boxing (Dactari - Milmar)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfb83a3b0513acaf8be4cae1512281dc", "Starpath Corporation", "", "Going-Up (1983) (Starpath) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfc226d04d7490b69e155abd7741e98c", "Atari, Matthew L. Hubbard", "CX26159", "Double Dunk (1989) (Atari) (PAL)", "AKA Super Basketball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfce5596a7e8ca13529e9804cad693ef", "Canal 3 - Intellivision", "", "Tennis (Canal 3) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfd5518c71552b8bb853b0e461e328d7", "Bit Corporation", "R320", "Spider Fighter (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfd6a8b23d12b0462baf6a05ef347cd8", "Activision, Larry Kaplan", "AX-006", "Bridge (1980) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfdb4d0427a1ea8085c6bc6eb90259d8", "", "", "Gunfight 2600 - Release Candidate (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfe2185f84ce8501933beb5c5e1fd053", "", "", "Football (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfe62ed7125ff9fae99b4c8a367c0399", "Activision, Larry Miller", "AX-026, AX-026-04", "Enduro (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfee10bd7119f10b136921ced2ee8972", "", "", "Space Instigators (V1.8) (19-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cfef1a2d1f6a5ee7a5e1f43f3056f112", "", "", "Skeleton+ (05-05-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cff1e9170bdbc29859b815203edf18fa", "Retroactive", "", "Push (V0.01) (1998) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cff578e5c60de8caecbee7f2c9bbb57b", "George Veeder", "", "Suicide Adventure (George Veeder) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "cff9950d4e650094f65f40d179a9882d", "Paul Slocum", "", "Mr. Roboto (Paul Slocum) (Hack)", "Hack of Berzerk", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "cfffc4b97d01cc3e7b9f47575f7b11ec", "Xonox - K-Tel Software, Anthony R. Henderson", "99007, 6240", "Tomarc the Barbarian (1983) (Xonox) (PAL60)", "Genesis controller (B is jump and throw, C switches between players)", "Hack of Tomarc the Barbarian", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d00f6f8ba89559e4b20972a478fc0370", "Spiceware", "SW-01", "Medieval Mayhem (PAL)", "", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "d010e3dfe7366e47561c088079a59439", "Retroactive", "", "Qb (V0.10) (Stella) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d026716b3c5be2c951cc4c064317c524", "", "", "Fu Kung! (V0.06) (14-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0498baca989e792db4b8270a02b9624", "", "", "Pac Ghost Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d071d2ec86b9d52b585cc0382480b351", "UA Limited", "", "Cat Trax (1983) (UA Limited) (1) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d078674afdf24a4547b4b32890fdc614", "Jone Yuan Telephonic Enterprise Co", "", "Laser Blast (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d078d25873c5b99f78fa267245a2af02", "SEGA - Beck-Tech, Steve Beck, Phat Ho", "006-01", "Congo Bongo (1983) (SEGA) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0796a0317abf9018d6745086bef411f", "Edward Smith", "", "Alien Attack (2018)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d08fccfbebaa531c4a4fa7359393a0a9", "Activision, David Crane, Bob Whitehead", "", "Venetian Blinds Demo (1981) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d090836f0a4ea8db9ac7abb7d6adf61e", "Hozer Video Games", "", "Yahtzee (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d09935802d6760ae58253685ff649268", "Telesys, Don Ruffcorn", "1006", "Demolition Herby (1983) (Telesys)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d09a7504ee8c8717ac3e24d263e7814d", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d09f1830fb316515b90694c45728d702", "Imagic, Brad Stewart", "720105-1A, IA3400", "Fire Fighter (1982) (Imagic)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0a379946ed77b1b126230ca68461333", "Ataripoll", "", "Atari Invaders (Ataripoll) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0af33865512e9b6900714c26db5fa23", "Telegames", "", "Armor Ambush (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0b26e908370683ad99bc6b52137a784", "Apollo - Games by Apollo, Larry Minor, Ernie Runyon, Ed Salvo - RCA Video Jeux", "AP-2004", "Lost Luggage (1982) (Apollo) (PAL)", "AKA La valise piegee", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0b9df57bfea66378c0418ec68cfe37f", "20th Century Fox Video Games - Sirius, Grady Ward", "11002", "Beany Bopper (1982) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0b9f705aa5f61f47a748a66009ae2d2", "", "", "Synthcart (14-01-2002) (Paul Slocum)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d0cb28e1b7bd6c7f683a0917b59f707e", "Atari, Gary Palmer", "CX2661P", "Fun with Numbers (1980) (Atari) (PAL) (4K)", "AKA Basic Math", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0cdafcb000b9ae04ac465f17788ad11", "Quelle - Otto Versand", "732.273 8 - 600273, 781644", "Lilly Adventure (1983) (Quelle) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0e05ba5f10e3df3023c5ee787f760ef", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0e15a3ce322c5af60f07343594392af", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) (4K)", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d0e9beb2347595c6c7d158e9d83d2da8", "Retroactive", "", "Qb (2.00) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d100b11be34a1e5b7832b1b53f711497", "", "", "Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d15655fe355fa57dd541487dc5725145", "Rentacom", "", "Vanguard (Rentacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d170317ae4c7d997a989c7d6567c2840", "Jone Yuan Telephonic Enterprise Co", "", "Stampede (Jone Yuan) (4K) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d175258b2973b917a05b46df4e1cf15d", "Suntek", "SS-032", "Walker (1983) (Suntek) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d17a671029b1532b197defca5f3649a7", "Hozer Video Games", "", "Gunfight 2600 - Limit broken again! (2001) (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d17a8c440d6be79fae393a4b46661164", "", "", "Warring Worms (Beta 3) (2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d1a1841b7f2007a24439ac248374630a", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (1 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d1a9478b99d6a55e13a9fd4262da7cd4", "U.S. Games Corporation, Garry Kitchen - Vidtec", "VC1001", "Space Jockey (1982) (U.S. Games) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d1b4075925e8d3031a7616d2f02fdd1f", "", "", "Demo Image Series #7 - Two Marios (27-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d1c3520b57c348bc21d543699bc88e7e", "Gameworld", "133-002", "Warplock (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01", "", "", "YES", "", "", "", "", "" }, + { "d1ca47b262f952413c1234117c4e4e21", "Bit Corporation", "R320", "Missile Command (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d1d704a7146e95709b57b6d4cac3f788", "Atari, Warren Robinett", "CX26163P", "Slot Racers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d20e61c86ed729780feca162166912ca", "Supergame", "32", "Pitfall (1984) (Supergame)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d214c7a734e133a5c18e93229435b57a", "Digivision", "", "Mickey (Digivision)", "AKA Sorcerer's Apprentice", "", "", "", "UASW", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d223bc6f13358642f02ddacfaf4a90c9", "Rainbow Vision - Suntek", "SS-003", "Pac-Kong (1983) (Rainbow Vision) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d245e2f27c84016041e9496b66b722fe", "", "", "Gunfight 2600 - The Final Kernel (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d25018349c544320bf3fd5092ee072bc", "Activision, Larry Miller", "AX-021", "Spider Fighter (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d28afe0517a046265c418181fa9dd9a1", "", "", "Dodge 'Em (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2901c34bb6496bb96c7bc78a9e6142a", "Greg Zumwalt", "", "Fish Revenge (2003) (Greg Zumwalt) (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2c4f8a4a98a905a9deef3ba7380ed64", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1001", "Sorcerer (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2c8e6aa8172b16c8aa9aae739ac9c5e", "Activision, David Crane", "08-08-1980", "Laser Blast (08-08-1980) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2c957dd7746521b51bb09fde25c5774", "Eckhard Stolberg", "", "Cubis (6K) (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2d8c4f1ea7f347c8bcc7d24f45aa338", "", "", "20 Sprites at Once Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2deddb77c8b823e4be9c57cb3c69adc", "Canal 3 - Intellivision", "C 3007", "Snoopy and the Red Baron (Canal 3)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d2f713c78a9ebba9da6d10aeefc6f20f", "Digivision", "", "Enduro (Digivision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d3171407c3a8bb401a3a62eb578f48fb", "ZiMAG - Emag - Vidco", "GN-080", "Spinning Fireball (1983) (ZiMAG) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d326db524d93fa2897ab69c42d6fb698", "Parker Brothers - Roklan, Paul Crowley, Bob Curtiss", "931505", "Super Cobra (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d339b95f273f8c3550dc4daa67a4aa94", "", "", "Laser Blast (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d341d39774277cee6a1d378a013f92ac", "Xonox, John Perkins", "6230, 7210, 06004, 99004", "Artillery Duel (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d3423d7600879174c038f53e5ebbf9d3", "U.S. Games Corporation - Western Technologies", "VC2005", "Piece o' Cake (1983) (U.S. Games)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "d3456b4cf1bd1a7b8fb907af1a80ee15", "Avalon Hill, Duncan Scott", "5003002", "Wall Ball (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d34b933660e29c0a0a04004f15d7e160", "", "", "Multi-Color Demo 5 (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d36308387241e98f813646f346e7f9f7", "King Atari", "", "Ghostbuster 2 (King Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d39e29b03af3c28641084dd1528aae05", "Funvision - Fund. Int'l Co.", "", "Spider Monster (1982) (Funvision) (PAL)", "AKA Spider Kong", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d3bb42228a6cd452c111c1932503cc03", "UA Limited", "", "Funky Fish (1983) (UA Limited) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d44d90e7c389165f5034b5844077777f", "Parker Brothers, Larry Gelberg", "PB5065", "Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d45bf71871b196022829aa3b96bfcfd4", "Activision, Steve Cartwright", "AX-017, AX-017-04", "MegaMania (1982) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d45ebf130ed9070ea8ebd56176e48a38", "SEGA, Jeff Lorenz", "001-01", "Tac-Scan (1983) (SEGA)", "Uses the Paddle Controllers (right only)", "", "", "", "", "", "", "", "YES", "", "", "YES", "", "", "AUTO 60", "", "", "YES", "", "", "", "", "" }, + { "d47387658ed450db77c3f189b969cc00", "PlayAround - J.H.M.", "206", "Westward Ho (1982) (PlayAround) (PAL)", "AKA Custer's Revenge", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d4806775693fcaaa24cf00fc00edcdf3", "Atari - Bobco, Robert C. Polaro", "CX26140, CX26140P", "Desert Falcon (1987) (Atari) (PAL)", "AKA Nile Flyer, Sphinx", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d483f65468d9a265661917bae1a54f3e", "Joe Grand", "", "SCSIcide Pre-release 3 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d4942f4b55313ff269488527d84ce35c", "Atari - GCC, Mark Ackerman, Glenn Parker", "CX2675, CX2675P", "Ms. Pac-Man (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d49aff83f77a1b9041ad7185df3c2277", "", "", "Space Treat (60% complete) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d4aa89e96d2902692f5c45f36903d336", "", "", "Euchre (NTSC) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d4c590ccfb611a73b3331359700c01a3", "", "", "Sprite Movement Demo 2 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d541b20eae221a8ee321375e5971e766", "Arcadia Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (Preview) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d54cd41ecfd59e4b72d2c086152b9a75", "Amiga - Video Soft - Michael K. Glass, Jerry Lawson", "1110", "Power Play Arcade Video Game Album (1983) (Amiga) (Prototype)", "3-D Ghost Attack only (3-D Genesis & 3-D Havoc missing in ROM)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d5618464dbdc2981f6aa8b955828eeb4", "CCE", "C-829", "Megamania (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d563ba38151b8204c9f5c9f58e781455", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d573089534ca596e64efef474be7b6bc", "Parker Brothers, John Emerson", "931511", "Action Force (1983) (Parker Bros) (PAL) [a]", "AKA G.I. Joe - Cobra Strike", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 55", "", "", "", "", "", "", "", "" }, + { "d57913088e0c49ac3a716bf9837b284f", "Activision, Garry Kitchen", "EAZ-032", "Pressure Cooker (1983) (Activision) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d57eb282d7540051bc9b5427cf966f03", "Atari Troll", "", "Custer's Viagra (Atari Troll) (Hack)", "Hack of Custer's Revenge", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d597d35c6022c590d6e75e865738558a", "", "", "Sprite Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5aa7472e7f2cc17e893a1a36f8dadf0", "", "", "Overhead Adventure Demo 5 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5c6b81212ad86fd9542a1fedaf57cae", "", "", "Sprite Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5d2d44fb73785996ccc24ae3a0f5cef", "Robby", "", "Grand Prix (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5e17022d1ecc20fd9b53dc464c302f1", "Activision, Carol Shaw", "EAX-020", "River Raid (1982) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5e27051512c1e7445a9bf91501bda09", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5e5b3ec074fff8976017ef121d26129", "Star Game", "003", "River Raid (Star Game)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d5f965c159e26a1fb49a22a47fbd1dd0", "Supergame", "", "River Raid II (Supergame)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d605ed12f4eaaaec3dcd5aa909a4bad7", "", "", "Chronocolor Frame Demo (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d61629bbbe035f45552e31cef7d591b2", "", "", "Atari Logo Demo (PD) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d62283aed0f4199adb2333de4c263e9c", "Atari, Alan J. Murphy, Nick 'Sandy Maiwald' Turner", "CX2615", "Demons to Diamonds (1982) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 57", "", "", "", "", "", "", "", "" }, + { "d62d7d1a974c31c5803f96a8c1552510", "", "", "StarMaster (Unknown) (PAL)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d632b74fea533d593af82cf16e7c5e4a", "", "", "Fu Kung! (V0.13) (01-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d65028524761ef52fbbdebab46f79d0f", "CCE", "", "Galaxian (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d65900fefa7dc18ac3ad99c213e2fa4e", "", "", "Guntest (2000) (Eckhard Stolberg)", "Light Gun Test (based on Sentinel code)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d69559f9c9dc6ef528d841bf9d91b275", "Activision, Alan Miller", "AX-016", "StarMaster (1982) (Activision)", "Use Color/BW switch to change between galactic chart and front views", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6a44277c3eb4f9d039185e0ecf7bfa6", "", "", "Trick (1997) (Eckhard Stolberg)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6acff6aed0f04690fe4024d58ff4ce3", "Spectravision - Spectravideo - Quelle", "SA-202 - 412.851 8", "Planet Patrol (1982) (Spectravision) (PAL) [different spaceship]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6b8beeb05e5b730084d4b8f381bbf8d", "", "", "208 in 1 Game Select ROM (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6d1ddd21e9d17ea5f325fa09305069c", "Funvision - Fund. International Co.", "", "Time Warp (1982) (Funvision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6d5dd8fd322d3cf874e651e7b6c1657", "", "", "How to Draw a Playfield (1997) (Nick Bensema) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d6dc9b4508da407e2437bfa4de53d1b2", "Bomb - Onbase", "CA283", "Z-Tack (1983) (Bomb) (PAL)", "AKA Base Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d726621c676552afa503b7942af5afa2", "Atari, Bob Whitehead", "CX26163P", "Blackjack (32 in 1) (1988) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d73ad614f1c2357997c88f37e75b18fe", "Goliath", "7", "Space Tunnel (1983) (Goliath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d74a81fcd89c5cf0bd4c88eb207ebd62", "", "", "Poker Squares (V0.00a) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d763e3a9cdcdd56c715ec826106fab6a", "Activision, David Crane", "AG-001", "Dragster (1980) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d7759fa91902edd93f1568a37dc70cdb", "Atari, Robert C. Polaro", "CX26157", "Stunt Cycle (1980) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d782543818b6320e4f60d77da2b596de", "Atari", "CX26163P", "Fishing Derby (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d787ec6785b0ccfbd844c7866db9667d", "Retroactive", "", "Qb (V0.04) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d7891b0faa4c7f764482762d0ed427a5", "", "", "Bars and Text Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d7b2259f6bb57bf37eac82365c1f8ad6", "Parker Brothers, Mike Brodie", "PB5320", "Super Cobra (1983) (Parker Bros) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d7b58303ec8d8c4dbcbf54d3b9734c7e", "", "", "Paddle Demo (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d7dd56677e4ec1e6627419478a4a9668", "", "", "Shadow Keep (Fixed) (04-03-2003) (Andrew Towers)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d7f5bf138cfc7feab7b8ef1534c8b477", "", "", "Eric Bergstrom's KC-135 (Radar Map) (Aaron Bergstrom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d816fea559b47f9a672604df06f9d2e3", "Atari, Gary Palmer", "CX26163P", "Fun with Numbers (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d81bb6965e6c99b3be99ffd8978740e4", "", "", "Gunfight 2600 - The Final Kernel Part 3 (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d82675ce67caf16afe5ed6b6fac8aa37", "Thomas Jentzsch", "", "Robot City (V0.23) (13-11-2002) (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d8295eff5dcc43360afa87221ea6021f", "Spectravideo", "SA-212", "Mangia' (1983) (Spectravideo) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d82c8a58098a6b46c5b81c16180354d1", "Dennis Debro", "", "Climber 5 (30-10-2002) (Dennis Debro) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d85f1e35c5445ac898746719a3d93f09", "Suntek", "SS-034", "Farmyard Fun (1983) (Suntek) (PAL)", "AKA Play Farm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d86deb100c6abed1588aa84b2f7b3a98", "Atari, Bob Whitehead - Sears", "CX2625 - 6-99827, 49-75114", "Football (1979) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d88691c995008b9ab61a44bb686b32e4", "", "", "Warring Worms (07-02-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d89262907e70c13dff23356c4a9055d0", "Bit Corporation", "R320", "Video Pinball (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d89fedded0436fdeda7c3c37e2fb7cf1", "", "", "Surround (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d8acaa980cda94b65066568dd04d9eb0", "CCE", "", "Sea Hunt (CCE)", "AKA Skindiver", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d8b2c81cea5af04f795eb3dc6573d72b", "", "", "Tunnel Demo 2 (27-03-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d8df256c0d89e494a9fb3e9abb8e44ac", "Imagic, Michael Greene", "IA3312P", "No Escape! (1982) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d8e4c8e2d210270cd1e0f6d1b4582b91", "Imagic, Mark Klein", "EIZ-003-04I", "Subterranea (1983) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d90205e29bb73a4cdf28ea7662ba0c3c", "Thomas Jentzsch", "", "Boulderdash Demo (Brighter Version) (09-12-2002) (TJ)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d912312349d90e9d41a9db0d5cd3db70", "CCE", "C-818", "Star Voyager (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d9548ad44e67edec202d1b8b325e5adf", "Apollo - Games by Apollo, Dan Oliver - RCA Video Jeux", "AP-2002", "Space Cavern (1982) (Apollo) (PAL)", "AKA Les guerriers de l'espace", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d968de2b4ff18bfe4a95066cde310578", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (PAL) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d97e3d0b4575ce0b9a6132e19cfeac6e", "Fabrizio Zavagli", "", "Space Treat (061002) (PD)", "Won't work with Stella < V1.2", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d97fd5e6e1daacd909559a71f189f14b", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (04-20-1983) (M Network) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d9ab6b67a17da51e5ad13717e93fa2e2", "Thomas Jentzsch", "", "Turbo (Coleco) Prototype Fake v0.1 (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d9b49f0678776e04916fa5478685a819", "Activision, John Van Ryzin - Ariola", "EAZ-036-04, EAZ-036-04B, EAZ-036-04I - 711 036-720", "H.E.R.O. (1984) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d9bd343533b61389b270c0787210943b", "Atari, Douglas 'Solaris' Neubauer", "CX26134", "Last Starfighter (1984) (Atari) (Prototype)", "Genesis controller (C switches to map mode)", "Hack of Last Starfighter (Solaris prototype)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "d9c9cece2e769c7985494b1403a25721", "SOLID Corp. (D. Scott Williamson)", "CX2655*", "Star Castle 2600 (SolidCorp)", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "d9da2ae7c7894a29b43b3c6b79f3b7a2", "Atari, Rob Fulop", "CX2633, CX2633P", "Night Driver (1980) (Atari) (PAL) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "d9fbf1113114fb3a3c97550a0689f10f", "ZiMAG - Emag - Vidco", "713-111 - GN-050", "Pizza Chef (1983) (ZiMAG) (Prototype)", "AKA Pizza Time", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da0fb2a484d0d2d8f79d6e063c94063d", "", "", "Air Raiders (1982) (Unknown) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da4e3396aa2db3bd667f83a1cb9e4a36", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da5096000db5fdaa8d02db57d9367998", "Digitel", "", "River Raid (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da6465a34d2e44d26aa9a2a0cd1bce4d", "Absolute Entertainment, Alex DeMeo", "AG-041-04", "Title Match Pro Wrestling (1987) (Absolute) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da66d75e4b47fab99733529743f86f4f", "Digitel", "", "Chopper Command (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "da732c57697ad7d7af414998fa527e75", "Atari - Glenn Axworthy", "CX26129", "Midnight Magic (1986) (Atari) (PAL)", "AKA Pinball Wizard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "da79aad11572c80a96e261e4ac6392d0", "Salu - Ubi Soft, Dennis M. Kiss", "460673", "Pick 'n' Pile (1990) (Salu) (PAL)", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "da7a17dcdaa62d6971393c0a6faf202a", "", "", "Flag Capture (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dab844deed4c752632b5e786b0f47999", "", "", "Super Challenge Baseball (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dac38b4dd3da73bb7b2e9d70c61d2b7c", "", "", "Hangman Monkey Biglist3 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dac5c0fe74531f077c105b396874a9f1", "Atari - GCC", "CX2680", "RealSports Tennis (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dac762e4d01d445bdef20b7771f6570e", "Atari, Carla Meninsky, Ed Riddle - Sears", "CX2611 - 99821, 49-75149", "Indy 500 (1977) (Atari) (4K) [a]", "Uses the Driving Controllers", "", "", "", "", "", "", "", "", "DRIVING", "DRIVING", "", "", "", "45", "", "", "", "", "", "", "", "" }, + { "dad2ab5f66f98674f12c92abcfbf3a20", "", "", "Blue and White Sprite Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "daeb54957875c50198a7e616f9cc8144", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11005", "Mega Force (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "daef7d8e5a09981c4aa81573d4dbb380", "Adam Thornton", "", "Lord of the Rings (Adam Thornton) (Hack)", "Hack of Dark Mage", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dafc3945677ccc322ce323d1e9930beb", "Atari", "", "A-Team (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db1753cc702c18d3917ec7f3b0e8659f", "", "", "Frame Counter 2 (2001) (Jake Patterson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db339aea2b65b84c7cfe0eeab11e110a", "", "", "Chronocolor Frame Demo 2 (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db4eb44bc5d652d9192451383d3249fc", "CBS Electronics - E.F. Dreyer - VSS, Ed Salvo", "4L 2738 0000", "Mountain King (1983) (CBS Electronics)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "db5073bd75eb05f7d62a7268396d1e77", "Atari", "CX26163P", "Golf (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db76f7a0819659d9e585f2cdde9175c7", "Xonox", "99005, 6220, 6250", "Robin Hood (1983) (Xonox) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db80d8ef9087af4764236f7b5649fa12", "M Network, Steve Crandall, Patricia Lewis Du Long", "MT4646", "Rocky & Bullwinkle (1983) (Mattel) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "db971b6afc9d243f614ebf380af0ac60", "Gammation, Robert L. Esken Jr.", "", "Gamma-Attack (1983) (Gammation)", "Uses right joystick controller", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dba270850ae997969a18ee0001675821", "Greg Troutman", "", "Dark Mage (Greg Troutman) (PD) (4K)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dbabb80e92ff18d8eecf615c0539151e", "", "", "Sprite Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dbb10b904242fcfb8428f372e00c01af", "Atari, John Dunn", "CX2631, CX2631P", "Superman (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dbba14a0f69f0e13fdccb3fde3baedca", "Thomas Jentzsch", "", "Reactor - Atari Trak-Ball Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dbc7485ad5814d466de780a3e7ed3b46", "Kyle Pittman", "", "Pink Floyd (Kyle Pittman) (PD)", "Hack of Adventures of Tron (Mattel)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dbc8829ef6f12db8f463e30f60af209f", "Data Age", "DA1001", "Encounter at L-5 (1982) (Data Age)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, + { "dbdaf82f4f0c415a94d1030271a9ef44", "CCE", "", "Kaboom! (CCE)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "dbdd21e1ee3d72119e8cd14d943c585b", "", "", "Slot Machine (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dc13df8420ec69841a7c51e41b9fbba5", "Atari, Mimi Nyden, Steve Woita", "CX26132", "Garfield (06-21-1984) (Atari) (Prototype)", "AKA Garfield on the Run", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dc33479d66615a3b09670775de4c2a38", "Suntek", "SS-033", "I.Q. Memory Teaser (1983) (Suntek) (PAL)", "AKA IQ 180", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dc81c4805bf23959fcf2c649700b82bf", "Imagic, Michael Greene", "720055-2A, IA3312P", "No Escape! (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dc905b22de0f191a029df13eddfcabc4", "Atari, Warren Robinett", "", "Elf Adventure (05-02-83) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dc97cbcf091a5ef4ca7fe95dc0848036", "Atari - Roklan, Joe Gaucher, Alex Leavens", "CX2683", "Crazy Climber (1983) (Atari) (Prototype) [a2]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dca90ea1084a2fdbe300d7178ca1a138", "Imagic, Dennis Koble", "IA3000P", "Trick Shot (1982) (Imagic) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dca941dab5c6f859b71883b13ade9744", "", "", "Hangman Pac-Man Biglist2 (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dcba0e33aa4aed67630a4b292386f405", "Retroactive", "", "Qb (V2.08) (Half Speed Version) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dcc2956c7a39fdbf1e861fc5c595da0d", "M Network - INTV - APh Technological Consulting, David Rolfe", "MT5664", "Frogs and Flies (1982) (M Network)", "AKA Frogs 'n' Flies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dcec46a98f45b193f07239611eb878c2", "", "", "Bars and Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd08e18cfee87a0e7fc19a684b36e124", "Atari - GCC, Kevin Osborn", "CX2689, CX2689P", "Kangaroo (1983) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd0cbe5351551a538414fb9e37fc56e8", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99006, 6220", "Sir Lancelot (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd0de0f61af2a2a4878e377b880a3933", "SOLID Corp. (D. Scott Williamson)", "CX2655-013", "Star Castle 2600 (SolidCorp) [013]", "http://starcastle2600.blogspot.com/p/star-castle-2600-story.html", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dd10b5ee37fdbf909423f2998a1f3179", "", "", "Space Instigators (V1.9) (21-10-2002) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd13a16d14100819f79b1ce3a5bf499c", "Thomas Jentzsch", "", "Missile Control - Atari Mouse Hack v1.15 (PAL) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd1422ffd538e2e33b339ebeef4f259d", "Atari, Michael Sierchio", "", "Football Demo (1982) (Atari)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd17711a30ad60109c8beace0d4a76e8", "", "", "Karate (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd1842ba0f3f9d94dccb21eaa0f069b7", "Bit Corporation", "R320", "Defender (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd45e370aceff765f1e72c619efd4399", "Bit Corporation", "PG201", "Sea Monster (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd4f4e0fbd81762533e39e6f5b55bb3a", "Thomas Jentzsch", "", "Turbo WIP (TJ)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd7598b8bcb81590428900f71b720efb", "Xonox - K-Tel Software - Computer Magic", "99005, 6220, 6250", "Robin Hood (1983) (Xonox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd7884b4f93cab423ac471aa1935e3df", "Atari, Brad Stewart - Sears", "CX2649, 49-75163", "Asteroids (1981) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "dd8a2124d4eda200df715c698a6ea887", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (3 of 3) (1982) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dd92d6ad50976f881d86b52d38616118", "SpkSoft", "", "River Raid (SpkSoft) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dda23757407c4e217f64962c87ad0c82", "Atari Freak 1", "", "Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack) [a]", "Hack of Pac-Man Jr.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ddd1efc1862cd3eb3baf4cba81ff5050", "", "", "Max3 (2001) (Maxime Beauvais) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de0173ed6be9de6fd049803811e5f1a8", "Xonox - K-Tel Software - Product Guild, Anthony R. Henderson", "99008, 6240", "Motocross Racer (1983) (Xonox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de07e9cb43ad8d06a35f6506e22c62e9", "", "", "Oh No! (Version 4) (22-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de1a636d098349be11bbc2d090f4e9cf", "", "", "Pressure Gauge (Hozer Video Games)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de1e9fb700baf8d2e5ae242bffe2dbda", "Activision - Imagineering, Mike Reidel", "EAK-043-04I", "Commando (1988) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de24f700fd28d5b8381de13abd091db9", "CCE", "", "Plaque Attack (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de29e46dbea003c3c09c892d668b9413", "Coleco - Woodside Design Associates, Steve 'Jessica Stevens' Kitchen", "4L1717, 4L1718, 4L1719, 4L2277", "Carnival (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de3d0e37729d85afcb25a8d052a6e236", "Spectravision - Spectravideo", "SA-204", "Tapeworm (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "de4436eaa41e5d7b7609512632b90078", "Activision, David Crane", "AX-014, AX-014-04", "Grand Prix (1982) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de5aab22e5aba5edcb29a3e7491ff319", "Star Game", "001", "Donkey Kong (Star Game)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de61a0b171e909a5a4cfcf81d146dbcb", "Rainbow Vision - Suntek", "SS-005", "Tom Boy (1983) (Rainbow Vision) (PAL)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de62f8a30298e2325249fe112ecb5c10", "CCE", "C-810", "Enduro (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de78b3a064d374390ac0710f95edde92", "Bomb - Onbase", "CA281", "Assault (1983) (Bomb)", "AKA Sky Alien", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de7a64108074098ba333cc0c70eef18a", "", "", "Nuts (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de7bca4e569ad9d3fd08ff1395e53d2d", "Thomas Jentzsch", "", "Thrust (V1.22) (2000) (TJ)", "Supports BoosterGrip", "New Release", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "de8443ff47283e7b274a7838cb071fb6", "Atari, Lou Harp", "CX26122", "Sinistar (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dea0ade296f7093e71185e802b500db8", "CCE", "", "Fishing Derby (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "deb39482e77f984d4ce73be9fd8adabd", "Activision, David Lubar", "AK-048-04", "River Raid II (1988) (Activision) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ded26e1cb17f875a9c17515c900f9933", "", "", "Space Treat (29-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df12953b919844dad2070ed2e70c9fa2", "Amiga - Video Soft", "3135", "S.A.C. Alert (1983) (Amiga) (Prototype) (PAL)", "Uses Joyboard", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df2745d585238780101df812d00b49f4", "Bit Corporation", "PG202", "Space Tunnel (1982) (BitCorp)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df3e6a9b6927cf59b7afb626f6fd7eea", "", "", "Tuby Bird (208 in 1) (Unknown) (PAL)", "AKA Dolphin", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df40af244a8d68b492bfba9e97dea4d6", "Franklin Cruz", "", "Asteroids 2 (Franlin Cruz) (Hack)", "Hack of Asteroids", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "df5cc5cccdc140eb7107f5b8adfacda1", "Cracker Jack Productions", "", "Lumberman (Cracker Jack) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df62a658496ac98a3aa4a6ee5719c251", "Atari, Tom Reuterdahl - Sears", "CX2626 - 6-99829, 49-75116", "Miniature Golf (1979) (Atari)", "AKA Arcade Golf", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df6a28a89600affe36d94394ef597214", "Apollo - Games by Apollo, Dan Oliver", "AP-2002", "Space Cavern (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df6a46714960a3e39b57b3c3983801b5", "Puzzy - Bit Corporation", "PG201", "Sea Monster (1982) (Puzzy) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df753cb87d3af4d03f694ab848638108", "CBS Electronics, Bob Curtiss", "4L1845, 4L1852, 4L1853, 4L1854", "Solar Fox (1983) (CBS Electronics) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df91277a3569344b89e6e8bd5bebc8d1", "Thomas Jentzsch", "", "Marble Craze - Amiga Mouse Hack v1.0 (PAL) (TJ)", "Uses Amiga Mouse Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "df95e4af466c809619299f49ece92365", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (06-03-1983) (Atari) (Prototype) (PAL)", "Uses Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfad86dd85a11c80259f3ddb6151f48f", "HES - Imagineering, David Lubar", "535", "My Golf (1990) (HES) (PAL) [fixed]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfafa3fa58f5cc3f0342cca475df6095", "", "", "Space Treat (V1.1 Beta) (24-12-2002) (Fabrizio Zavagli)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfc03ef371cf5163f54c50d8ee73c8cf", "Atari, Gary Palmer", "CX2661", "Fun with Numbers (1980) (Atari) (4K)", "AKA Basic Math", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfc3dbbb39f05d7dd8ee3ac987478970", "", "", "Imagic Selector ROM (1982) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfcdd6f593bb7b05dbc2e8e1fc6ee0de", "", "", "Gunfight 2600 - Scenarios complete (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfe034297200dff672df9533ed1449a9", "", "", "Sprite Movement Demo 1 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dfe6aa7443bb813cefa35a4cf4887422", "", "", "This Planet Sucks (Greg Troutman) [a1]", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "dff33523ccd2fdc8912e84cab8e0d982", "", "", "Fu Kung! (V0.03) (10-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e01e00504e6d4b88fa743c0bbe8a96e5", "", "", "Qb (Special Edition, some bugfixes) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e020f612255e266a8a6a9795a4df0c0f", "Telegames - VSS", "7062 A305", "Universal Chaos (1988) (Telegames) (PAL)", "AKA Targ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e02156294393818ff872d4314fc2f38e", "Sancho - Tang's Electronic Co.", "TEC005", "Dice Puzzle (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e0221c95aa657f5764eeeb64c8429258", "", "", "Tomb Raider 2600 [REV 02] (Montezuma's Revenge Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e03b0b091bea5bc9d3f14ee0221e714d", "CBS Electronics, Bob Curtiss", "4L1852, 4L1853, 4L1854, 4L1855", "Solar Fox (1983) (CBS Electronics) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e040df95a055b18ebdb094e904cb71b2", "", "", "Score Demo (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e04f1c1e4401d584d3f4343410a5bcc4", "Wizard Video Games - MicroGraphic Image, Robert Barber, Tim Martin", "007", "Halloween (1983) (Wizard Video Games) (Prototype) [a]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e0b24c3f40a46cda52e29835ab7ad660", "Quelle - Otto Versand", "626.502 9 - 746381", "Top Gun (1983) (Quelle) (PAL)", "AKA Air Raiders", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e0cf2dcc4c1348c468f5bb1e421c9164", "", "", "Invader Sprites in a Line Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e0de3773f5b867795db557be7b8a703e", "", "", "Boulderdash (13 Blocks Wide) (02-04-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e0eff071f578ecf19edc2ab276644e46", "", "", "Gas Gauge Demo (2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1029676edb3d35b76ca943da7434da8", "Atari, Robert C. Polaro, Alan J. Murphy - Sears", "CX2609 - 49-75186", "Defender (10-30-1981) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e10bf1af6bf3b4a253c5bef6577fe923", "Rob Kudla", "", "Space Invaders (1978) (Atari) [h1]", "Hack of Space Invaders (Atari)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e10d2c785aadb42c06390fae0d92f282", "Parker Brothers, Dawn Stockbridge", "PB5910", "Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1143b72a30d4d3fee385eec38b4aa4d", "", "", "Word Zapper (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e12e32dee68201b6765fcd0ed54d6646", "Atari, Larry Kaplan", "CX2612, CX2612P", "Street Racer (1977) (Atari) (PAL)", "Uses the Paddle Controllers (swapped)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "AUTO 75", "", "", "", "", "", "", "", "" }, + { "e13818a5c0cb2f84dd84368070e9f099", "CCE", "C-839", "Misterious Thief, A (1983) (CCE)", "AKA A Mysterious Thief", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e13c7627b2e136b9c449d9e8925b4547", "Atari, Alan Miller - Sears", "CX2624 - 6-99826, 49-75113", "Basketball (1978) (Atari) (4K)", "", "Common", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1486c7822c07117b4f94a32e5ed68c1", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (06-14-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e14dc36b24fe22c04fa076e298f2e15f", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (16K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "e14feddeb82f5160ed5cf9ca4078e58d", "", "", "SpaceMaster X-7 (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e150f0d14f013a104b032305c0ce23ef", "Spectravision - Spectravideo", "SA-205", "China Syndrome (1982) (Spectravision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e15b5525cf8f77297b322838df8d999c", "", "", "Sprite Demo 0 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e171558c51bb3bac97bfa79fa2c1a19c", "", "", "Warring Worms (Tim Strauss Edition) (20-12-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e17699a54c90f3a56ae4820f779f72c4", "Rainbow Vision - Suntek", "SS-020", "Tuby Bird (1983) (Rainbow Vision) (PAL)", "AKA Dolphin", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e18abe87035379c56b435bfe8175077b", "Grimlock", "", "Rumble 2600 (Grimlock) (Hack)", "Hack of Mario Bros.", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1a51690792838c5c687da80cd764d78", "20th Century Fox, John Russell", "", "Alligator People (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1b90f1e01b1a316d7bbf141525cc00e", "", "", "Sky Jinks (Unknown) (PAL) (4K) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1d5c8213e82820128fa9c4775f1e166", "Jess Ragan", "", "Jungle King (2003) (Jess Ragan) (Hack)", "Hack of Jungle Hunt", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1d79e4e7c150f3861256c541ec715a1", "", "", "Space Jockey (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1e09e2f280e8e142121a377d0dc1b46", "Thomas Jentzsch", "", "Thrust (V1.21) (2000) (TJ)", "Bugfixed", "New Release", "", "", "", "", "", "", "", "BOOSTERGRIP", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1efe2ef7664bb6758b1a22ff8ea16a1", "Dynacom", "", "Enduro (1983) (Dynacom)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e1f88da6da8a7d521ca1dcbf2bc6978b", "Activision, Bob Whitehead - Ariola", "EAG-005, PAG-005, EAG-005-04B - 711 005-715", "Skiing (1980) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e21ee3541ebd2c23e817ffb449939c37", "Tigervision - Software Electronics Corp., Karl T. Olinger - Teldec", "7-001", "King Kong (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e227be19f572f6900e314213ae9a4deb", "Atari, Dan Hitchens, Mimi Nyden", "CX2656", "SwordQuest - EarthWorld (1982) (Atari) (Prototype)", "AKA Adventure I, SwordQuest I - EarthWorld", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e237ee91514d5ed535c95a14fc608c11", "Activision, Matthew L. Hubbard, Bob Whitehead", "AX-024", "Dolphin (1983) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2389c0be5b5b84e0d3ca36ec7e67514", "Retroactive", "", "Qb (V2.09) (NTSC) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e24d7d879281ffec0641e9c3f52e505a", "Parker Brothers, Mark Lesser", "PB5950", "Lord of the Rings (1983) (Parker Bros) (Prototype)", "Journey to Rivendell (The Lord of the Rings I)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e25e173740f7ecc0e23025445c4591f3", "Greg Zumwalt", "", "Comitoid (Greg Zumwalt)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e275cbe7d4e11e62c3bfcfb38fca3d49", "M Network - INTV - APh Technological Consulting, Ken Smith", "MT5658", "Super Challenge Football (1982) (M Network)", "AKA Pro Football", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e27d518993b0a010f16e92b971ecdcdd", "Manuel Polik", "", "Star Fire (2003) (XYPE) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e28113d10c0c14cc3b5f430b0d142fcb", "CCE", "C-816", "Keystone Kappers (1983) (CCE) [a]", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2846af3e4d172b251ab77cbdd01761e", "Steve Engelhardt", "", "Adventure Plus (2003) (Steve Engelhardt) (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2904748da63dfefc8816652b924b642", "Jone Yuan Telephonic Enterprise Co", "", "Catch Time (Jone Yuan)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2b682f6e6d76b35c180c7d847e93b4f", "", "", "Dodge Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2c1b60eaa8eda131632d73e4e0c146b", "Atari - GCC, Mark Ackerman, Noellie Alito", "CX2692", "Moon Patrol (07-04-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2c89f270f72cd256ed667507fa038a2", "Starpath Corporation, Stephen H. Landrum", "AR-4101", "Communist Mutants from Space (1982) (Arcadia) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e2ca84a2bb63d1a210ebb659929747a9", "Telesys, Don 'Donyo' Ruffcorn", "1002", "Cosmic Creeps (1982) (Telesys) (PAL)", "AKA Space Maze, Spaze Maze", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e2eccbbe963f80f291cb1f18803bf557", "Atari, Joe Decuir, Steve Mayer, Larry Wagner", "CX26163P", "Combat (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e30f3a37032da52d7815b5a409f6d4b4", "SEGA, Fred Mack", "", "Bear Game Demo (1983) (SEGA)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e314b42761cd13c03def744b4afc7b1b", "Activision, David Crane, Dan Kitchen", "AZ-108-04", "Ghostbusters (1985) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e34c236630c945089fcdef088c4b6e06", "Activision, Steve Cartwright, David Crane - Ariola", "EAB-035-04 - 711 035-721", "Pitfall II (1984) (Activision) (PAL)", "Lost Caverns", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e3533684a7ef930a7fbd0c4dd8ec4847", "CCE", "C-856", "Pimball (1983) (CCE)", "AKA Video Pinball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e3600be9eb98146adafdc12d91323d0f", "Atari, Carol Shaw", "CX2618, CX2618P", "3-D Tic-Tac-Toe (1980) (Atari) (PAL)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e363e467f605537f3777ad33e74e113a", "Atari, Bob Whitehead - Sears", "CX2603 - 99803, 49-75601", "Star Ship (1977) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e377c3af4f54a51b85efe37d4b7029e6", "20th Century Fox Video Games, Beck-Tech, Steve Beck", "11035", "Save the Whales (1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e37c8055d70979af354251ebe9f1b7dd", "HES", "", "Mega Funpak - Gorf, P. Patrol, Pacman, Skeet Shoot (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e38dc1f81a02e325562cd285123f579b", "Atari - GCC, Mike Feinstein", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e39843c56b7a4a08b18fa7949ec3ee6b", "", "", "Joshua Invaders (Hack)", "Hack of Space Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e39a13b13dc82c5fdbfbbfd55ba1230e", "", "", "Analog Clock (Additional Frame Info) (V0.0) (20-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e3c0451d29dad724231bc5818ec4bae0", "", "", "Single-Scanline Positioning Demo 1 (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e3c35eac234537396a865d23bafb1c84", "TechnoVision - Video Technology", "TVS1001", "Nuts (1983) (TechnoVision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e3ed4ba3361756970f076e46e9cad1d2", "", "", "Tennis (Unknown) (PAL) (4K) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e40a818dac4dd851f3b4aafbe2f1e0c1", "Atari, Bill Aspromonte, Dr. Lee Salk", "CX26135", "Peek-A-Boo (1984) (Atari) (Prototype)", "Uses the Keypad Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e42b937c30c617241ca9e01e4510c3f6", "", "", "Pitfall! (No Walls Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e434c0e161dd3c3fb435eb6bad2e182c", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681", "Battlezone (05-02-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e48d3a4056ede9393586421996db1ae8", "Thomas Jentzsch", "", "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Full-Speed) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e49ac0ec879a0d7820bc2598fc2cfcd4", "CCE", "", "Kaboom! (CCE) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "e4a0b28befaaa2915df1fa01238b1e29", "", "", "Gunfight 2600 - Red River (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4afe157c09962cf39cdb25845d83d47", "Activision, David Crane - Ariola", "EAG-009, PAG-009 - 711 009-720", "Freeway (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4b12deaafd1dbf5ac31afe4b8e9c233", "Adam Thornton", "", "Lord of the Rings (Adam Thornton) (Hack) [a]", "Hack of Dark Mage", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e4bff1d5df70163c0428a1ead309c22d", "Atari, Robert C. Polaro, Alan J. Murphy", "CX2609, CX2609P", "Defender (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4c00beb17fdc5881757855f2838c816", "20th Century Fox Video Games - Sirius, Ed Hodapp", "11004", "Deadly Duck (1982) (20th Century Fox)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4c2077a18e3c27f4819aa7757903aa0", "", "", "Many Blue Bars Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4c666ca0c36928b95b13d33474dbb44", "Arcadia Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Arcadia)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e4d41f2d59a56a9d917038682b8e0b8c", "Cody Pittman", "", "Kiss Meets Pacman (Cody Pittman) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4e9125a8741977583776729359614e1", "SnailSoft", "", "Comitoid beta 4 (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e4fa739c81b003c92bea7da5e84c7feb", "Akor", "", "TV Boy (1992) (Akor) (NTSC) [bad dump]", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e505bd8e59e31aaed20718d47b15c61b", "Funvision - Fund. Int'l Co.", "", "Space War (1982) (Funvision) (PAL)", "AKA Condor Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e51030251e440cffaab1ac63438b44ae", "Parker Brothers - On-Time Software, Joe Gaucher, Louis Marbel", "PB5110", "James Bond 007 (1984) (Parker Bros)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e51c23389e43ab328ccfb05be7d451da", "Arcadia Corporation, Scott Nelson", "13", "Sweat! - The Decathlon Game (1983) (Arcadia) (Prototype)", "Uses the Paddle Controllers (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5359cbbbff9c6d7fe8aeff5fb471b46", "CCE", "C-849", "Boom Bang (1983) (CCE)", "AKA Crackpots", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e549f1178e038fa88dc6d657dc441146", "Atari, Bob Whitehead - Sears", "CX2625 - 6-99827, 49-75114", "Football (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e556e07cc06c803f2955986f53ef63ed", "Coleco - Individeo, Ed Temple", "2665", "Front Line (1984) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e558be88eef569f33716e8e330d2f5bc", "Shock Vision", "", "Keystone Kapers (Shock Vision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e56da674188ba2f02c7a0a343a01236f", "", "", "This Planet Sucks Demo 4 (Greg Troutman) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e59d022d524d05acc19515598c831e4d", "Alessandro Ciceri", "", "MagiCard+ (alex_79) WIP_20150118 (PAL)", "MagiCard hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5a6e0bb7d56e2f08b237e15076e5699", "", "", "Color Table Display Helper (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5bacf526036d3c8c99db5b030cf00e7", "", "", "Starmaster (Genesis)", "Genesis controller (C switches to map mode)", "Hack of Starmaster", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5d5085123a98c1e61818caa2971e999", "", "", "Euchre (PAL) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5d72ff8bab4450be57785cc9e83f3c0", "Telegames", "6082 A145", "Kung Fu Superkicks (1988) (Telegames) (PAL)", "AKA Chuck Norris Superkicks", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5ecd78edd24326a968809decbc7b916", "Imagic, Bob Smith", "720020-1A, IA3611", "Cheese (Dragonfire Beta) (05-21-1982) (Imagic) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e5f17b3e62a21d0df1ca9aee1aa8c7c5", "CommaVid, John Bronstein", "CM-003", "Cosmic Swarm (1982) (CommaVid)", "AKA Termite", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e5f360226dc552aba3e7e9b202330f48", "Supercat", "", "Mega Bitmap Demo (2007) (Supercat)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e5f84930aa468db33c0d0f7b26dd8293", "CCE", "C-826", "Grand Prix (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e5fcc62e1d73706be7b895e887e90f84", "", "", "Air-Sea Battle (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e600f5e98a20fafa47676198efe6834d", "Parker Brothers - Roklan, Joe Gaucher", "PB5080", "Gyruss (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e609e8a007127b8fcff79ffc380da6b1", "", "", "Multi-Sprite Game V2.3 (Piero Cavina) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e61210293b14c9c4ecc91705072c6a7e", "Gameworld", "133-005", "Bugs (1983) (Gameworld) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 50", "", "", "", "", "", "", "", "" }, + { "e62e60a3e6cb5563f72982fcd83de25a", "Jone Yuan Telephonic Enterprise Co", "", "End of the World (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e63a87c231ee9a506f9599aa4ef7dfb9", "Tigervision, Warren Schwader", "7-003", "Threshold (1982) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e63efdfda9a4003dcd77a854a781a06a", "Paul Slocum", "", "Combat Rock (PD) (Hack) [a]", "Hack of Combat", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e643aaec9a9e1c8ab7fe1eae90bc77d7", "Roger Williams", "", "Asymmetric Playfield (Roger Williams)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e64a8008812327853877a37befeb6465", "Answer Software Corporation - TY Associates, Mike Wentz", "ASC1002", "Gauntlet (1983) (Answer Software)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e6508b878145187b87b9cded097293e7", "", "", "Oystron (V2.8) (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e66e5af5dea661d58420088368e4ef0d", "Activision, Bob Whitehead", "AG-011", "Stampede (1981) (Activision) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e67b0ed32fd9d28d12ab3775d52e8c3a", "Atari, Omegamatrix", "", "Video Olympics Menu (2020) (Hack)", "Hack of Video Olympics", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "AUTO 60", "", "", "", "", "", "", "", "" }, + { "e6d5948f451a24994dfaaca51dfdb4e1", "Jone Yuan Telephonic Enterprise Co", "", "Football (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e6de4ef9ab62e2196962aa6b0dedac59", "Imagic, Wilfredo Aguilar, Michael Becker, Dennis Koble", "720113-2A, 13206", "Solar Storm (1983) (Imagic) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "e6e5bb0e4f4350da573023256268313d", "Thomas Jentzsch", "", "Missile Control (Thomas Jentzsch)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e6f49a1053c79211f82be4d90dc9fe3d", "", "", "Gunfight 2600 - Little progress... (2001) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e723ad8f406cb258b89681ef4cef0eff", "Thomas Jentzsch", "", "Sadoom (TJ) (PAL) (Hack)", "Hack of Kaboom!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "e72eb8d4410152bdcb69e7fba327b420", "Atari, Douglas Neubauer, Mimi Nyden", "CX26136", "Solaris (1986) (Atari)", "AKA Universe, Star Raiders II, The Last Starfighter", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e72ee2d6e501f07ec5e8a0efbe520bee", "Imagic, Dave Johnson", "720119-2A, 13211, EIX-004-04I", "Quick Step! (1983) (Imagic) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e73838c43040bcbc83e4204a3e72eef4", "CCE", "", "Apples and Dolls (CCE)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e74022cfe31ec8908844718dfbdedf7a", "", "", "Space Treat (30-12-2002) (Fabrizio Zavagli) [a2]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e77ec259e1387bc308b0534647a89198", "Parker Brothers, David Lamkins, Laura Nikolich", "931503", "Spider-Man (1982) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e77f332b71f13884c84771e7a121182d", "Jone Yuan Telephonic Enterprise Co", "", "Hey! Stop! (Jone Yuan)", "AKA Keystone Kapers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e784a9d26707cfcd170a4c1c60422a72", "Quelle", "147.443 6", "Gefecht im All (1983) (Quelle) (PAL)", "AKA Space Jockey", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e7864caaf9ec49ed67b1904ce8602690", "", "", "Donkey Kong 2K3 Pic (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e7a758bb0b43d0f7004e92b9abf4bc83", "", "", "Troll's Adventure (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e7dd8c2e6c100044002c1086d02b366e", "Activision, Steve Cartwright - Ariola", "EAX-013, PAX-013, 711 013-720", "Barnstorming (1982) (Activision) (PAL)", "AKA Die tollkeuhnen Flieger", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e7f005ddb6902c648de098511f6ae2e5", "Spectravideo - Universum", "SV-010", "CompuMate (1983) (Spectravideo) (PAL)", "", "", "", "", "CM", "", "", "", "", "COMPUMATE", "COMPUMATE", "", "", "", "", "", "", "YES", "80", "", "", "", "" }, + { "e800e4aec7c6c54c9cf3db0d1d030058", "", "", "Qb (2.06) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e80a4026d29777c3c7993fbfaee8920f", "", "", "Frisco (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e823b13751e4388f1f2a375d3560a8d7", "Arcadia Corporation, Stephen Harland Landrum", "AR-4105", "Official Frogger (Preview) (1983) (Arcadia) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e879b7093ac4cfad74c88d636ca97d00", "", "", "Poker Squares (V0.0f) (2001) (B. Watson)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e88340f5bd2f03e2e9ce5ecfa9c644f5", "", "", "Lock 'n' Chase (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e8a3473bf786cf796d1336d2d03a0008", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (12-05-1983) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e8aa36e3d49e9bfa654c25dcc19c74e6", "Atari, Joe Decuir, Larry Caplan, Steve Mayer, Larry Wagner", "CX2601, CX2601P", "Combat (1977) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e8e7b9bdf4bf04930c2bcaa0278ee637", "", "", "Boring Taz (Hack)", "Hack of Taz", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e8f7679359c4f532f5d5e93af7d8a985", "", "", "Hangman Invader Original Words (Hack)", "Hack of Hangman", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9034b41741dcee64ab6605aba9de455", "Digivision", "", "Phanton Tank (Digivision)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e908611d99890733be31733a979c62d8", "Atari, Dan Hitchens, Mimi Nyden", "CX2697", "Mario Bros. (1983) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e91d2ecf8803ae52b55bbf105af04d4b", "Atari, Howard Scott Warshaw", "CX2655, CX2655P", "Yars' Revenge (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e923001015bedd7901569f035d9c592c", "", "", "Adventure II (Hack)", "Hack of Adventure", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e927ecf80f3784d745abd8368d78f2f3", "", "", "Space Instigators (V1.8) (19-10-2002) (CT) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e932f44fad2a66b6d5faec9addec208e", "", "", "Atari Logo Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e94632b0d863dd76459d689a9865bb33", "Jone Yuan Telephonic Enterprise Co", "", "Combat (Jone Yuan) (4K)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e957eb4612d6bd5940d3492dfa749668", "", "", "Tunnel Demo (27-03-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e959b5a2c882ccaacb43c32790957c2d", "", "", "Phantom II & Pirate (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e97eafd0635651d3999cece953c06bd5", "", "", "M.A.S.H (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9be3e8e4a7e73dd63ed4235a3a1a25f", "", "", "MMetall (Hack)", "Hack of Miniature Golf", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9c5d04643855949a23ff29349af74ea", "", "", "SCSIcide (Score Hack 2) (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9c71f8cdba6037521c9a3c70819d171", "Action Hi Tech - Hi-Score", "", "Bank Heist (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9cb18770a41a16de63b124c1e8bd493", "Parker Brothers - Roklan, Joe Gaucher", "931519", "Popeye (1983) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "e9db2f91efe6ff7ea3546e2c2578fb09", "Omegamatrix", "", "Millipede (Atari Mouse) v6.5 (Omegamatrix)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "PAL60", "", "", "", "", "", "", "" }, + { "e9e646f730b8400cd5da08c849ef3e3b", "Tron", "", "Enduro (Tron)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9e6ad30549a6e2cd89fe93b7691d447", "Atari - Bobco, Robert C. Polaro", "CX26140, CX26140P", "Desert Falcon (05-27-1987) (Atari) (Prototype) (PAL)", "AKA Nile Flyer, Sphinx", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "e9f25c7af4f27c9e1b5b8f6fe6141e8c", "Champ Games", "CG-03-N", "Scramble (NTSC)", "Compatible with Genesis controller", "Homebrew", "", "", "", "", "", "", "", "JOYSTICK", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ea38fcfc06ad87a0aed1a3d1588744e4", "Atari, Lou Harp", "CX26122", "Sinistar (01-XX-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ea6d40db5498d6386571a76df448aa4c", "", "", "Vertical Playfield Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ea7e25ade3fe68f5b786ee0aa82b1fe5", "", "", "Galatic (208 in 1) (Unknown) (PAL)", "AKA Challenge of.... Nexar, The", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ea832e2cb6aae6f525f07452c381fa48", "", "", "Polar to Cartesian and VV (2001) (Roger Williams)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ea86176b27ab0da8cce8f0179884bfaa", "", "", "Demo Image Series #10 - It's Art (28-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eaacfcdc1d4ee1258429b7ae7f084125", "Telegames", "6057 A227", "Quest for Quintana Roo (1989) (Telegames)", "Genesis controller (B is action button, C chooses tool or weapon)", "Hack of Quest for Quintana Roo", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ead60451c28635b55ca8fea198444e16", "Sancho - Tang's Electronic Co.", "TEC004", "Nightmare (1983) (Sancho) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eada0dd61ce13f8317de774dc1e68604", "", "", "2600 Digital Clock (Demo 1) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eae0c06ee61c63b81cd016096fc901b0", "Joe Grand", "", "SCSIcide (v1.0) (2001) (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eae6a5510055341d3abeb45667bb3e9b", "HES", "", "Wall Defender (HES) (PAL)", "AKA Wall Break (Planet Patrol if right difficulty = 'A')", "", "", "0", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eaf744185d5e8def899950ba7c6e7bb5", "Atari", "CX26172", "Xenophobe (1991) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eafe8b40313a65792e88ff9f2fe2655c", "Eric Ball", "ELB004", "Skeleton+ (NTSC)", "Stereo sound", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb3d680699f8762f71f38e28e321234d", "", "", "Fu Kung! (V0.01) (08-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb4252faff7a4f2ba5284a98b8f78d1a", "", "", "John K Harvey's Equalizer (NTSC) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "eb46e99ec15858f8cd8c91cef384ce09", "Goliath - Hot Shot", "83-113", "Ground Zero (1983) (Goliath) (PAL)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb503cc64c3560cd78b7051188b7ba56", "Star Game", "043", "Moto Laser (Star Game)", "AKA Mega Force", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb634650c3912132092b7aee540bbce3", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "eb6d6e22a16f30687ade526d7a6f05c5", "Atari", "CX26150P", "Q-bert (1987) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb71743c6c7ccce5b108fad70a326ad9", "", "", "Euchre (25-11-2001) (Erik Eid) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb7934360658a29c50aeaff20bfda23b", "Activision, John Van Ryzin", "EAZ-036-04", "H.E.R.O. (1984) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eb92193f06b645df0b2a15d077ce435f", "Starpath Corporation, Steve Hales, Stephen H. Landrum", "4 AR-4102", "Suicide Mission (1982) (Starpath) (PAL)", "AKA Meteoroids", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "eb9712e423b57f0b07ccd315bb9abf61", "Retroactive", "", "Qb (V2.04) (PAL) (2001) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "eb9f8b84c193d9d93a58fca112aa39ed", "", "", "Register Twiddler Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebcb084a91d41865b2c1915779001ca7", "JVP", "", "Bob Is Going Home (JVP)", "AKA Bobby Is Going Home", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebcbc8a181a738e13df6216e5c329230", "Activision, Steve Cartwright", "AX-022", "Seaquest (1983) (Activision) (16K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebd2488dcace40474c1a78fa53ebfadf", "Skill Screen Games, Herman Quast", "SSG001", "Extra Terrestrials (1984) (SSG)", "The only Canadian-designed and manufactured Atari 2600 game from the 1980's", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebdc5716b85c4ff44fa357cb697d6cef", "Thomas Jentzsch", "", "Centipede - Amiga Mouse Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebf2dff78a08733251bf3838f02f7938", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype) [a2]", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ebf9038e927e6a0db3e0d170c59911e6", "", "", "Pac-2600 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ec3beb6d8b5689e867bafb5d5f507491", "U.S. Games Corporation - Vidtec - JWDA, Todd Marshall, Henry Will IV", "VC1003", "Word Zapper (1982) (U.S. Games)", "AKA Word Grabber", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ec407a206b718a0a9f69b03e920a0185", "Quelle", "876.482 1", "Landung in der Normandie (1983) (Quelle) (PAL)", "AKA Commando Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ec5c861b487a5075876ab01155e74c6c", "Apollo - Games by Apollo, Ed Salvo, Byron Parks", "AP-2001", "Spacechase (1982) (Apollo)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ece463abde92e8b89bcd867ec71751b8", "Puzzy - Bit Corporation", "PG205", "Dancing Plate (1982) (Puzzy) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ece908d77ab944f7bac84322b9973549", "", "", "Tom Boy (Unknown) (PAL60)", "AKA Pitfall!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ecf51385384b468834611d44a8429c03", "20th Century Fox Video Games, Douglas 'Dallas North' Neubauer", "11105", "Mega Force (1982) (20th Century Fox) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ecfa04523dde82fe42cdc7315a8f61b6", "Activision, David Crane - Ariola", "EAG-004, PAG-004 - 711 004-715", "Fishing Derby (1980) (Activision) (PAL) (4K)", "AKA Schneller als der Hai", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed014beeeb77dbb2bbcf9b5f6850b2f4", "", "", "Green Bar Text Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed0451010d022b96a464febcba70b9c4", "PlayAround - J.H.M.", "203", "Knight on the Town (1982) (PlayAround) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ed0ab909cf7b30aff6fc28c3a4660b8e", "Panda", "105", "Stunt Man (1983) (Panda)", "AKA Nightmare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed1306436ce237afc5a7ed3f77134202", "HES", "771-341", "2 Pak Special - Dolphin, Pigs n' Wolf (1990) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed1492d4cafd7ebf064f0c933249f5b0", "CCE", "", "Video Cube (CCE)", "AKA Atari Video Cube", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed1a784875538c7871d035b7a98c2433", "Bit Corporation", "R320", "Save Our Ship (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed2218b3075d15eaa34e3356025ccca3", "Atari, Richard Maurer", "CX2635, CX2635P", "Maze Craze (1980) (Atari) (PAL)", "AKA A Game of Cops 'n Robbers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed5ccfc93ad4561075436ee42a15438a", "Atari, Tom Reuterdahl", "CX2626, CX2626P", "Miniature Golf (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ed8f319e82d355832195eb7715644795", "Activision, Larry Kaplan, David Crane", "AG-010, AG-010-04", "Kaboom! (1981) (Activision) (8K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "eddef10fdc0029301064115ae0cd41d4", "CCE", "", "Freeway (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ede4ab11ca346bd023b2c21d941e0c50", "Activision, David Crane", "EAZ-030", "Decathlon (1983) (Activision) (SECAM)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ede7e8bf865b0afb4744f86d13624f9a", "", "", "Demo Image Series #2 - Clown (19-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "edf69b123e06eaf8663cc78d8aeba06e", "SpkSoft 98", "", "River Raid (SpkSoft 98) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee28424af389a7f3672182009472500c", "Atari, Carol Shaw - Ralph Lauren", "", "Polo (1978) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee456542b93fa8d7e6a8c689b5a0413c", "", "", "Chronocolor Donkey Kong Clean (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee4c186123d31a279ed7a84d3578df23", "Atari, Carol Shaw, Nick 'Sandy Maiwald' Turner", "CX2608", "Super Breakout (1982 - 1981) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 45", "", "", "", "", "", "", "", "" }, + { "ee659ae50e9df886ac4f8d7ad10d046a", "Exus Corporation", "", "Video Reflex (1983) (Exus)", "AKA Foot Craz", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee6665683ebdb539e89ba620981cb0f6", "Coleco", "2658", "Berenstain Bears (1983) (Coleco)", "Uses the KidVid Controller", "Unbelievably Rare", "", "", "", "A", "", "", "", "", "KIDVID", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee67dc0b01746372d2b983d88f48e24f", "", "", "Scroller Demo (02-01-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee681f566aad6c07c61bbbfc66d74a27", "Activision", "", "Unknown Activision Game (10-29-1982) (Activision) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee6cbedf6c0aac90faa0a8dbc093ffbe", "CCE", "", "My Golf (CCE) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee8027d554d14c8d0b86f94737d2fdcc", "Canal 3 - Intellivision", "", "Yars' Revenge (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "ee84bdc5dae268e227e407c7b5e6b6b7", "", "", "Marilyn Monroe Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ee9caee4eb958284fb10c277b14537f1", "Carrere Video, Garry Kitchen - Teldec", "USC1001", "Space Jockey (1983) (Carrere Video) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eea0da9b987d661264cce69a7c13c3bd", "Coleco", "2454", "Zaxxon (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eeb92f3f46df841487d1504f2896d61a", "Cody Pittman", "", "Corys Adventure (Cody Pittman) (Hack)", "Hack of Pac-Man", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eec61cc4250df70939d48fe02d7122ac", "Activision, Bob Whitehead - Ariola", "EAG-005, PAG-005, EAG-005-04B - 711 005-715", "Skiing (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eed9eaf1a0b6a2b9bc4c8032cb43e3fb", "Atari - Axlon, Steve DeFrisco", "CX26192", "Klax (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "eee7695ae3eea7818321df0b790b31f3", "", "", "Sound Paddle V2 (Dennis Caswell & Jim Nitchals) (PD)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "ef263d40a23483ab339cac44d9515a56", "Thomas Jentzsch", "", "Fatal Run (TJ)", "NTSC Conversion", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ef3a4f64b6494ba770862768caf04b86", "Activision, Bob Whitehead", "AG-034-04", "Private Eye (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ef60b06fddb675b0d783afbfa5fc5232", "", "", "Many Blue Bars and Text Demo 4 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ef66af190840871409fe1702d2483554", "Andrew Davie, Paul Slocum, Christopher Tumber", "", "DiscoTech (12-02-2003) (Andrew Davie)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ef71e9fb0d8d477226d8d42261fbf0a7", "Piero Cavina", "", "Multi-Sprite Demo V2.0 (Piero Cavina) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ef76ea05655a0b62cb1018c92b9b4b7d", "Gakken", "010", "Strategy X (1983) (Gakken) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "efa1098c7d091b940c2543abe372f036", "Scott Stilphen", "", "E.T. The Extra-Terrestrial (Scott Stilphen) (Hack)", "Hack of E.T. The Extra-Terrestrial", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "efb47d70b2965ce689e2c5757616b286", "", "", "Time Test Demo (Eckhard Stolberg) (PAL) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "efd387430a35a659ff569a9a0ec22209", "Atari - GCC", "CX26118", "Millipede (1984) (Atari) (Prototype) (PAL)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "efefc02bbc5258815457f7a5b8d8750a", "CBS Electronics, Richard K. Balaska Jr.", "4L 2520 5000", "Tunnel Runner (1983) (CBS Electronics) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "effa3a7ce078c6d83bf43174a7bfdb1f", "Thomas Jentzsch", "", "Centipede - Atari Mouse Hack v1.4 (NTSC) (Half-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "efffafc17b7cb01b9ca35324aa767364", "", "", "Circus Atari (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f02ba8b5292bf3017d10553c9b7b2861", "Atari", "CX26172", "Xenophobe (1991) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f032b2f2d8323404a6b4541f92dd1825", "", "", "Many Blue Bars and Text Demo 3 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f047df70d3d08e331122cd2de61d6af8", "Dave Neuman", "", "Space Battle (NTSC)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f04ee80011d95798006378643650aaa7", "Atari, Bill Aspromonte, John Russell, Michael Sierchio, Robert Zdybel", "CX26114", "Pigs in Space (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0510abbfbe24ead552e92e3841f63f3", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (NTSC) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0536303f49006806bac3aec15738336", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (4 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0541d2f7cda5ec7bab6d62b6128b823", "Atari, Paul Donaldson", "", "Bionic Breakthrough (1984) (Atari) (Prototype)", "Uses Mindlink Controller (left only)", "Prototype", "", "", "", "", "", "", "", "MINDLINK", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f060826626aac9e0d8cda0282f4b7fc3", "Atari, David Crane - Sears", "CX2605 - 6-99822, 49-75109", "Outlaw (1978) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0631c6675033428238408885d7e4fde", "Paul Slocum", "", "Test Cart (2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f066bea7ab0a37b83c83c924a87c5b67", "", "", "Air Raiders (1982) (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0a6e99f5875891246c3dbecbf2d2cea", "Atari, James Andreasen - Sears", "CX2654 - 49-75141", "Haunted House (1982) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0b7db930ca0e548c41a97160b9f6275", "Atari, Larry Wagner, Bob Whitehead - Sears", "CX2645 - 49-75181", "Video Chess (1979) (Atari)", "AKA Computer Chess", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0cacae1d1b79ee92f0dc035f42e0560", "", "", "Boring Donkey Kong (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0d393dbf4164a688b2346770c9bbd12", "", "", "Racquetball (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f0daaa966199ef2b49403e9a29d12c50", "", "", "Mr. Postman (Unknown)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0de4f49e95d529569e8788d5a7b4d30", "Thomas Jentzsch", "", "Reactor - Atari Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)", "Uses Atari Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0e0addc07971561ab80d9abe1b8d333", "Imagic, Rob Fulop", "720000-200, 720101-1B, 720101-1C, IA3200, IA3200C, IX-006-04", "Demon Attack (1982) (Imagic)", "AKA Death from Above", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f0ef9a1e5d4027a157636d7f19952bb5", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype) [a5]", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f10e3f45fb01416c87e5835ab270b53a", "Suntek", "SS-024", "Ski Run (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1127ade54037236e75a133b1dfc389d", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (Preview) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f11cfab087fcbd930ab8b0becc5b2e5a", "Canal 3 - Intellivision", "", "River Raid (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f12afbffa080dd3b2801dd14d4837cf6", "Atari, Michael Kosaka, Peter C. Niday, Robert Vieira", "CX26110", "Crystal Castles (01-04-1984) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f137211537438b1fce3d811baef25457", "", "", "Incoming (02-10-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1489e27a4539a0c6c8529262f9f7e18", "Champ Games", "CG-01-P", "Lady Bug (PAL60)", "", "Homebrew", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f14d5e96ec3380aef57a4b70132c6677", "Goliath - Hot Shot", "83-414", "Pac Kong (1983) (Goliath) (PAL)", "AKA Inca Gold", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1554569321dc933c87981cf5c239c43", "Atari - Glenn Axworthy", "CX26129", "Midnight Magic (1986) (Atari)", "AKA Pinball Wizard", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f16c709df0a6c52f47ff52b9d95b7d8d", "Atari, Alan Miller - Sears", "CX2662 - 6-99811", "Hangman (1978) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f16ef574d2042ed8fe877d6541f4dba4", "Spectravision - Spectravideo", "SA-201", "Gangster Alley (1982) (Spectravision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1929bb9b5db22d98dd992aa3fe72920", "", "", "Cube Conquest (Improved Interlace) (Billy Eno) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f19aba18f86e415812480ad2be221425", "Chris Larkin", "", "Solaris Trainer (2002) (Chris Larkin) (Hack)", "Hack of Solaris", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1a0a23e6464d954e3a9579c4ccd01c8", "20th Century Fox, Douglas 'Dallas North' Neubauer", "11006", "Alien (1982) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f1ae6305fa33a948e36deb0ef12af852", "Andreas Dietrich", "", "Donkey Kong VCS (2017) (1.0)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f1b2ea568b3e156e3f2849dac83591f6", "", "", "Sprite Demo (1997) (Bob Colbert) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1b7edff81ceef5af7ae1fa76c8590fc", "Atari, Richard Maurer", "CX2632, CX2632P", "Space Invaders (1980) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1beca5a198cf08190487e5c27b8e540", "", "", "Fu Kung! (V0.16) (2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1e375d921858467166e53bcec05803f", "Jeffry Johnston", "", "Radial Pong - Version 3 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f1eeeccc4bba6999345a2575ae96508e", "Video Gems", "VG-03", "Steeplechase (1983) (Video Gems) (PAL)", "", "", "", "", "", "", "A", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f1fe06ebe2900eac4cdd17799389a102", "Atari, Jim Huether", "CX26163P", "Sky Diver (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f20675c8b98518367b9f5b8ee6f7c8ea", "Atari", "CX26163P", "Stampede (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f20bd756f3990e06c492f53cd0168e68", "", "", "Skeleton+ (03-05-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f21813aa050437f0dbc8479864acec6d", "", "", "Sneak 'n Peek (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f23d19b73dac50cc6149316912b8ee53", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (PAL) (TJ)", "Uses Amiga Mouse Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f240ba9f8092d2e8a4c7d82c554bf509", "Quelle", "463.860 7", "Strahlen der Teufelsvoegel (1983) (Quelle) (PAL)", "AKA Atlantis", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f280976d69d6e27a48506bd6bad11dcd", "Atari, Larry Kaplan", "CX2664, CX2664P", "Brain Games (1978) (Atari) (PAL)", "Uses Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f283cc294ece520c2badf9da20cfc025", "Atari - CCW, Christopher H. Omarzu", "CX26104", "Big Bird's Egg Catch (1983) (Atari) (PAL)", "Uses Kids/Keypad Controllers", "Rare", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f28c07767b3e90a2689ade5b5e305874", "Canal 3 - Intellivision", "C 3014", "Keystone Kapers (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f2d40c70cf3e1d03bc112796315888d9", "Atari - CCW, Michael Callahan, Preston Stuart", "CX26103", "Alpha Beam with Ernie (1983) (Atari) (PAL)", "Uses Keypad Controllers", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f2d4d6187903cac2d5ea8ed90dad120d", "Digimax", "", "River Raid II (Digimax)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f2e4fb2d3600c0f76d05864e658cc57b", "", "", "Marble Craze (Kernel) (17-02-2002) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f2f2cb35fdef063c966c1f5481050ea2", "", "", "Ram It (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f2f59629d7341c97644405daeac08845", "Jone Yuan Telephonic Enterprise Co", "", "Bobby Is Going Home (Jone Yuan)", "2600 Screen Search Console", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f303630a2d7316787aecd67fff6b2e33", "AtariAge - Fred Quimby", "", "Gingerbread Man (Fred Quimby)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3213a8a702b0646d2eaf9ee0722b51c", "Atari, Carol Shaw - Sears", "CX2618 - 49-75123", "3-D Tic-Tac-Toe (1980) (Atari) (4K)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f33f1d0f7819c74148dacb48cbf1c597", "Retroactive", "", "Qb (2.00) (Retroactive) (Stella)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f344ac1279152157d63e64aa39479599", "Tigervision", "7-012", "Espial (1984) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f34dd3b8156aaf113cb621b2e51d90b8", "Joe Grand", "", "SCSIcide Pre-release 5 (Joe Grand)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f34f08e5eb96e500e851a80be3277a56", "Atari, Brad Stewart - Sears", "CX2622 - 6-99813, 49-75107", "Breakout (1978) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 60", "", "", "", "", "", "", "", "" }, + { "f367e58667a30e7482175809e3cec4d4", "ZiMAG - Emag - Vidco", "708-111 - GN-040", "Cosmic Corridor (1983) (ZiMAG)", "AKA Space Tunnel", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f38358cd8f5ecfedffd5aca1aa939f18", "Universal Gamex Corporation, Alan Roberts", "1005", "X-Man (1983) (Universal) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f39e4bc99845edd8621b0f3c7b8c4fd9", "AtariAge", "", "Toyshop Trouble (AtariAge)", "F8 Emulator Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3c431930e035a457fe370ed4d230659", "", "", "Crackpots (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3cd0f886201d1376f3abab2df53b1b9", "Commavid, Ben Burch", "CM-010", "Rush Hour (1983) (Commavid) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3dfae774f3bd005a026e29894db40d3", "Otto Versand", "649635", "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3f5f72bfdd67f3d0e45d097e11b8091", "Sears Tele-Games, Marilyn Churchill, Matthew L. Hubbard", "CX2647 - 49-75142", "Submarine Commander (1982) (Sears)", "AKA Seawolf 3", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f3f92aad3a335f0a1ead24a0214ff446", "", "", "Spectrum Color Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f40e437a9ebf0bdfe26204152f74f868", "Bit Corporation", "R320", "Jawbreaker (32 in 1) (BitCorp) (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4204fc92d17ed4cb567c40361ad58f1", "Inky", "", "Beanie Baby Bash (Inky) (Hack)", "Hack of Beany Bopper", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4469178cd8998cb437fa110a228eaca", "Digitel", "", "Frostbite (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f45644ff82b533a781a1ee50f2e95f3c", "", "", "Overhead Adventure Demo 6 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f457674cef449cfd85f21db2b4f631a7", "U.S. Games Corporation - JWDA, Todd Marshall, Wes Trager, Henry Will IV", "VC1004", "Commando Raid (1982) (U.S. Games)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f473f99e47d4026a7a571184922ebf04", "Philip R. Frey", "", "Donkey Claus (Philip R. Frey) (Hack)", "Hack of Donkey Kong", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f48022230bb774a7f22184b48a3385af", "Atari, Rob Fulop - Sears", "CX2633 - 49-75119", "Night Driver (1980) (Atari) (4K)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "f48735115ec302ba8bb2d2f3a442e814", "", "", "Dancing Plate (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f49a34f1fdd7dc147cbf96ce2ce71b76", "", "", "Qb (Special Edition) (PAL) (Retroactive)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f4a09f906cc37be31224433f576d77d3", "Thomas Jentzsch", "", "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (PAL) (TJ)", "Uses Atari Trak-Ball Controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4ab6bd5f80d8988141edde4c84b23b5", "Atari, Alan Miller", "CX2624, CX2624P", "Basketball (1978) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4b8a47a95b61895e671c3ec86ffd461", "Parker Brothers, Wilfredo Aguilar, Michael Becker, Neil McKenzie, Bob Smith, Brad Stewart", "PB5540", "Star Wars - The Arcade Game (01-03-1984) (Parker Bros) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f4c2e50b01dff99bddbe037b3489511c", "", "", "Hypnotic (V0.04) (2001) (Inkling) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4c6621f1a0b4d27081123c08d7d1497", "CCE", "C-838", "Immies & Aggies (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4cf6881b65c424095dc25dc987f151f", "", "", "128 in 1 Game Select ROM (Unknown)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f4dabd5bcc603e8464a478208037d423", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (08-21-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f526d0c519f5001adb1fc7948bfbb3ce", "Mythicon, Bill Bryner, Bruce de Graaf", "MA1003", "Star Fox (1983) (Mythicon)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f52f40299fd238c6ffd9e6107050dc76", "Activision, Bob Whitehead - Ariola", "EAG-011, PAG-011 - 711 011-715", "Stampede (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f539e32bf6ce39c8ca47cb0cdd2c5cb8", "Control Video Corporation", "", "GameLine Master Module ROM (1983) (Control Video)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f542b5d0193a3959b54f3c4c803ba242", "Atari, Tom Rudadahl - Sears", "CX2634 - 49-75121", "Golf (1980) (Atari) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f5445b52999e229e3789c39e7ee99947", "Atari, Jim Huether", "CX26163P", "Flag Capture (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f5a2f6efa33a3e5541bc680e9dc31d5b", "Suntek", "SS-022", "Motocross (1983) (Suntek) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f5a3e051730d45fea518f2e8b926565b", "Robby", "", "Keystone Kapers (Robby)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f5aa6bd10f662199c42e43863a30106c", "", "", "Music Kit (V1.0) - Song Player (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f5d103a9ae36d1d4ee7eef657b75d2b3", "Starpath Corporation, Stephen H. Landrum", "9 AR-4105", "Official Frogger, The (Preview) (1983) (Starpath)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f613aad84d2163d6b197b220bfec1b7e", "", "", "X-Doom V.27 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f661f129644f338b13d9f4510d816c03", "Atari, David Crane", "CX26163P", "Outlaw (32 in 1) (1988) (Atari) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6676e3fe901eb8515fc7ae310302c3c", "Activision, David Crane", "AG-008", "Laser Blast (1981) (Activision) (8K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f67181b3a01b9c9159840b15449b87b0", "Atari, Nick 'Sandy Maiwald' Turner", "CX2665", "Frog Pond (08-27-1982) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f687ec4b69611a7f78bd69b8a567937a", "Activision, Alan Miller - Ariola", "EAZ-028 - 711 028-725", "Robot Tank (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f69a39b215852a0c2764d2a923c1e463", "", "", "Move a Blue Blob Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f69bb58b815a6bdca548fa4d5e0d5a75", "Atari, Larry Kaplan", "CX26163P", "Bowling (32 in 1) (1988) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f69d4fcf76942fcd9bdf3fd8fde790fb", "CCE", "", "Aquaventure (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6a282374441012b01714e19699fc62a", "ZiMAG - Emag - Vidco", "710-111 - GN-010", "I Want My Mommy (1983) (ZiMAG)", "AKA Open, Sesame!", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f6a9ea814d15b85bffe980c927df606b", "", "", "Missile Command (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f6b5ebb65cbb2981af4d546c470629d7", "Coleco - Individeo, Ed Temple", "", "Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype) [a]", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6c13e816e58c8c62f82b2c8b91a2d67", "", "", "Scrolling Playfield 2 (Junkosoft) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6d512bef1bf253dc935d0e13c3d1462", "", "", "Slot Racers (Unknown) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6daebc0424fa0f8d9aaf26c86df50f4", "Brian Watson", "", "Color Tweaker (V1.0) (2001) (B. Watson)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6efa00ae99aaf33e427b674bcfd834d", "", "", "2600 Digital Clock (Demo 3) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f6f1b27efc247a0e8d473ddb4269ff9e", "Rainbow Vision - Suntek", "SS-015", "Catch Time (1983) (Rainbow Vision) (PAL)", "AKA Plaque Attack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f70e3f3bb2d19ec2aaec8f78dc43744f", "Jone Yuan Telephonic Enterprise Co", "", "Pooyan (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f714a223954c28eccf459295517dcae6", "", "", "Big - Move This Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7154add27b95cd90464dbed8cfd7557", "Fabrizio Zavagli", "", "Space Treat Deluxe (2003) (PAL)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f724d3dd2471ed4cf5f191dbb724b69f", "Atari, Jerome Domurat, Howard Scott Warshaw", "CX2659", "Raiders of the Lost Ark (1982) (Atari)", "Console ports are swapped", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f736864442164b29235e8872013180cd", "Telegames - VSS", "6057 A227", "Quest for Quintana Roo (1988) (Telegames) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f73d2d0eff548e8fc66996f27acf2b4b", "CCE", "C-813", "Pitfall (1983) (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7424985bac41067502b4a05b64cb75a", "Activision, Steve Cartwright", "AX-027", "Plaque Attack (1983) (Activision)", "Genesis controller (B is fire up, C is fire down)", "Hack of Plaque Attack", "", "", "", "", "", "", "", "GENESIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f74ad642552385c3daa203a2a6fc2291", "Eckhard Stolberg", "", "Cubis (1997) (Eckhard Stolberg)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f750b5d613796963acecab1690f554ae", "Manuel Polik", "", "Gunfight 2600 (MP)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f75872946e82ad74d48eae5bc28f5f0e", "Sears Tele-Games, Jim Huether", "CX2614 - 49-75126", "Steeplechase (04-15-1980) (Sears) (Prototype)", "Uses the Paddle Controllers", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f777444fc21a5925e066b68b1d350575", "", "", "Marble Craze (Kernel Works) (Paul Slocum)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f77f5fc3893da5d00198e4cd96544aad", "Canal 3 - Intellivision", "", "Stampede (Canal 3)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7856e324bc56f45b9c8e6ff062ec033", "Atari, Jerome Domurat, Michael Sierchio", "CX2667", "RealSports Soccer (1983) (Atari) [no opening tune]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f78c125b5da483c41e51522947d6c4ce", "", "", "Sound Paddle V1 (Dennis Caswell & Jim Nitchals) (PD)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "YES", "", "", "", "", "", "01", "", "", "", "", "", "", "", "" }, + { "f7a138eed69665b5cd1bfa796a550b01", "Tigervision - Teldec", "7-012 - 3.60016 VC", "Espial (1984) (Tigervision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7a651972d78f9ba485b14690452d4be", "Paul Slocum", "", "Homestar Runner Demo #2 (2004-03-29)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f7af41a87533524d9a478575b0d873d0", "Quelle", "495.663 7", "Spiderman (1983) (Quelle) (PAL)", "AKA Spider-Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7d6592dcb773c81c278140ed4d01669", "Activision, David Crane, Dan Kitchen", "EAG-108-04, EAZ-108-04B", "Ghostbusters (1985) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7e07080ed8396b68f2e5788a5c245e2", "Video Game Cartridge - Ariola", "TP-617", "Farmyard Fun (Ariola)", "AKA Play Farm", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7ec2f2bdbe8fbea048c0d5fa6503b0b", "Akor", "", "TV Boy (1992) (Akor) (PAL)", "Includes 127 games", "", "", "", "", "", "", "", "", "JOYSTICK", "JOYSTICK", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7f50d9c9d28bcc9f7d3075668b7ac89", "Activision, David Crane - Ariola", "EAG-008, PAG-008, EAG-008-04I - 711 008-720", "Laser Blast (1981) (Activision) (PAL) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f7fac15cf54b55c5597718b6742dbec2", "Spiceware", "SW-01", "Medieval Mayhem (NTSC)", "", "Homebrew", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "AUTO 55", "", "", "", "", "", "", "", "" }, + { "f802fa61011dd9eb6f80b271bac479d0", "Suntek", "SS-023", "Mole Hunter (1983) (Suntek) (PAL)", "AKA Topy", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f80cf77164079d774b9b0fae33dffca9", "", "", "Fu Kung! (V0.15) (Negative Version) (05-02-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8240e62d8c0a64a61e19388414e3104", "Activision, Steve Cartwright", "AX-013", "Barnstorming (1982) (Activision)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f825c538481f9a7a46d1e9bc06200aaf", "Atari, Richard Maurer - Sears", "CX2635 - 49-75157", "Maze Craze (1980) (Atari)", "AKA A Game of Cops 'n Robbers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "NTSC", "", "", "", "", "", "", "" }, + { "f844f4c6f3baaaf5322657442d6f29eb", "Atari, Sam Comstock, Richard Dobbis, Nick 'Sandy Maiwald' Turner", "CX26111", "Snoopy and the Red Baron (1983) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f847fb8dba6c6d66d13724dbe5d95c4d", "Absolute Entertainment, David Crane", "AG-042-02, AG-042-04", "Skate Boardin' (1987) (Absolute)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8582bc6ca7046adb8e18164e8cecdbc", "", "", "Panda Chase (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8648d0c6ad1266434f6c485ff69ec40", "CCE", "", "Oink! (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8811d45a9935cca90c62f924712f8e6", "Jone Yuan Telephonic Enterprise Co", "", "Chopper Command (Jone Yuan) (Hack)", "2600 Screen Search Console", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8b2a6a4d73ebff10d805a9b59041986", "Activision, Larry Kaplan - Ariola", "EAX-006, PAX-006 - 771 006-720", "Bridge (1980) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8bfd99163d2c4ec688357786e6fba28", "", "", "Eckhard Stolberg's Scrolling Text Demo 2 (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8c1c4a41303bd40b0d6c81bfaf8573b", "HES", "773-891", "2 Pak Special - Dungeon Master, Creature Strike (1992) (HES) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8fbe2b07345086fc867bceeaf38dc48", "Atari, Eric Manghise, Mimi Nyden, Joseph Tung", "CX2640", "RealSports Baseball (1982) (Atari) (Prototype) (4K)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f8ff34b53d86f55bd52d7a520af6d1dc", "", "", "Big Dig (04-04-2003) (CT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f90b5da189f24d7e1a2117d8c8abc952", "Atari, David Crane - Sears", "CX2653 - 6-99823, 49-75111", "Slot Machine (1979) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f91fb8da3223b79f1c9a07b77ebfa0b2", "Atari, Alan J. Murphy, Nick 'Sandy Maiwald' Turner - Sears", "CX2615 - 49-75140", "Demons to Diamonds (1982) (Atari)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "10 57", "", "", "", "", "", "", "", "" }, + { "f93d7fee92717e161e6763a88a293ffa", "20th Century Fox Video Games - Lazer Micro Systems - Dunhill Electronics, B. Winston Hendrickson, Randall Hyde, Mark V. Rhoads, John Simonds", "11013", "Porky's (1983) (20th Century Fox)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9420173efcb4b9f2b01c2a7b595cca7", "CCE", "", "Laser Blast (CCE) (4K)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f954381f9e0f2009d1ac40dedd777b1a", "Thomas Jentzsch", "", "Robot City (V0.18) (01-09-2002) (TJ)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9655ed51462ecfc690c7b97cec649f9", "Andrew Wallace", "", "Laseresal 2002 (PAL) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f965cc981cbb0822f955641f8d84e774", "Answer Software Corporation - TY Associates, Kim Ellis", "ASC2001", "Confrontation (1983) (Answer) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "f9660ebed66fee8bdfdf07b4faa22941", "VGS", "", "Vanguard (VGS)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9677b2ec8728a703eb710274474613d", "Atari, Ian Shepard", "CX2604, CX2604P", "Space War (1978) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f97dee1aa2629911f30f225ca31789d4", "Avalon Hill, Jean Baer, Bill 'Rebecca Ann' Heineman, Jim Jacob", "5005002", "Out of Control (1983) (Avalon Hill)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f98d2276d4a25b286135566255aea9d0", "Digitel", "", "Name This Game (1983) (Digitel)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f98d869f287d2ce4f8fb36e0686929d9", "", "", "Skeleton+ (17-04-2003) (Eric Ball) (NTSC)", "", "", "STEREO", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f991e0670b5f67faa6b6211e9bd81b91", "Nukey Shay, Omegamatrix", "", "Double Dragon (Genesis) (PAL) V2", "Genesis controller", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f992a39b46aa48188fab12ad3809ae4a", "", "", "Sky Jinks (Unknown) (PAL) (Hack)", "", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9967369943209b4788d4e92cefc0795", "Atari", "CX26163P", "Fishing (32 in 1) (1988) (Atari) (PAL) (4K)", "AKA Fishing Derby", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9cef637ea8e905a10e324e582dd39c2", "CCE", "", "Private Eye (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9d51a4e5f8b48f68770c89ffd495ed1", "Atari, Tod Frye, Mimi Nyden", "CX2657", "SwordQuest - FireWorld (1982) (Atari)", "AKA Adventure II, SwordQuest II - FireWorld", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9da42f91a1c5cfa344d2ff440c6f8d4", "ZUT", "", "Pac Invaders (ZUT)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9de91d868d6ebfb0076af9063d7195e", "", "", "Maze Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "f9e99596345a84358bc5d1fbe877134b", "Activision, Larry Kaplan, David Crane - Ariola", "EAG-010, PAG-010 - 711 010-720", "Kaboom! (1981) (Activision) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 50", "", "", "", "", "", "", "", "" }, + { "fa0570561aa80896f0ead05c46351389", "Tigervision", "7-008", "Miner 2049er (1983) (Tigervision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa1b060fd8e0bca0c2a097dcffce93d3", "Atari - CCW, Christopher H. Omarzu, Preston Stuart, Bruce Williams", "CX26101", "Oscar's Trash Race (1984) (Atari)", "Uses the Keypad Controllers", "", "", "", "", "", "", "", "", "KEYBOARD", "KEYBOARD", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa2be8125c3c60ab83e1c0fe56922fcb", "Camelot - DSD, Michael Doherty, Clyde Hager - Johnson & Johnson", "", "Tooth Protectors (1983) (Camelot)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fa3de71841c0841db6a741884a6b6b2f", "", "", "Warring Worms (17-02-2002) (Billy Eno)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa4404fabc094e3a31fcd7b559cdd029", "Atari, Alan J. Murphy, Robert C. Polaro", "CX26100", "Bugs Bunny (1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa529ec88eca679f6d5fd0ccb2120e46", "", "", "20 Sprites at Once Demo 1 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa6fe97a10efb9e74c0b5a816e6e1958", "ZiMAG - Emag - Vidco", "707-111 - GN-030", "Tanks But No Tanks (1983) (ZiMAG)", "AKA Phantom Tank", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa7ce62e7fd77e02b3e2198d70742f80", "Atari, Peter C. Niday", "CX26108", "Donald Duck's Speedboat (04-18-1983) (Atari) (Prototype) (PAL)", "AKA Donald Duck's Regatta", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa7e11a3dbea4365975cd2f094e61d25", "Tim Snider", "", "Mystery Science Theater 2600 (1999) (Tim Snider) (Hack)", "Hack of Megamania", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fa98d48cd609c9babc819e0a1bd8d598", "AtariAge (Chris Walton)", "", "Juno First (2009) (PAL60)", "AtariVox supported", "Homebrew", "", "", "", "", "", "", "", "", "ATARIVOX", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fab7b04b9f42df761eb6f2bc445eaa99", "20th Century Fox Video Games - Sirius Software, David Lubar", "11008", "Fantastic Voyage (11-04-1982) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fabca526d57de46768b392f758f1a008", "", "", "Laseresal 2600 (16-12-2001) (Andrew Wallace) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fac28963307b6e85082ccd77c88325e7", "CCE", "", "Berzerk (CCE)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fadb89f9b23beb4d43a7895c532757e2", "Galaga Games", "", "River Raid (1984) (Galaga Games) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fae0b86934a7c5a362281dffebdb43a0", "Retroactive", "", "Qb (2.07) (Retroactive) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "faebcb2ef1f3831b2fc1dbd39d36517c", "Atari, Jerome Domurat, Steve Woita", "CX2696", "Asterix (1984) (Atari) (PAL)", "AKA Taz", "Extremely Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "faed2ef6b44894f8c83f2b50891c35c6", "CCE", "", "Super Baseball (CCE)", "AKA RealSports Baseball", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "faffd84f3a8eceee2fa5ea5b0a3e6678", "Suntek", "SS-025", "Spectracube Invasion (1983) (Suntek) (PAL)", "AKA Immies & Aggies", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb09ee4ccd47ae74a3c314f0d8a40344", "", "", "Titans (SnailSoft)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb0c32ef7af5b45486db663510094be8", "", "", "Demo Image Series #15 - Three Marios (NTSC) (Non-Interleave) (06-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb0e84cee4c108d24253bcb7e382cffd", "", "", "Interleaved ChronoColour Demo (SECAM) (05-03-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb27afe896e7c928089307b32e5642ee", "M Network - INTV - APh Technological Consulting, Jeff Ronne, Brett Stutz", "MT5662", "TRON - Deadly Discs (1983) (M Network)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb4ca865abc02d66e39651bd9ade140a", "Arcadia Corporation, Brian McGhie", "AR-4104", "Rabbit Transit (1983) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb531febf8e155328ec0cd39ef77a122", "", "", "Worm War I (208 in 1) (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fb5c8af97bd8ffe88323656f462645a7", "", "", "Interlace Demo (Glenn Saunders)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fb833ed50c865a9a505a125fc9d79a7e", "ITT Family Games", "", "Pumuckl I (1983) (ITT Family Games) (PAL)", "AKA Panda Chase", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb884ffd89013331a6f01ae3f6abd214", "Activision, David Crane", "", "Venetian Blinds Demo (1982) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb88baa01afd34e0e4b601e1d29bc806", "Manuel Polik", "", "Star Fire (2003) (XYPE)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb88c400d602fe759ae74ef1716ee84e", "20th Century Fox Video Games, Bill Aspromonte", "11031", "Crash Dive (1983) (20th Century Fox)", "AKA Voyage to the Bottom of the Sea", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb91da78455d9b1606913fbf8c859772", "", "", "Split Screen (Ballblazer) Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fb91dfc36cddaa54b09924ae8fd96199", "Parker Brothers, Mark Lesser", "PB5590", "Frogger II (1984) (Parker Bros) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fb978f1c053e8061cc37a726639f43f7", "Atari - Axlon, Tod Frye - Heuristica, Agustin Ortiz", "CX26169", "Shooting Arcade (03-07-1989) (Atari) (Prototype)", "Uses the Light Gun Controller (left only)", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fbac6476e7b2b20d246202af81662c88", "Starpath Corporation, Stephen H. Landrum", "AR-4400", "Dragonstomper (Preview) (1982) (Starpath) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fbb0151ea2108e33b2dbaae14a1831dd", "Thomas Jentzsch", "", "Robot Tank TV (Thomas Jentzsch) (Hack)", "Uses two simultaneous Joystick Controllers, Hack of Robot Tank", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fbb4f3debf48dc961b559384467f2057", "Digitel", "", "River Raid III (1985) (Digitel)", "AKA River Raid", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fbe554aa8f759226d251ba6b64a9cce4", "Atari - GCC, Mike Feinstein, Brad Rice", "CX2681, CX2681P", "Battlezone (1983) (Atari) (PAL)", "", "Uncommon", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fbfebee9c14694719e3eda4854dc42ee", "Jake Patterson", "", "Baubles 3 (Jake Patterson) (PD)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc2104dd2dadf9a6176c1c1c8f87ced9", "Coleco - Woodside Design Associates, Harley H. Puthuff Jr.", "2663", "Time Pilot (1983) (Coleco)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc2233fc116faef0d3c31541717ca2db", "Atari, Tod Frye", "CX2646", "Pac-Man (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc24a94d4371c69bc58f5245ada43c44", "Atari - Axlon, Steve DeFrisco", "CX26170", "Secret Quest (1989) (Atari)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc6052438f339aea373bbc999433388a", "Atari, David Crane", "CX2653P", "Slot Machine (1979) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc668a2251dd79cbd903d4fa0e558f96", "Thomas Jentzsch", "", "Thrust (V1.1) (2000) (TJ) [a1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc92d74f073a44bc6e46a3b3fa8256a2", "", "", "Megademo (19xx) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fc9c1652fe3a2cade6188f4d3692481f", "Andrew Davies", "", "Andrew Davies early notBoulderDash demo (NTSC)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fca4a5be1251927027f2c24774a02160", "Activision, John Van Ryzin", "AZ-036-04", "H.E.R.O. (1984) (Activision)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fcbbd0a407d3ff7bf857b8a399280ea1", "ZiMAG - Emag - Vidco", "GN-070", "Mysterious Thief, A (1983) (ZiMAG) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fcbdf405f0fc2027b0ea45bb5af94c1a", "Amiga - Video Soft, Michael K. Glass, Jerry Lawson", "", "3-D Ghost Attack (1983) (Amiga) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fcea12625c071ddc49f4e409f4038c60", "Fabrizio Zavagli", "", "Balls! (16-09-2002) (Fabrizio Zavagli)", "", "Homebrew", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "YES", "", "", "", "", "" }, + { "fcf8e306f6615f74feba5cb25550038c", "", "", "Blue Dot Demo (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd0e5148162e8ec6719445d559f018a9", "Activision, Steve Cartwright - Ariola", "EAX-022, EAX-022-04I - 711 022-720", "Seaquest (1983) (Activision) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd10915633aea4f9cd8b518a25d62b55", "Atari, John Dunn", "CX2631, CX2631P", "Superman (1979) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd16949913aaab5beaefed73bf2ca67c", "Atari - GCC, John Allred, Mike Feinstein", "CX2688", "Jungle Hunt (02-03-1983) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd4f5536fd80f35c64d365df85873418", "Atari - Bobco, Robert C. Polaro", "CX26140", "Desert Falcon (1987) (Atari)", "AKA Nile Flyer, Sphinx", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd6e507b5df68beeeddeaf696b6828fa", "", "", "Boxing (Unknown) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd7464edaa8cc264b97ba0d13e7f0678", "HES", "771-333", "2 Pak Special - Challenge, Surfing (1990) (HES) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd78f186bdff83fbad7f97cb583812fe", "Amiga - Video Soft", "3125", "Surf's Up (1983) (Amiga) (Prototype) [a2]", "Uses the Joyboard controller", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd8b4ee0d57605b35e236e814f706ff1", "Atari - GCC, Mike Feinstein, John Mracek", "CX2673, CX2673P", "Phoenix (1982) (Atari) (PAL) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fd9b321cee5fbb32c39ba3ca5d9ec7cf", "Jeffry Johnston", "", "Radial Pong - Version 5 (Jeffry Johnston) (PD)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fdd4995a50395db14f518f63c2d63438", "", "", "Oh No! (Version 3) (18-01-2003) (AD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fde42e39710e75e9e4d4d75440f8e4e5", "Thomas Jentzsch", "", "Coke Zero (v1.0) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fdf0de38517e0cf7f0885f98ccc95836", "Arcadia Corporation, Dennis Caswell", "AR-4200", "Escape from the Mindmaster (2 of 4) (1982) (Arcadia)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fdf6680b2b1e8054293a39700a765692", "", "", "Alpha Demo - The Beta Demo 2 (2000) (MP)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe0b7f27e3ad50bbf9ff468ee56d553d", "", "", "Lines Demo (Eckhard Stolberg) (PAL) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe0bc4bb92c1c4de7d5706aaa8d8c10d", "", "", "Sprite Demo 2 (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe3b461d4c8b179fe68bc77760294c25", "Atari, Joe Decuir", "CX2621, CX2621P", "Video Olympics (1977) (Atari) (PAL) (4K)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe641247a4ab9bee970e19ab55f23b25", "20th Century Fox Video Games, Beck-Tech, Steve Beck", "11035", "Save the Whales (02-07-1983) (20th Century Fox) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe67087f9c22655ce519616fc6c6ef4d", "Atari - Zip Technology, Randy Bowker, Bruce Williams", "CX26142", "Crack'ed (11-28-1988) (Atari) (Prototype)", "", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe6abc0f63e31e2646c9c600926b5b7f", "Atari", "CX26137", "4 in 1 (02-19-1987) (Atari) (Prototype)", "Home Run, Canyon Bomber, Sky Diver, Night Driver", "Prototype", "", "", "4IN1", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe870018332a0221eb59fb18b0c6bccc", "", "", "Incoming (08-11-2002) (Ben Larson) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fe9ae625d924b54c9f8a14ac9a0f6c6d", "BG Dodson", "", "High Bid! (BG Dodson) (Hack)", "Hack of Pepsi Invaders", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "feba8686fd0376015258d1152923958a", "", "", "Super Circus (Unknown) (PAL)", "AKA Circus Atari", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fec0c2e2ab0588ed20c750b58cf3baa3", "Activision - Cheshire Engineering, David Rolfe, Larry Zwick", "EAZ-037-04, EAZ-037-04I", "Beamrider (1984) (Activision) (PAL)", "", "Rare", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "fece458a8023a809a5006867feca40e8", "", "", "SCSIcide (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "feec54aac911887940b47fe8c9f80b11", "Atari, Rob Fulop", "CX2633, CX2633P", "Night Driver (1980) (Atari) (PAL)", "Uses the Paddle Controllers (left only)", "", "", "", "", "", "", "", "", "", "", "", "", "", "AUTO 65", "", "", "YES", "", "", "", "", "" }, + { "feedcc20bc3ca34851cd5d9e38aa2ca6", "Atari, David Crane - Sears", "CX2607 - 6-99828, 49-75115", "Canyon Bomber (1979) (Atari)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXDR", "", "YES", "", "", "10", "", "", "", "", "", "", "", "" }, + { "ff1523783e0e76a3b0d1f7f0d1cb3050", "Thomas Jentzsch", "", "Marble Craze - Atari Trak-Ball Hack v1.0 (PAL) (TJ)", "Uses Atari Trak-Ball Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ff3bd0c684f7144aeaa18758d8281a78", "Atari, Bob Whitehead", "CX2651", "Blackjack (1977) (Atari) (PAL)", "Uses the Paddle Controllers", "Rare", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ff5a9e340d96df6f5a5b6eb038e923bd", "", "", "Space Shuttle (1983) (Activision) [t1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ff7627207e8aa03730c35c735a82c26c", "Atari, Bob Whitehead", "CX26163P", "Blackjack (32 in 1) (1988) (Atari) (PAL)", "Uses the Paddle Controllers", "", "", "", "", "", "", "", "", "PADDLES_IAXIS", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ff86fc8ffa717bb095e8471638c1c31c", "Arcadia Corporation, Dennis Caswell", "AR-4302", "Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia) (PAL)", "Uses Paddle Controllers", "", "", "", "", "", "", "", "", "", "", "", "", "", "01 56", "", "", "", "", "", "", "", "" }, + { "ff87d58125ae517eb7b09a0475a1ccdc", "", "", "SCSIcide (Score Hack 1) (24-02-2001) (Joe Grand) (PD)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ffb1cd548563158ce33f9d10268187e7", "Erik Eid", "", "Euchre (Beta) (NTSC) (12-09-2002) (Erik Eid)", "", "New Release", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ffc0ff4305dd46b4b459885bd1818e2e", "Barry Laws Jr.", "", "Star Wars - The Battle of Alderaan (Star Strike Hack)", "Hack of Star Strike (Mattel)", "New Release (Hack)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ffdc0eb3543404eb4c353fbdddfa33b6", "CCE", "C-827", "Chopper Command (1983) (CCE) [a]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ffe51989ba6da2c6ae5a12d277862e16", "Atari - Sears", "CX2627 - 6-99841", "Human Cannonball (1979) (Atari) (4K)", "AKA Cannon Man", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }, + { "ffebb0070689b9d322687edd9c0a2bae", "", "", "Spitfire Attack (1983) (Milton Bradley) [h1]", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" } }}; #endif diff --git a/src/emucore/Device.hxx b/src/emucore/Device.hxx index 444a599af..fb2423a35 100644 --- a/src/emucore/Device.hxx +++ b/src/emucore/Device.hxx @@ -20,9 +20,9 @@ class System; -#include "Console.hxx" -#include "Serializable.hxx" #include "bspf.hxx" +#include "ConsoleTiming.hxx" +#include "Serializable.hxx" /** Abstract base class for devices which can be attached to a 6502 @@ -32,6 +32,39 @@ class System; */ class Device : public Serializable { + public: + enum AccessType { + NONE = 0, + REFERENCED = 1 << 0, /* 0x01, code somewhere in the program references it, + i.e. LDA $F372 referenced $F372 */ + VALID_ENTRY = 1 << 1, /* 0x02, addresses that can have a label placed in front of it. + A good counterexample would be "FF00: LDA $FE00"; $FF01 + would be in the middle of a multi-byte instruction, and + therefore cannot be labelled. */ + + // The following correspond to specific types that can be set within the + // debugger, or specified in a Distella cfg file, and are listed in order + // of increasing hierarchy + // + ROW = 1 << 2, // 0x004, all other addresses + DATA = 1 << 3, // 0x008, addresses loaded into registers other than GRPx / PFx / COLUxx, AUDxx + AUD = 1 << 4, // 0x010, addresses loaded into audio registers + BCOL = 1 << 5, // 0x020, addresses loaded into COLUBK register + PCOL = 1 << 6, // 0x040, addresses loaded into COLUPF register + COL = 1 << 7, // 0x080, addresses loaded into COLUPx registers + PGFX = 1 << 8, // 0x100, addresses loaded into PFx registers + GFX = 1 << 9, // 0x200, addresses loaded into GRPx registers + TCODE = 1 << 10, // 0x400, (tentative) disassemble-able code segments + CODE = 1 << 11, // 0x800, disassemble-able code segments + // special bits for address + HADDR = 1 << 13 | 1 << 14 | 1 << 15, // 0xe000, // highest 3 address bits + // special type for poke() + WRITE = TCODE // 0x200, address written to + }; + using AccessFlags = uInt16; + + using AccessCounter = uInt32; + public: Device() = default; virtual ~Device() = default; @@ -97,20 +130,36 @@ class Device : public Serializable */ virtual bool poke(uInt16 address, uInt8 value) { return false; } + #ifdef DEBUGGER_SUPPORT /** - Query the given address for its disassembly flags + Query the given address for its access flags @param address The address to modify */ - virtual uInt8 getAccessFlags(uInt16 address) const { return 0; } + virtual AccessFlags getAccessFlags(uInt16 address) const { return AccessType::NONE; } /** - Change the given address type to use the given disassembly flags + Change the given address type to use the given access flags @param address The address to modify - @param flags A bitfield of DisasmType directives for the given address + @param flags A bitfield of AccessType directives for the given address */ - virtual void setAccessFlags(uInt16 address, uInt8 flags) { } + virtual void setAccessFlags(uInt16 address, AccessFlags flags) { } + + /** + Increase the given address's access counter + + @param address The address to modify + */ + virtual void increaseAccessCounter(uInt16 address, bool isWrite = false) { } + + /** + Query the access counters + + @return The access counters as comma separated string + */ + virtual string getAccessCounters() const { return ""; } + #endif protected: /// Pointer to the system the device is installed in or the null pointer diff --git a/src/emucore/DispatchResult.hxx b/src/emucore/DispatchResult.hxx index 4ce172aeb..6d76cf5ce 100644 --- a/src/emucore/DispatchResult.hxx +++ b/src/emucore/DispatchResult.hxx @@ -55,7 +55,7 @@ class DispatchResult if (myStatus != status) throw runtime_error("invalid status for operation"); } - template void assertStatus(Status status, Ts... more) const + template void assertStatus(Status status, Ts... more) const { if (myStatus == status) return; diff --git a/src/emucore/Driving.cxx b/src/emucore/Driving.cxx index 74fa30139..bd08a03e0 100644 --- a/src/emucore/Driving.cxx +++ b/src/emucore/Driving.cxx @@ -49,12 +49,9 @@ Driving::Driving(Jack jack, const Event& event, const System& system) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Driving::update() { - // Make sure direct gray codes from Stelladaptor stay in sync with - // simulated gray codes generated by PC keyboard or PC joystick - myCounter = (myGrayIndex << 2) | (myCounter & 3); - // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; + int d_axis = myEvent.get(myXAxisValue); if(myEvent.get(myCCWEvent) != 0 || d_axis < -16384) --myCounter; else if(myEvent.get(myCWEvent) != 0 || d_axis > 16384) ++myCounter; @@ -65,9 +62,9 @@ void Driving::update() int m_axis = myEvent.get(Event::MouseAxisXMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } else { @@ -78,22 +75,22 @@ void Driving::update() int m_axis = myEvent.get(Event::MouseAxisXMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); } if(myControlIDY > -1) { int m_axis = myEvent.get(Event::MouseAxisYMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonRightValue); } } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); // Only consider the lower-most bits (corresponding to pins 1 & 2) - myCounter &= 0x0f; - myGrayIndex = myCounter >> 2; + myGrayIndex = Int32(myCounter * SENSITIVITY / 4.0F) & 0b11; // Stelladaptor is the only controller that should set this int yaxis = myEvent.get(myYAxisValue); @@ -111,6 +108,10 @@ void Driving::update() myGrayIndex = 2; // up + down else /* if(yaxis < 16384-4096) */ myGrayIndex = 0; // no movement + + // Make sure direct gray codes from Stelladaptor stay in sync with + // simulated gray codes generated by PC keyboard or PC joystick + myCounter = myGrayIndex / SENSITIVITY * 4.0F; } // Gray codes for rotation @@ -154,3 +155,13 @@ bool Driving::setMouseControl( return true; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Driving::setSensitivity(int sensitivity) +{ + BSPF::clamp(sensitivity, 1, 20, 10); + SENSITIVITY = sensitivity / 10.0F; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float Driving::SENSITIVITY = 1.0; diff --git a/src/emucore/Driving.hxx b/src/emucore/Driving.hxx index 51c0226c3..6d0adaea8 100644 --- a/src/emucore/Driving.hxx +++ b/src/emucore/Driving.hxx @@ -76,9 +76,18 @@ class Driving : public Controller bool setMouseControl( Controller::Type xtype, int xid, Controller::Type ytype, int yid) override; + /** + Sets the sensitivity for digital emulation of driving controlle movement + using a keyboard. + + @param sensitivity Value from 1 to 20, with larger values causing + more movement (10 represents the baseline) + */ + static void setSensitivity(int sensitivity); + private: // Counter to iterate through the gray codes - uInt32 myCounter{0}; + Int32 myCounter{0}; // Index into the gray code table uInt32 myGrayIndex{0}; @@ -98,6 +107,10 @@ class Driving : public Controller // Controllers to emulate in 'specific' mouse axis mode int myControlIDX{-1}, myControlIDY{-1}; + // User-defined sensitivity; adjustable since end-users may prefer different + // speeds + static float SENSITIVITY; + private: // Following constructors and assignment operators not supported Driving() = delete; diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 045a0bc8b..0ca7764fd 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -22,7 +22,6 @@ #include #include "bspf.hxx" -#include "StellaKeys.hxx" /** @author Stephen Anthony, Christian Speckner, Thomas Jentzsch @@ -92,6 +91,7 @@ class Event TogglePauseMode, StartPauseMode, OptionsMenuMode, CmdMenuMode, DebuggerMode, ExitMode, TakeSnapshot, ToggleContSnapshots, ToggleContSnapshotsFrame, + ToggleTurbo, NextState, PreviousState, LoadState, SaveState, SaveAllStates, LoadAllStates, @@ -100,12 +100,15 @@ class Event Unwind1Menu, Unwind10Menu, UnwindAllMenu, RewindPause, UnwindPause, - FormatDecrease, FormatIncrease, TogglePalette, ToggleColorLoss, + FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss, + PreviousPaletteAttribute, NextPaletteAttribute, + PaletteAttributeDecrease, PaletteAttributeIncrease, ToggleFullScreen, VidmodeDecrease, VidmodeIncrease, - VCenterDecrease, VCenterIncrease, ScanlineAdjustDecrease, ScanlineAdjustIncrease, + VCenterDecrease, VCenterIncrease, VSizeAdjustDecrease, VSizeAdjustIncrease, OverscanDecrease, OverscanIncrease, VidmodeStd, VidmodeRGB, VidmodeSVideo, VidModeComposite, VidModeBad, VidModeCustom, + PreviousVideoMode, NextVideoMode, PreviousAttribute, NextAttribute, DecreaseAttribute, IncreaseAttribute, ScanlinesDecrease, ScanlinesIncrease, PhosphorDecrease, PhosphorIncrease, TogglePhosphor, ToggleInter, ToggleJitter, @@ -118,10 +121,14 @@ class Event ToggleCollisions, ToggleBits, ToggleFixedColors, ToggleFrameStats, ToggleSAPortOrder, ExitGame, - + SettingDecrease, SettingIncrease, PreviousSetting, NextSetting, + ToggleAdaptRefresh, PreviousMultiCartRom, // add new events from here to avoid that user remapped events get overwritten + PreviousSettingGroup, NextSettingGroup, + TogglePlayBackMode, + DecreaseAutoFire, IncreaseAutoFire, + DecreaseSpeed, IncreaseSpeed, HighScoresMenuMode, - LastType }; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index b2779c41f..c57a29fb1 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -22,6 +22,7 @@ #include "Base.hxx" #include "Console.hxx" +#include "PaletteHandler.hxx" #include "FrameBuffer.hxx" #include "FSNode.hxx" #include "OSystem.hxx" @@ -29,6 +30,7 @@ #include "Paddles.hxx" #include "Lightgun.hxx" #include "PointingDevice.hxx" +#include "Driving.hxx" #include "PropsSet.hxx" #include "Settings.hxx" #include "Sound.hxx" @@ -65,6 +67,8 @@ #include "ScrollBarWidget.hxx" #endif +using namespace std::placeholders; + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EventHandler::EventHandler(OSystem& osystem) : myOSystem(osystem) @@ -101,6 +105,8 @@ void EventHandler::initialize() Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense")); Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense")); PointingDevice::setSensitivity(myOSystem.settings().getInt("tsense")); + Driving::setSensitivity(myOSystem.settings().getInt("dcsense")); + Controller::setAutoFireRate(myOSystem.settings().getInt("autofirerate")); #ifdef GUI_SUPPORT // Set quick select delay when typing characters in listwidgets @@ -332,8 +338,9 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int) #endif #if 0 case SystemEvent::WINDOW_MINIMIZED: - if(myState == EventHandlerState::EMULATION) enterMenuMode(EventHandlerState::OPTIONSMENU); - break; + if(myState == EventHandlerState::EMULATION) + enterMenuMode(EventHandlerState::OPTIONSMENU); + break; #endif default: // handle other events as testing requires // cerr << "handleSystemEvent: " << e << endl; @@ -341,15 +348,240 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EventHandler::AdjustGroup EventHandler::getAdjustGroup() +{ + if (myAdjustSetting >= AdjustSetting::START_DEBUG_ADJ && myAdjustSetting <= AdjustSetting::END_DEBUG_ADJ) + return AdjustGroup::DEBUG; + + return AdjustGroup::AV; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AdjustFunction EventHandler::cycleAdjustSetting(int direction) +{ + const bool isFullScreen = myOSystem.frameBuffer().fullScreen(); + const bool isCustomPalette = + myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM; + const bool isCustomFilter = + myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM); + const bool isPAL = myOSystem.console().timing() == ConsoleTiming::pal; + bool repeat = false; + + do + { + switch (getAdjustGroup()) + { + case AdjustGroup::AV: + myAdjustSetting = + AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction, + int(AdjustSetting::START_AV_ADJ), int(AdjustSetting::END_AV_ADJ))); + // skip currently non-relevant adjustments + repeat = (myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen) + #ifdef ADAPTABLE_REFRESH_SUPPORT + || (myAdjustSetting == AdjustSetting::ADAPT_REFRESH && !isFullScreen) + #endif + || (myAdjustSetting == AdjustSetting::PALETTE_PHASE && !isCustomPalette) + || (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS + && myAdjustSetting <= AdjustSetting::NTSC_BLEEDING + && !isCustomFilter); + break; + + case AdjustGroup::DEBUG: + myAdjustSetting = + AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction, + int(AdjustSetting::START_DEBUG_ADJ), int(AdjustSetting::END_DEBUG_ADJ))); + repeat = (myAdjustSetting == AdjustSetting::COLOR_LOSS && !isPAL); + break; + + default: + break; + } + // avoid endless loop + if(repeat && !direction) + direction = 1; + } while(repeat); + + return getAdjustSetting(myAdjustSetting); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting) +{ + // Notes: + // - All methods MUST show a message + // - This array MUST have the same order as AdjustSetting + const AdjustFunction ADJUST_FUNCTIONS[int(AdjustSetting::NUM_ADJ)] = + { + // Audio & Video settings + std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1), + std::bind(&FrameBuffer::selectVidMode, &myOSystem.frameBuffer(), _1), + std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1), + #ifdef ADAPTABLE_REFRESH_SUPPORT + std::bind(&FrameBuffer::toggleAdaptRefresh, &myOSystem.frameBuffer(), _1), + #endif + std::bind(&FrameBuffer::changeOverscan, &myOSystem.frameBuffer(), _1), + std::bind(&Console::selectFormat, &myOSystem.console(), _1), + std::bind(&Console::changeVerticalCenter, &myOSystem.console(), _1), + std::bind(&Console::changeVSizeAdjust, &myOSystem.console(), _1), + // Palette adjustables + std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::PHASE_SHIFT, _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::HUE, _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::SATURATION, _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::CONTRAST, _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::BRIGHTNESS, _1), + std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), + PaletteHandler::GAMMA, _1), + // NTSC filter adjustables + std::bind(&TIASurface::changeNTSC, &myOSystem.frameBuffer().tiaSurface(), _1), + std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), + int(NTSCFilter::Adjustables::SHARPNESS), _1), + std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), + int(NTSCFilter::Adjustables::RESOLUTION), _1), + std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), + int(NTSCFilter::Adjustables::ARTIFACTS), _1), + std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), + int(NTSCFilter::Adjustables::FRINGING), _1), + std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), + int(NTSCFilter::Adjustables::BLEEDING), _1), + std::bind(&Console::changePhosphor, &myOSystem.console(), _1), + std::bind(&TIASurface::setScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1), + std::bind(&Console::toggleInter, &myOSystem.console(), _1), + // Debug settings + std::bind(&FrameBuffer::toggleFrameStats, &myOSystem.frameBuffer(), _1), + std::bind(&Console::toggleP0Bit, &myOSystem.console(), _1), + std::bind(&Console::toggleP1Bit, &myOSystem.console(), _1), + std::bind(&Console::toggleM0Bit, &myOSystem.console(), _1), + std::bind(&Console::toggleM1Bit, &myOSystem.console(), _1), + std::bind(&Console::toggleBLBit, &myOSystem.console(), _1), + std::bind(&Console::togglePFBit, &myOSystem.console(), _1), + std::bind(&Console::toggleBits, &myOSystem.console(), _1), + std::bind(&Console::toggleP0Collision, &myOSystem.console(), _1), + std::bind(&Console::toggleP1Collision, &myOSystem.console(), _1), + std::bind(&Console::toggleM0Collision, &myOSystem.console(), _1), + std::bind(&Console::toggleM1Collision, &myOSystem.console(), _1), + std::bind(&Console::toggleBLCollision, &myOSystem.console(), _1), + std::bind(&Console::togglePFCollision, &myOSystem.console(), _1), + std::bind(&Console::toggleCollisions, &myOSystem.console(), _1), + std::bind(&Console::toggleFixedColors, &myOSystem.console(), _1), + std::bind(&Console::toggleColorLoss, &myOSystem.console(), _1), + std::bind(&Console::toggleJitter, &myOSystem.console(), _1), + // Following functions are not used when cycling settings but for "direct only" hotkeys + std::bind(&StateManager::changeState, &myOSystem.state(), _1), + std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1), + std::bind(&TIASurface::changeCurrentNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), _1), + std::bind(&Console::changeSpeed, &myOSystem.console(), _1), + }; + + return ADJUST_FUNCTIONS[int(setting)]; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) { // Take care of special events that aren't part of the emulation core // or need to be preprocessed before passing them on - bool pressed = (value != 0); + const bool pressed = (value != 0); + + // The global settings keys change settings or values as long as the setting + // message from the previous settings event is still displayed. + // Therefore, do not change global settings/values or direct values if + // a) the setting message is no longer shown + // b) other keys have been pressed + if(!myOSystem.frameBuffer().messageShown()) + { + myAdjustActive = false; + myAdjustDirect = AdjustSetting::NONE; + } + + const bool adjustActive = myAdjustActive; + const AdjustSetting adjustAVDirect = myAdjustDirect; + + if(pressed) + { + myAdjustActive = false; + myAdjustDirect = AdjustSetting::NONE; + } switch(event) { + //////////////////////////////////////////////////////////////////////// + // Allow adjusting several (mostly repeated) settings using the same six hotkeys + + case Event::PreviousSettingGroup: + case Event::NextSettingGroup: + if (pressed && !repeated) + { + const int direction = event == Event::PreviousSettingGroup ? -1 : +1; + AdjustGroup adjustGroup = AdjustGroup(BSPF::clampw(int(getAdjustGroup()) + direction, + 0, int(AdjustGroup::NUM_GROUPS) - 1)); + string msg; + + switch (adjustGroup) + { + case AdjustGroup::AV: + msg = "Audio & Video"; + myAdjustSetting = AdjustSetting::START_AV_ADJ; + break; + + case AdjustGroup::DEBUG: + msg = "Debug"; + myAdjustSetting = AdjustSetting::START_DEBUG_ADJ; + break; + + default: + break; + } + myOSystem.frameBuffer().showMessage(msg + " settings"); + myAdjustActive = false; + } + break; + + // Allow adjusting several (mostly repeated) settings using the same four hotkeys + case Event::PreviousSetting: + case Event::NextSetting: + if(pressed && !repeated) + { + const int direction = event == Event::PreviousSetting ? -1 : +1; + + // Get (and display) the previous|next adjustment function, + // but do not change its value + cycleAdjustSetting(adjustActive ? direction : 0)(0); + // Fallback message when no message is displayed by method + //if(!myOSystem.frameBuffer().messageShown()) + // myOSystem.frameBuffer().showMessage("Message " + std::to_string(int(myAdjustSetting))); + myAdjustActive = true; + } + break; + + case Event::SettingDecrease: + case Event::SettingIncrease: + if(pressed) + { + const int direction = event == Event::SettingDecrease ? -1 : +1; + + // if a "direct only" hotkey was pressed last, use this one + if(adjustAVDirect != AdjustSetting::NONE) + { + myAdjustDirect = adjustAVDirect; + getAdjustSetting(myAdjustDirect)(direction); + } + else + { + // Get (and display) the current adjustment function, + // but only change its value if the function was already active before + getAdjustSetting(myAdjustSetting)(adjustActive ? direction : 0); + myAdjustActive = true; + } + } + return; + //////////////////////////////////////////////////////////////////////// // If enabled, make sure 'impossible' joystick directions aren't allowed case Event::JoystickZeroUp: @@ -391,268 +623,529 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if(!myAllowAllDirectionsFlag && pressed) myEvent.set(Event::JoystickOneLeft, 0); break; - //////////////////////////////////////////////////////////////////////// - - case Event::Fry: - if (!repeated) myFryingFlag = pressed; - return; - - case Event::ReloadConsole: - if (pressed && !repeated) myOSystem.reloadConsole(); - return; + /////////////////////////////////////////////////////////////////////////// + // Audio & Video events (with global hotkeys) case Event::VolumeDecrease: - if(pressed) myOSystem.sound().adjustVolume(-1); + if(pressed) + { + myOSystem.sound().adjustVolume(-1); + myAdjustSetting = AdjustSetting::VOLUME; + myAdjustActive = true; + } return; case Event::VolumeIncrease: - if(pressed) myOSystem.sound().adjustVolume(+1); + if(pressed) + { + myOSystem.sound().adjustVolume(+1); + myAdjustSetting = AdjustSetting::VOLUME; + myAdjustActive = true; + } return; case Event::SoundToggle: - if(pressed && !repeated) myOSystem.sound().toggleMute(); + if(pressed && !repeated) + { + myOSystem.sound().toggleMute(); + myAdjustSetting = AdjustSetting::VOLUME; + myAdjustActive = true; + } return; case Event::VidmodeDecrease: - if(pressed) myOSystem.frameBuffer().changeVidMode(-1); + if(pressed) + { + myOSystem.frameBuffer().selectVidMode(-1); + myAdjustSetting = AdjustSetting::ZOOM; + myAdjustActive = true; + } return; case Event::VidmodeIncrease: - if(pressed) myOSystem.frameBuffer().changeVidMode(+1); - return; - - case Event::VCenterDecrease: - if (pressed) myOSystem.console().changeVerticalCenter(-1); - return; - - case Event::VCenterIncrease: - if (pressed) myOSystem.console().changeVerticalCenter(+1); - return; - - case Event::ScanlineAdjustDecrease: - if (pressed) myOSystem.console().changeScanlineAdjust(-1); - return; - - case Event::ScanlineAdjustIncrease: - if (pressed) myOSystem.console().changeScanlineAdjust(+1); + if(pressed) + { + myOSystem.frameBuffer().selectVidMode(+1); + myAdjustSetting = AdjustSetting::ZOOM; + myAdjustActive = true; + } return; case Event::ToggleFullScreen: - if (pressed && !repeated) myOSystem.frameBuffer().toggleFullscreen(); + if (pressed && !repeated) + { + myOSystem.frameBuffer().toggleFullscreen(); + myAdjustSetting = AdjustSetting::FULLSCREEN; + myAdjustActive = true; + } return; + #ifdef ADAPTABLE_REFRESH_SUPPORT + case Event::ToggleAdaptRefresh: + if (pressed && !repeated) + { + myOSystem.frameBuffer().toggleAdaptRefresh(); + myAdjustSetting = AdjustSetting::ADAPT_REFRESH; + myAdjustActive = true; + } + return; + #endif + case Event::OverscanDecrease: - if (pressed) myOSystem.frameBuffer().changeOverscan(-1); + if (pressed) + { + myOSystem.frameBuffer().changeOverscan(-1); + myAdjustSetting = AdjustSetting::OVERSCAN; + myAdjustActive = true; + } return; case Event::OverscanIncrease: - if (pressed) myOSystem.frameBuffer().changeOverscan(1); + if (pressed) + { + myOSystem.frameBuffer().changeOverscan(+1); + myAdjustSetting = AdjustSetting::OVERSCAN; + myAdjustActive = true; + } + return; + + case Event::FormatDecrease: + if (pressed && !repeated) + { + myOSystem.console().selectFormat(-1); + myAdjustSetting = AdjustSetting::TVFORMAT; + myAdjustActive = true; + } + return; + + case Event::FormatIncrease: + if (pressed && !repeated) + { + myOSystem.console().selectFormat(+1); + myAdjustSetting = AdjustSetting::TVFORMAT; + myAdjustActive = true; + } + return; + + case Event::VCenterDecrease: + if(pressed) + { + myOSystem.console().changeVerticalCenter(-1); + myAdjustSetting = AdjustSetting::VCENTER; + myAdjustActive = true; + } + return; + + case Event::VCenterIncrease: + if(pressed) + { + myOSystem.console().changeVerticalCenter(+1); + myAdjustSetting = AdjustSetting::VCENTER; + myAdjustActive = true; + } + return; + + case Event::VSizeAdjustDecrease: + if(pressed) + { + myOSystem.console().changeVSizeAdjust(-1); + myAdjustSetting = AdjustSetting::VSIZE; + myAdjustActive = true; + } + return; + + case Event::VSizeAdjustIncrease: + if(pressed) + { + myOSystem.console().changeVSizeAdjust(+1); + myAdjustSetting = AdjustSetting::VSIZE; + myAdjustActive = true; + } + return; + + case Event::PaletteDecrease: + if (pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(-1); + myAdjustSetting = AdjustSetting::PALETTE; + myAdjustActive = true; + } + return; + + case Event::PaletteIncrease: + if (pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(+1); + myAdjustSetting = AdjustSetting::PALETTE; + myAdjustActive = true; + } + return; + + case Event::PreviousVideoMode: + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().changeNTSC(-1); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } + return; + + case Event::NextVideoMode: + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().changeNTSC(+1); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidmodeStd: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::OFF); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::OFF); + myAdjustDirect = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidmodeRGB: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::RGB); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::RGB); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidmodeSVideo: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::SVIDEO); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::SVIDEO); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidModeComposite: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::COMPOSITE); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::COMPOSITE); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidModeBad: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::BAD); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::BAD); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } return; case Event::VidModeCustom: - if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); + if(pressed && !repeated) + { + myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); + myAdjustSetting = AdjustSetting::NTSC_PRESET; + myAdjustActive = true; + } + return; + case Event::PhosphorDecrease: + if(pressed) + { + myOSystem.console().changePhosphor(-1); + myAdjustSetting = AdjustSetting::PHOSPHOR; + myAdjustActive = true; + } + return; + + case Event::PhosphorIncrease: + if(pressed) + { + myOSystem.console().changePhosphor(+1); + myAdjustSetting = AdjustSetting::PHOSPHOR; + myAdjustActive = true; + } + return; + + case Event::TogglePhosphor: + if(pressed && !repeated) + { + myOSystem.console().togglePhosphor(); + myAdjustSetting = AdjustSetting::PHOSPHOR; + myAdjustActive = true; + } return; case Event::ScanlinesDecrease: - if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-2); + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-1); + myAdjustSetting = AdjustSetting::SCANLINES; + myAdjustActive = true; + } return; case Event::ScanlinesIncrease: - if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+2); + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+1); + myAdjustSetting = AdjustSetting::SCANLINES; + myAdjustActive = true; + } + return; + + case Event::ToggleInter: + if(pressed && !repeated) + { + myOSystem.console().toggleInter(); + myAdjustSetting = AdjustSetting::INTERPOLATION; + myAdjustActive = true; + } + return; + + /////////////////////////////////////////////////////////////////////////// + // Direct key Audio & Video events + case Event::PreviousPaletteAttribute: + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(-1); + myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE; + } + return; + + case Event::NextPaletteAttribute: + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(+1); + myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE; + } + return; + + case Event::PaletteAttributeDecrease: + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(-1); + myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE; + } + return; + + case Event::PaletteAttributeIncrease: + if (pressed) + { + myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(+1); + myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE; + } return; case Event::PreviousAttribute: if (pressed) { - myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); - myOSystem.frameBuffer().showMessage( - myOSystem.frameBuffer().tiaSurface().ntsc().setPreviousAdjustable()); + myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(-1); + myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE; } return; case Event::NextAttribute: if (pressed) { - myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); - myOSystem.frameBuffer().showMessage( - myOSystem.frameBuffer().tiaSurface().ntsc().setNextAdjustable()); + myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(+1); + myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE; } return; case Event::DecreaseAttribute: if (pressed) { - myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); - myOSystem.frameBuffer().showMessage( - myOSystem.frameBuffer().tiaSurface().ntsc().decreaseAdjustable()); + myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(-1); + myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE; } return; case Event::IncreaseAttribute: if (pressed) { - myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM); - myOSystem.frameBuffer().showMessage( - myOSystem.frameBuffer().tiaSurface().ntsc().increaseAdjustable()); + myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(+1); + myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE; } return; - case Event::PhosphorDecrease: - if (pressed) myOSystem.console().changePhosphor(-1); - return; - - case Event::PhosphorIncrease: - if (pressed) myOSystem.console().changePhosphor(1); - return; - - case Event::TogglePhosphor: - if (pressed && !repeated) myOSystem.console().togglePhosphor(); - return; - - case Event::ToggleColorLoss: - if (pressed && !repeated) myOSystem.console().toggleColorLoss(); - return; - - case Event::TogglePalette: - if (pressed && !repeated) myOSystem.console().togglePalette(); - return; - - case Event::ToggleInter: - if (pressed && !repeated) myOSystem.console().toggleInter(); - return; - - case Event::ToggleJitter: - if (pressed && !repeated) myOSystem.console().toggleJitter(); - return; + /////////////////////////////////////////////////////////////////////////// + // Debug events (with global hotkeys) case Event::ToggleFrameStats: - if (pressed) myOSystem.frameBuffer().toggleFrameStats(); - return; - - case Event::ToggleTimeMachine: - if (pressed && !repeated) myOSystem.state().toggleTimeMachine(); - return; - - #ifdef PNG_SUPPORT - case Event::ToggleContSnapshots: - if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(false); - return; - - case Event::ToggleContSnapshotsFrame: - if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(true); - return; - #endif - - case Event::HandleMouseControl: - if (pressed && !repeated) handleMouseControl(); - return; - - case Event::ToggleSAPortOrder: - if (pressed && !repeated) toggleSAPortOrder(); - return; - - case Event::FormatDecrease: - if (pressed) myOSystem.console().toggleFormat(-1); - return; - - case Event::FormatIncrease: - if (pressed) myOSystem.console().toggleFormat(1); - return; - - case Event::ToggleGrabMouse: - if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen()) + if (pressed && !repeated) { - bool oldState = myOSystem.frameBuffer().grabMouseEnabled(); - myOSystem.frameBuffer().toggleGrabMouse(); - bool newState = myOSystem.frameBuffer().grabMouseEnabled(); - myOSystem.frameBuffer().showMessage(oldState != newState ? myOSystem.frameBuffer().grabMouseEnabled() - ? "Grab mouse enabled" : "Grab mouse disabled" - : "Grab mouse not allowed while cursor shown"); + myOSystem.frameBuffer().toggleFrameStats(); + myAdjustSetting = AdjustSetting::STATS; + myAdjustActive = true; } return; case Event::ToggleP0Collision: - if (pressed && !repeated) myOSystem.console().toggleP0Collision(); + if (pressed && !repeated) + { + myOSystem.console().toggleP0Collision(); + myAdjustSetting = AdjustSetting::P0_CX; + myAdjustActive = true; + } return; case Event::ToggleP0Bit: - if (pressed && !repeated) myOSystem.console().toggleP0Bit(); + if (pressed && !repeated) + { + myOSystem.console().toggleP0Bit(); + myAdjustSetting = AdjustSetting::P0_ENAM; + myAdjustActive = true; + } return; case Event::ToggleP1Collision: - if (pressed && !repeated) myOSystem.console().toggleP1Collision(); + if (pressed && !repeated) + { + myOSystem.console().toggleP1Collision(); + myAdjustSetting = AdjustSetting::P1_CX; + myAdjustActive = true; + } return; case Event::ToggleP1Bit: - if (pressed && !repeated) myOSystem.console().toggleP1Bit(); + if (pressed && !repeated) + { + myOSystem.console().toggleP1Bit(); + myAdjustSetting = AdjustSetting::P1_ENAM; + myAdjustActive = true; + } return; case Event::ToggleM0Collision: - if (pressed && !repeated) myOSystem.console().toggleM0Collision(); + if (pressed && !repeated) + { + myOSystem.console().toggleM0Collision(); + myAdjustSetting = AdjustSetting::M0_CX; + myAdjustActive = true; + } return; case Event::ToggleM0Bit: - if (pressed && !repeated) myOSystem.console().toggleM0Bit(); + if (pressed && !repeated) + { + myOSystem.console().toggleM0Bit(); + myAdjustSetting = AdjustSetting::M0_ENAM; + myAdjustActive = true; + } return; case Event::ToggleM1Collision: - if (pressed && !repeated) myOSystem.console().toggleM1Collision(); + if (pressed && !repeated) + { + myOSystem.console().toggleM1Collision(); + myAdjustSetting = AdjustSetting::M1_CX; + myAdjustActive = true; + } return; case Event::ToggleM1Bit: - if (pressed && !repeated) myOSystem.console().toggleM1Bit(); + if (pressed && !repeated) + { + myOSystem.console().toggleM1Bit(); + myAdjustSetting = AdjustSetting::M1_ENAM; + myAdjustActive = true; + } return; case Event::ToggleBLCollision: - if (pressed && !repeated) myOSystem.console().toggleBLCollision(); + if (pressed && !repeated) + { + myOSystem.console().toggleBLCollision(); + myAdjustSetting = AdjustSetting::BL_CX; + myAdjustActive = true; + } return; case Event::ToggleBLBit: - if (pressed) myOSystem.console().toggleBLBit(); + if (pressed && !repeated) + { + myOSystem.console().toggleBLBit(); + myAdjustSetting = AdjustSetting::BL_ENAM; + myAdjustActive = true; + } return; case Event::TogglePFCollision: - if (pressed && !repeated) myOSystem.console().togglePFCollision(); + if (pressed && !repeated) + { + myOSystem.console().togglePFCollision(); + myAdjustSetting = AdjustSetting::PF_CX; + myAdjustActive = true; + } return; case Event::TogglePFBit: - if (pressed && !repeated) myOSystem.console().togglePFBit(); - return; - - case Event::ToggleFixedColors: - if (pressed) myOSystem.console().toggleFixedColors(); + if (pressed && !repeated) + { + myOSystem.console().togglePFBit(); + myAdjustSetting = AdjustSetting::PF_ENAM; + myAdjustActive = true; + } return; case Event::ToggleCollisions: - if (pressed && !repeated) myOSystem.console().toggleCollisions(); + if (pressed && !repeated) + { + myOSystem.console().toggleCollisions(); + myAdjustSetting = AdjustSetting::ALL_CX; + myAdjustActive = true; + } return; case Event::ToggleBits: - if (pressed && !repeated) myOSystem.console().toggleBits(); + if (pressed && !repeated) + { + myOSystem.console().toggleBits(); + myAdjustSetting = AdjustSetting::ALL_ENAM; + myAdjustActive = true; + } return; + case Event::ToggleFixedColors: + if (pressed && !repeated) + { + myOSystem.console().toggleFixedColors(); + myAdjustSetting = AdjustSetting::FIXED_COL; + myAdjustActive = true; + } + return; + + case Event::ToggleColorLoss: + if (pressed && !repeated) + { + myOSystem.console().toggleColorLoss(); + myAdjustSetting = AdjustSetting::COLOR_LOSS; + myAdjustActive = true; + } + return; + + case Event::ToggleJitter: + if (pressed && !repeated) + { + myOSystem.console().toggleJitter(); + myAdjustSetting = AdjustSetting::JITTER; + myAdjustActive = true; + } + return; + + /////////////////////////////////////////////////////////////////////////// + // State events + case Event::SaveState: - if(pressed && !repeated) myOSystem.state().saveState(); + if (pressed && !repeated) + { + myOSystem.state().saveState(); + myAdjustDirect = AdjustSetting::STATE; + } return; case Event::SaveAllStates: @@ -660,12 +1153,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) myOSystem.frameBuffer().showMessage(myOSystem.state().rewindManager().saveAllStates()); return; - case Event::NextState: - if(pressed) myOSystem.state().changeState(1); + case Event::PreviousState: + if (pressed) + { + myOSystem.state().changeState(-1); + myAdjustDirect = AdjustSetting::STATE; + } return; - case Event::PreviousState: - if (pressed) myOSystem.state().changeState(-1); + case Event::NextState: + if (pressed) + { + myOSystem.state().changeState(+1); + myAdjustDirect = AdjustSetting::STATE; + } return; case Event::ToggleAutoSlot: @@ -673,7 +1174,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; case Event::LoadState: - if(pressed && !repeated) myOSystem.state().loadState(); + if (pressed && !repeated) + { + myOSystem.state().loadState(); + myAdjustDirect = AdjustSetting::STATE; + } return; case Event::LoadAllStates: @@ -717,6 +1222,76 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed) enterTimeMachineMenuMode(1000, true); return; + /////////////////////////////////////////////////////////////////////////// + // Misc events + + case Event::DecreaseSpeed: + if(pressed) + { + myOSystem.console().changeSpeed(-1); + myAdjustDirect = AdjustSetting::CHANGE_SPEED; + } + return; + + case Event::IncreaseSpeed: + if(pressed) + { + myOSystem.console().changeSpeed(+1); + myAdjustDirect = AdjustSetting::CHANGE_SPEED; + } + return; + + case Event::ToggleTurbo: + if (pressed && !repeated) myOSystem.console().toggleTurbo(); + return; + + case Event::Fry: + if (!repeated) myFryingFlag = pressed; + return; + + case Event::ReloadConsole: + if (pressed && !repeated) myOSystem.reloadConsole(true); + return; + + case Event::PreviousMultiCartRom: + if (pressed && !repeated) myOSystem.reloadConsole(false); + return; + + case Event::ToggleTimeMachine: + if (pressed && !repeated) myOSystem.state().toggleTimeMachine(); + return; + + #ifdef PNG_SUPPORT + case Event::ToggleContSnapshots: + if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(false); + return; + + case Event::ToggleContSnapshotsFrame: + if (pressed && !repeated) myOSystem.png().toggleContinuousSnapshots(true); + return; + #endif + + case Event::DecreaseAutoFire: + if(pressed) myOSystem.console().changeAutoFireRate(-1); + return; + + case Event::IncreaseAutoFire: + if(pressed) myOSystem.console().changeAutoFireRate(+1); + return; + + case Event::HandleMouseControl: + if (pressed && !repeated) handleMouseControl(); + return; + + case Event::ToggleSAPortOrder: + if (pressed && !repeated) toggleSAPortOrder(); + return; + + case Event::ToggleGrabMouse: + if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen()) + myOSystem.frameBuffer().toggleGrabMouse(); + return; + case Event::TakeSnapshot: if(pressed && !repeated) myOSystem.frameBuffer().tiaSurface().saveSnapShot(); return; @@ -738,6 +1313,10 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (pressed && !repeated) changeStateByEvent(Event::TimeMachineMode); return; + case EventHandlerState::PLAYBACK: + if (pressed && !repeated) changeStateByEvent(Event::TogglePlayBackMode); + return; + // this event is called when exiting a ROM from the debugger, so it acts like pressing ESC in emulation case EventHandlerState::EMULATION: case EventHandlerState::DEBUGGER: @@ -749,7 +1328,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if (myOSystem.settings().getBool("confirmexit")) { StringList msg; - string saveOnExit = myOSystem.settings().getString("saveonexit"); + const string saveOnExit = myOSystem.settings().getString("saveonexit"); bool activeTM = myOSystem.settings().getBool( myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine"); @@ -829,7 +1408,6 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) if(myComboTable[combo][i] != Event::NoType) handleEvent(myComboTable[combo][i], pressed, repeated); return; - //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Events which relate to switches() @@ -954,6 +1532,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) myOSystem.console().switches().update(); } return; + //////////////////////////////////////////////////////////////////////// case Event::NoType: // Ignore unmapped events @@ -1011,7 +1590,7 @@ bool EventHandler::changeStateByEvent(Event::Type type) switch(type) { case Event::TogglePauseMode: - if(myState == EventHandlerState::EMULATION) + if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PLAYBACK) setState(EventHandlerState::PAUSE); else if(myState == EventHandlerState::PAUSE) setState(EventHandlerState::EMULATION); @@ -1021,7 +1600,7 @@ bool EventHandler::changeStateByEvent(Event::Type type) case Event::OptionsMenuMode: if (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE - || myState == EventHandlerState::TIMEMACHINE) + || myState == EventHandlerState::TIMEMACHINE || myState == EventHandlerState::PLAYBACK) enterMenuMode(EventHandlerState::OPTIONSMENU); else handled = false; @@ -1029,7 +1608,7 @@ bool EventHandler::changeStateByEvent(Event::Type type) case Event::CmdMenuMode: if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE - || myState == EventHandlerState::TIMEMACHINE) + || myState == EventHandlerState::TIMEMACHINE || myState == EventHandlerState::PLAYBACK) enterMenuMode(EventHandlerState::CMDMENU); else if(myState == EventHandlerState::CMDMENU && !myOSystem.settings().getBool("minimal_ui")) // The extra check for "minimal_ui" allows mapping e.g. right joystick fire @@ -1055,7 +1634,8 @@ bool EventHandler::changeStateByEvent(Event::Type type) break; case Event::TimeMachineMode: - if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE) + if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE + || myState == EventHandlerState::PLAYBACK) enterTimeMachineMenuMode(0, false); else if(myState == EventHandlerState::TIMEMACHINE) leaveMenuMode(); @@ -1063,10 +1643,24 @@ bool EventHandler::changeStateByEvent(Event::Type type) handled = false; break; + case Event::TogglePlayBackMode: + if (myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE + || myState == EventHandlerState::TIMEMACHINE) + enterPlayBackMode(); + else if (myState == EventHandlerState::PLAYBACK) + #ifdef GUI_SUPPORT + enterMenuMode(EventHandlerState::TIMEMACHINE); + #else + setState(EventHandlerState::PAUSE); + #endif + else + handled = false; + break; + case Event::DebuggerMode: #ifdef DEBUGGER_SUPPORT if(myState == EventHandlerState::EMULATION || myState == EventHandlerState::PAUSE - || myState == EventHandlerState::TIMEMACHINE) + || myState == EventHandlerState::TIMEMACHINE || myState == EventHandlerState::PLAYBACK) enterDebugMode(); else if(myState == EventHandlerState::DEBUGGER && myOSystem.debugger().canExit()) leaveDebugMode(); @@ -1091,12 +1685,12 @@ void EventHandler::setActionMappings(EventMode mode) // Fill the EmulActionList with the current key and joystick mappings for(auto& item: ourEmulActionList) { - Event::Type event = item.event; + const Event::Type event = item.event; item.key = "None"; string key = myPKeyHandler->getMappingDesc(event, mode); #ifdef JOYSTICK_SUPPORT - string joydesc = myPJoyHandler->getMappingDesc(event, mode); + const string joydesc = myPJoyHandler->getMappingDesc(event, mode); if(joydesc != "") { if(key != "") @@ -1113,12 +1707,12 @@ void EventHandler::setActionMappings(EventMode mode) // Fill the MenuActionList with the current key and joystick mappings for(auto& item: ourMenuActionList) { - Event::Type event = item.event; + const Event::Type event = item.event; item.key = "None"; string key = myPKeyHandler->getMappingDesc(event, mode); #ifdef JOYSTICK_SUPPORT - string joydesc = myPJoyHandler->getMappingDesc(event, mode); + const string joydesc = myPJoyHandler->getMappingDesc(event, mode); if(joydesc != "") { if(key != "") @@ -1144,7 +1738,7 @@ void EventHandler::setComboMap() string list = myOSystem.settings().getString("combomap"); replace(list.begin(), list.end(), ':', ' '); istringstream buf(list); - Int32 version = myOSystem.settings().getInt("event_ver"); + const Int32 version = myOSystem.settings().getInt("event_ver"); // Erase the 'combo' array auto ERASE_ALL = [&]() { @@ -1206,7 +1800,7 @@ void EventHandler::removePhysicalJoystickFromDatabase(const string& name) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod) { - bool mapped = myPKeyHandler->addMapping(event, mode, key, mod); + const bool mapped = myPKeyHandler->addMapping(event, mode, key, mod); if(mapped) setActionMappings(mode); @@ -1219,7 +1813,7 @@ bool EventHandler::addJoyMapping(Event::Type event, EventMode mode, bool updateMenus) { #ifdef JOYSTICK_SUPPORT - bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir); + const bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir); if (mapped && updateMenus) setActionMappings(mode); @@ -1417,7 +2011,7 @@ VariantList EventHandler::getComboList(EventMode /**/) const VarList::push_back(l, "None", "-1"); for(uInt32 i = 0; i < ourEmulActionList.size(); ++i) { - Event::Type event = EventHandler::ourEmulActionList[i].event; + const Event::Type event = EventHandler::ourEmulActionList[i].event; // exclude combos events if(!(event >= Event::Combo1 && event <= Event::Combo16)) { @@ -1439,7 +2033,7 @@ StringList EventHandler::getComboListForEvent(Event::Type event) const int combo = event - Event::Combo1; for(uInt32 i = 0; i < EVENTS_PER_COMBO; ++i) { - Event::Type e = myComboTable[combo][i]; + const Event::Type e = myComboTable[combo][i]; for(uInt32 j = 0; j < ourEmulActionList.size(); ++j) { if(EventHandler::ourEmulActionList[j].event == e) @@ -1463,7 +2057,7 @@ void EventHandler::setComboListForEvent(Event::Type event, const StringList& eve if(event >= Event::Combo1 && event <= Event::Combo16) { assert(events.size() == 8); - int combo = event - Event::Combo1; + const int combo = event - Event::Combo1; for(uInt32 i = 0; i < 8; ++i) { uInt32 idx = BSPF::stringToInt(events[i]); @@ -1550,7 +2144,7 @@ int EventHandler::getActionListIndex(int idx, Event::Group group) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const { - int index = getActionListIndex(idx, group); + const int index = getActionListIndex(idx, group); if(group == Event::Group::Menu) { @@ -1571,7 +2165,7 @@ Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string EventHandler::actionAtIndex(int idx, Event::Group group) const { - int index = getActionListIndex(idx, group); + const int index = getActionListIndex(idx, group); if(group == Event::Group::Menu) { @@ -1592,7 +2186,7 @@ string EventHandler::actionAtIndex(int idx, Event::Group group) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string EventHandler::keyAtIndex(int idx, Event::Group group) const { - int index = getActionListIndex(idx, group); + const int index = getActionListIndex(idx, group); if(group == Event::Group::Menu) { @@ -1720,6 +2314,15 @@ void EventHandler::enterTimeMachineMenuMode(uInt32 numWinds, bool unwind) #endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EventHandler::enterPlayBackMode() +{ +#ifdef GUI_SUPPORT + setState(EventHandlerState::PLAYBACK); + myOSystem.sound().mute(true); // sound does not work in playback mode +#endif +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::setState(EventHandlerState state) { @@ -1735,6 +2338,7 @@ void EventHandler::setState(EventHandlerState state) switch(myState) { case EventHandlerState::EMULATION: + case EventHandlerState::PLAYBACK: myOSystem.sound().mute(false); enableTextEvents(false); break; @@ -1808,8 +2412,8 @@ void EventHandler::setState(EventHandlerState state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void EventHandler::exitEmulation(bool checkLauncher) { - string saveOnExit = myOSystem.settings().getString("saveonexit"); - bool activeTM = myOSystem.settings().getBool( + const string saveOnExit = myOSystem.settings().getString("saveonexit"); + const bool activeTM = myOSystem.settings().getBool( myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine"); @@ -1833,6 +2437,7 @@ void EventHandler::exitEmulation(bool checkLauncher) EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::Quit, "Quit", "" }, { Event::ReloadConsole, "Reload current ROM/load next game", "" }, + { Event::PreviousMultiCartRom, "Load previous multicart game", "" }, { Event::ExitMode, "Exit current Stella menu/mode", "" }, { Event::OptionsMenuMode, "Enter Options menu UI", "" }, { Event::CmdMenuMode, "Toggle Commands menu UI", "" }, @@ -1840,6 +2445,9 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::TogglePauseMode, "Toggle Pause mode", "" }, { Event::StartPauseMode, "Start Pause mode", "" }, { Event::Fry, "Fry cartridge", "" }, + { Event::DecreaseSpeed, "Decrease emulation speed", "" }, + { Event::IncreaseSpeed, "Increase emulation speed", "" }, + { Event::ToggleTurbo, "Toggle 'Turbo' mode", "" }, { Event::DebuggerMode, "Toggle Debugger mode", "" }, { Event::ConsoleSelect, "Select", "" }, @@ -1931,35 +2539,54 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::KeyboardOnePound, "P1 Keyboard #", "" }, // Video { Event::ToggleFullScreen, "Toggle fullscreen", "" }, +#ifdef ADAPTABLE_REFRESH_SUPPORT + { Event::ToggleAdaptRefresh, "Toggle fullscreen refresh rate adapt", "" }, +#endif { Event::OverscanDecrease, "Decrease overscan in fullscreen mode", "" }, { Event::OverscanIncrease, "Increase overscan in fullscreen mode", "" }, { Event::VidmodeDecrease, "Previous zoom level", "" }, { Event::VidmodeIncrease, "Next zoom level", "" }, - { Event::ScanlineAdjustIncrease, "Increase vertical display size", "" }, - { Event::ScanlineAdjustDecrease, "Decrease vertical display size", "" }, + { Event::VSizeAdjustDecrease, "Decrease vertical display size", "" }, + { Event::VSizeAdjustIncrease, "Increase vertical display size", "" }, { Event::VCenterDecrease, "Move display up", "" }, { Event::VCenterIncrease, "Move display down", "" }, { Event::FormatDecrease, "Decrease display format", "" }, { Event::FormatIncrease, "Increase display format", "" }, - { Event::TogglePalette, "Switch palette (Standard/Z26/User)", "" }, + // Palette settings + { Event::PaletteDecrease, "Switch to previous palette", "" }, + { Event::PaletteIncrease, "Switch to next palette", "" }, + { Event::PreviousPaletteAttribute,"Select previous palette attribute", "" }, + { Event::NextPaletteAttribute, "Select next palette attribute", "" }, + { Event::PaletteAttributeDecrease,"Decrease selected palette attribute", "" }, + { Event::PaletteAttributeIncrease,"Increase selected palette attribute", "" }, { Event::ToggleInter, "Toggle display interpolation", "" }, - - // TV effects: + // Blargg TV effects: { Event::VidmodeStd, "Disable TV effects", "" }, { Event::VidmodeRGB, "Select 'RGB' preset", "" }, { Event::VidmodeSVideo, "Select 'S-Video' preset", "" }, { Event::VidModeComposite, "Select 'Composite' preset", "" }, { Event::VidModeBad, "Select 'Badly adjusted' preset", "" }, { Event::VidModeCustom, "Select 'Custom' preset", "" }, + { Event::PreviousVideoMode, "Select previous TV effect mode preset", "" }, + { Event::NextVideoMode, "Select next TV effect mode preset", "" }, { Event::PreviousAttribute, "Select previous 'Custom' attribute", "" }, { Event::NextAttribute, "Select next 'Custom' attribute", "" }, { Event::DecreaseAttribute, "Decrease selected 'Custom' attribute", "" }, { Event::IncreaseAttribute, "Increase selected 'Custom' attribute", "" }, + // Other TV effects { Event::TogglePhosphor, "Toggle 'phosphor' effect", "" }, { Event::PhosphorDecrease, "Decrease 'phosphor' blend", "" }, { Event::PhosphorIncrease, "Increase 'phosphor' blend", "" }, { Event::ScanlinesDecrease, "Decrease scanlines", "" }, { Event::ScanlinesIncrease, "Increase scanlines", "" }, + + { Event::PreviousSettingGroup, "Select previous setting group", "" }, + { Event::NextSettingGroup, "Select next setting group", "" }, + { Event::PreviousSetting, "Select previous setting", "" }, + { Event::NextSetting, "Select next setting", "" }, + { Event::SettingDecrease, "Decrease current setting", "" }, + { Event::SettingIncrease, "Increase current setting", "" }, + // Developer keys: { Event::ToggleFrameStats, "Toggle frame stats", "" }, { Event::ToggleP0Bit, "Toggle TIA Player0 object", "" }, @@ -1984,6 +2611,8 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::VolumeDecrease, "Decrease volume", "" }, { Event::VolumeIncrease, "Increase volume", "" }, + { Event::DecreaseAutoFire, "Decrease auto fire speed", "" }, + { Event::IncreaseAutoFire, "Increase auto fire speed", "" }, { Event::HandleMouseControl, "Switch mouse emulation modes", "" }, { Event::ToggleGrabMouse, "Toggle grab mouse", "" }, { Event::ToggleSAPortOrder, "Swap Stelladaptor port ordering", "" }, @@ -1998,6 +2627,7 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::Unwind1Menu, "Unwind one state & enter TM UI", "" }, { Event::Unwind10Menu, "Unwind 10 states & enter TM UI", "" }, { Event::UnwindAllMenu, "Unwind all states & enter TM UI", "" }, + { Event::TogglePlayBackMode, "Toggle 'Time Machine' playback mode", "" }, { Event::Combo1, "Combo 1", "" }, { Event::Combo2, "Combo 2", "" }, @@ -2048,28 +2678,37 @@ EventHandler::MenuActionList EventHandler::ourMenuActionList = { { const Event::EventSet EventHandler::MiscEvents = { Event::Quit, Event::ReloadConsole, Event::Fry, Event::StartPauseMode, Event::TogglePauseMode, Event::OptionsMenuMode, Event::CmdMenuMode, Event::ExitMode, + Event::ToggleTurbo, Event::DecreaseSpeed, Event::IncreaseSpeed, Event::TakeSnapshot, Event::ToggleContSnapshots, Event::ToggleContSnapshotsFrame, // Event::MouseAxisXMove, Event::MouseAxisYMove, // Event::MouseButtonLeftValue, Event::MouseButtonRightValue, + Event::DecreaseAutoFire, Event::IncreaseAutoFire, Event::HandleMouseControl, Event::ToggleGrabMouse, - Event::ToggleSAPortOrder, - Event::HighScoresMenuMode + Event::HighScoresMenuMode, + Event::ToggleSAPortOrder, Event::PreviousMultiCartRom, + Event::PreviousSettingGroup, Event::NextSettingGroup, + Event::PreviousSetting, Event::NextSetting, + Event::SettingDecrease, Event::SettingIncrease, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const Event::EventSet EventHandler::AudioVideoEvents = { Event::VolumeDecrease, Event::VolumeIncrease, Event::SoundToggle, Event::VidmodeDecrease, Event::VidmodeIncrease, - Event::ToggleFullScreen, - Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom, - Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute, - Event::ScanlinesDecrease, Event::ScanlinesIncrease, - Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor, + Event::ToggleFullScreen, Event::ToggleAdaptRefresh, + Event::OverscanDecrease, Event::OverscanIncrease, Event::FormatDecrease, Event::FormatIncrease, Event::VCenterDecrease, Event::VCenterIncrease, - Event::ScanlineAdjustDecrease, Event::ScanlineAdjustIncrease, - Event::OverscanDecrease, Event::OverscanIncrease, - Event::TogglePalette, Event::ToggleInter + Event::VSizeAdjustDecrease, Event::VSizeAdjustIncrease, + Event::PaletteDecrease, Event::PaletteIncrease, + Event::PreviousPaletteAttribute, Event::NextPaletteAttribute, + Event::PaletteAttributeDecrease, Event::PaletteAttributeIncrease, + Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom, + Event::PreviousVideoMode, Event::NextVideoMode, + Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute, + Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor, + Event::ScanlinesDecrease, Event::ScanlinesIncrease, + Event::ToggleInter, }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2078,6 +2717,7 @@ const Event::EventSet EventHandler::StateEvents = { Event::TimeMachineMode, Event::RewindPause, Event::UnwindPause, Event::ToggleTimeMachine, Event::Rewind1Menu, Event::Rewind10Menu, Event::RewindAllMenu, Event::Unwind1Menu, Event::Unwind10Menu, Event::UnwindAllMenu, + Event::TogglePlayBackMode, Event::SaveAllStates, Event::LoadAllStates, Event::ToggleAutoSlot, }; diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 929e99f8c..a7c1d2e07 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -25,6 +25,7 @@ class OSystem; class MouseControl; class DialogContainer; class PhysicalJoystick; +class Variant; namespace GUI { class Font; @@ -36,7 +37,6 @@ namespace GUI { #include "StellaKeys.hxx" #include "PKeyboardHandler.hxx" #include "PJoystickHandler.hxx" -#include "Variant.hxx" #include "bspf.hxx" /** @@ -136,6 +136,7 @@ class EventHandler bool enterDebugMode(); void leaveDebugMode(); void enterTimeMachineMenuMode(uInt32 numWinds, bool unwind); + void enterPlayBackMode(); /** Send an event directly to the event handler. @@ -391,6 +392,78 @@ class EventHandler */ void removePhysicalJoystick(int index); + private: + enum class AdjustSetting + { + NONE = -1, + // *** Audio & Video group *** + VOLUME, + ZOOM, + FULLSCREEN, + #ifdef ADAPTABLE_REFRESH_SUPPORT + ADAPT_REFRESH, + #endif + OVERSCAN, + TVFORMAT, + VCENTER, + VSIZE, + // Palette adjustables + PALETTE, + PALETTE_PHASE, + PALETTE_HUE, + PALETTE_SATURATION, + PALETTE_CONTRAST, + PALETTE_BRIGHTNESS, + PALETTE_GAMMA, + // NTSC filter adjustables + NTSC_PRESET, + NTSC_SHARPNESS, + NTSC_RESOLUTION, + NTSC_ARTIFACTS, + NTSC_FRINGING, + NTSC_BLEEDING, + // Other TV effects adjustables + PHOSPHOR, + SCANLINES, + INTERPOLATION, + // *** Debug group *** + STATS, + P0_ENAM, + P1_ENAM, + M0_ENAM, + M1_ENAM, + BL_ENAM, + PF_ENAM, + ALL_ENAM, + P0_CX, + P1_CX, + M0_CX, + M1_CX, + BL_CX, + PF_CX, + ALL_CX, + FIXED_COL, + COLOR_LOSS, + JITTER, + // *** Only used via direct hotkeys *** + STATE, + PALETTE_CHANGE_ATTRIBUTE, + NTSC_CHANGE_ATTRIBUTE, + CHANGE_SPEED, + // *** Ranges *** + NUM_ADJ, + START_AV_ADJ = VOLUME, + END_AV_ADJ = INTERPOLATION, + START_DEBUG_ADJ = STATS, + END_DEBUG_ADJ = JITTER, + }; + enum class AdjustGroup + { + AV, + DEBUG, + NUM_GROUPS + }; + private: // Define event groups static const Event::EventSet MiscEvents; @@ -417,6 +490,12 @@ class EventHandler int getEmulActionListIndex(int idx, const Event::EventSet& events) const; int getActionListIndex(int idx, Event::Group group) const; + // The following two methods are used for adjusting several settings using global hotkeys + // They return the function used to adjust the currenly selected setting + AdjustGroup getAdjustGroup(); + AdjustFunction cycleAdjustSetting(int direction); + AdjustFunction getAdjustSetting(AdjustSetting setting); + private: // Structure used for action menu items struct ActionList { @@ -425,6 +504,13 @@ class EventHandler string key; }; + // If true, the setting is visible and its value can be changed + bool myAdjustActive{false}; + // ID of the currently selected global setting + AdjustSetting myAdjustSetting{AdjustSetting::START_AV_ADJ}; + // ID of the currently selected direct hotkey setting (0 if none) + AdjustSetting myAdjustDirect{AdjustSetting::NONE}; + // Global Event object Event myEvent; @@ -468,7 +554,12 @@ class EventHandler #else PNG_SIZE = 0, #endif - EMUL_ACTIONLIST_SIZE = 144 + 3 + PNG_SIZE + COMBO_SIZE, + #ifdef ADAPTABLE_REFRESH_SUPPORT + REFRESH_SIZE = 1, + #else + REFRESH_SIZE = 0, + #endif + EMUL_ACTIONLIST_SIZE = 165 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE, MENU_ACTIONLIST_SIZE = 18 ; diff --git a/src/emucore/EventHandlerConstants.hxx b/src/emucore/EventHandlerConstants.hxx index 5ffe73f6c..79a473c2d 100644 --- a/src/emucore/EventHandlerConstants.hxx +++ b/src/emucore/EventHandlerConstants.hxx @@ -22,6 +22,7 @@ enum class EventHandlerState { EMULATION, TIMEMACHINE, + PLAYBACK, PAUSE, LAUNCHER, OPTIONSMENU, @@ -83,7 +84,8 @@ enum class EventMode { kPaddlesMode, kKeypadMode, kCompuMateMode, // cannot be remapped - kCommonMode // mapping common between controllers + kCommonMode, // mapping common between controllers + kNumModes }; namespace GUI diff --git a/src/emucore/FSNode.cxx b/src/emucore/FSNode.cxx index 6965839ef..f2e5e477a 100644 --- a/src/emucore/FSNode.cxx +++ b/src/emucore/FSNode.cxx @@ -13,9 +13,6 @@ // // See the file "License.txt" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// Based on code from ScummVM - Scumm Interpreter -// Copyright (C) 2002-2004 The ScummVM project //============================================================================ #include "FSNodeFactory.hxx" @@ -28,15 +25,49 @@ FilesystemNode::FilesystemNode(const AbstractFSNodePtr& realNode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FilesystemNode::FilesystemNode(const string& p) +FilesystemNode::FilesystemNode(const string& path) { + setPath(path); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FilesystemNode::setPath(const string& path) +{ + // Only create a new object when necessary + if (path == getPath()) + return; + // Is this potentially a ZIP archive? #if defined(ZIP_SUPPORT) - if (BSPF::containsIgnoreCase(p, ".zip")) - _realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::Type::ZIP); + if (BSPF::containsIgnoreCase(path, ".zip")) + _realNode = FilesystemNodeFactory::create(path, FilesystemNodeFactory::Type::ZIP); else #endif - _realNode = FilesystemNodeFactory::create(p, FilesystemNodeFactory::Type::SYSTEM); + _realNode = FilesystemNodeFactory::create(path, FilesystemNodeFactory::Type::SYSTEM); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FilesystemNode& FilesystemNode::operator/=(const string& path) +{ + // This part could probably be put in a virtual function, but it seems like + // a waste since almost every system uses the same separator, except Windows +#ifdef BSPF_WINDOWS + #define PATH_SEPARATOR '\\' +#else + #define PATH_SEPARATOR '/' +#endif + + if (path != EmptyString) + { + string newPath = getPath(); + if (newPath != EmptyString && newPath[newPath.length()-1] != PATH_SEPARATOR) + newPath += PATH_SEPARATOR; + newPath += path; + setPath(newPath); + } + + return *this; +#undef PATH_SEPARATOR } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -47,7 +78,8 @@ bool FilesystemNode::exists() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FilesystemNode::getChildren(FSList& fslist, ListMode mode, - const NameFilter& filter) const + const NameFilter& filter, + bool includeParentDirectory) const { if (!_realNode || !_realNode->isDirectory()) return false; @@ -58,6 +90,20 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode, if (!_realNode->getChildren(tmp, mode)) return false; + #if defined(ZIP_SUPPORT) + // before sorting, replace single file ZIP archive names with contained file names + // because they are displayed using their contained file names + for (auto& i : tmp) + { + if (BSPF::endsWithIgnoreCase(i->getPath(), ".zip")) + { + FilesystemNodeZIP node(i->getPath()); + + i->setName(node.getName()); + } + } + #endif + std::sort(tmp.begin(), tmp.end(), [](const AbstractFSNodePtr& node1, const AbstractFSNodePtr& node2) { @@ -69,7 +115,7 @@ bool FilesystemNode::getChildren(FSList& fslist, ListMode mode, ); // Add parent node, if it is valid to do so - if (hasParent()) + if (includeParentDirectory && hasParent()) { FilesystemNode parent = getParent(); parent.setName(" [..]"); @@ -209,35 +255,117 @@ bool FilesystemNode::rename(const string& newfile) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t FilesystemNode::read(ByteBuffer& image) const +size_t FilesystemNode::read(ByteBuffer& buffer) const { - size_t size = 0; + size_t sizeRead = 0; // File must actually exist if (!(exists() && isReadable())) throw runtime_error("File not found/readable"); // First let the private subclass attempt to open the file - if (_realNode && (size = _realNode->read(image)) > 0) - return size; + if (_realNode && (sizeRead = _realNode->read(buffer)) > 0) + return sizeRead; // Otherwise, the default behaviour is to read from a normal C++ ifstream - image = make_unique(512 * 1024); - ifstream in(getPath(), std::ios::binary); + std::ifstream in(getPath(), std::ios::binary); if (in) { in.seekg(0, std::ios::end); - std::streampos length = in.tellg(); + sizeRead = static_cast(in.tellg()); in.seekg(0, std::ios::beg); - if (length == 0) + if (sizeRead == 0) throw runtime_error("Zero-byte file"); - size = std::min(length, 512 * 1024); - in.read(reinterpret_cast(image.get()), size); + buffer = make_unique(sizeRead); + in.read(reinterpret_cast(buffer.get()), sizeRead); } else throw runtime_error("File open/read error"); - return size; + return sizeRead; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNode::read(stringstream& buffer) const +{ + size_t sizeRead = 0; + + // File must actually exist + if (!(exists() && isReadable())) + throw runtime_error("File not found/readable"); + + // First let the private subclass attempt to open the file + if (_realNode && (sizeRead = _realNode->read(buffer)) > 0) + return sizeRead; + + // Otherwise, the default behaviour is to read from a normal C++ ifstream + // and convert to a stringstream + std::ifstream in(getPath()); + if (in) + { + in.seekg(0, std::ios::end); + sizeRead = static_cast(in.tellg()); + in.seekg(0, std::ios::beg); + + if (sizeRead == 0) + throw runtime_error("Zero-byte file"); + + buffer << in.rdbuf(); + } + else + throw runtime_error("File open/read error"); + + return sizeRead; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNode::write(const ByteBuffer& buffer, size_t size) const +{ + size_t sizeWritten = 0; + + // First let the private subclass attempt to open the file + if (_realNode && (sizeWritten = _realNode->write(buffer, size)) > 0) + return sizeWritten; + + // Otherwise, the default behaviour is to write to a normal C++ ofstream + std::ofstream out(getPath(), std::ios::binary); + if (out) + { + out.write(reinterpret_cast(buffer.get()), size); + + out.seekp(0, std::ios::end); + sizeWritten = static_cast(out.tellp()); + out.seekp(0, std::ios::beg); + } + else + throw runtime_error("File open/write error"); + + return sizeWritten; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +size_t FilesystemNode::write(const stringstream& buffer) const +{ + size_t sizeWritten = 0; + + // First let the private subclass attempt to open the file + if (_realNode && (sizeWritten = _realNode->write(buffer)) > 0) + return sizeWritten; + + // Otherwise, the default behaviour is to write to a normal C++ ofstream + std::ofstream out(getPath()); + if (out) + { + out << buffer.rdbuf(); + + out.seekp(0, std::ios::end); + sizeWritten = static_cast(out.tellp()); + out.seekp(0, std::ios::beg); + } + else + throw runtime_error("File open/write error"); + + return sizeWritten; } diff --git a/src/emucore/FSNode.hxx b/src/emucore/FSNode.hxx index 2a8acc278..cf76f9ac1 100644 --- a/src/emucore/FSNode.hxx +++ b/src/emucore/FSNode.hxx @@ -13,42 +13,24 @@ // // See the file "License.txt" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// Based on code from ScummVM - Scumm Interpreter -// Copyright (C) 2002-2004 The ScummVM project //============================================================================ #ifndef FS_NODE_HXX #define FS_NODE_HXX +#include + #include "bspf.hxx" /* * The API described in this header is meant to allow for file system browsing in a - * portable fashions. To this ends, multiple or single roots have to be supported + * portable fashion. To this end, multiple or single roots have to be supported * (compare Unix with a single root, Windows with multiple roots C:, D:, ...). * * To this end, we abstract away from paths; implementations can be based on - * paths (and it's left to them whether / or \ or : is the path separator :-); - * but it is also possible to use inodes or vrefs (MacOS 9) or anything else. - * - * You may ask now: "isn't this cheating? Why do we go through all this when we use - * a path in the end anyway?!?". - * Well, for once as long as we don't provide our own file open/read/write API, we - * still have to use fopen(). Since all our targets already support fopen(), it should - * be possible to get a fopen() compatible string for any file system node. - * - * Secondly, with this abstraction layer, we still avoid a lot of complications based on - * differences in FS roots, different path separators, or even systems with no real - * paths (MacOS 9 doesn't even have the notion of a "current directory"). - * And if we ever want to support devices with no FS in the classical sense (Palm...), - * we can build upon this. + * paths (and it's left to them whether / or \ or : is the path separator :-). */ -#include - -#include "bspf.hxx" - class FilesystemNode; class AbstractFSNode; using AbstractFSNodePtr = shared_ptr; @@ -102,13 +84,19 @@ class FilesystemNode /** * Compare the name of this node to the name of another, testing for - * equality, + * equality. */ inline bool operator==(const FilesystemNode& node) const { return BSPF::compareIgnoreCase(getName(), node.getName()) == 0; } + /** + * Append the given path to the node, adding a directory separator + * when necessary. Modelled on the C++17 fs::path API. + */ + FilesystemNode& operator/=(const string& path); + /** * By default, the output operator simply outputs the fully-qualified * pathname of the node. @@ -134,7 +122,8 @@ class FilesystemNode * does not exist). */ bool getChildren(FSList& fslist, ListMode mode = ListMode::DirectoriesOnly, - const NameFilter& filter = [](const FilesystemNode&){ return true; }) const; + const NameFilter& filter = [](const FilesystemNode&){ return true; }, + bool includeParentDirectory = true) const; /** * Set/get a string representation of the name of the file. This is can be @@ -232,7 +221,7 @@ class FilesystemNode /** * Read data (binary format) into the given buffer. * - * @param buffer The buffer to contain the data. + * @param buffer The buffer to contain the data (allocated in this method). * * @return The number of bytes read (0 in the case of failure) * This method can throw exceptions, and should be used inside @@ -240,6 +229,40 @@ class FilesystemNode */ size_t read(ByteBuffer& buffer) const; + /** + * Read data (text format) into the given stream. + * + * @param buffer The buffer stream to contain the data. + * + * @return The number of bytes read (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + size_t read(stringstream& buffer) const; + + /** + * Write data (binary format) from the given buffer. + * + * @param buffer The buffer that contains the data. + * @param size The size of the buffer. + * + * @return The number of bytes written (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + size_t write(const ByteBuffer& buffer, size_t size) const; + + /** + * Write data (text format) from the given stream. + * + * @param buffer The buffer stream that contains the data. + * + * @return The number of bytes written (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + size_t write(const stringstream& buffer) const; + /** * The following methods are almost exactly the same as the various * getXXXX() methods above. Internally, they call the respective methods @@ -252,6 +275,7 @@ class FilesystemNode private: AbstractFSNodePtr _realNode; explicit FilesystemNode(const AbstractFSNodePtr& realNode); + void setPath(const string& path); }; @@ -391,14 +415,47 @@ class AbstractFSNode /** * Read data (binary format) into the given buffer. * - * @param buffer The buffer to containing the data - * This will be allocated by the method, and must be - * freed by the caller. + * @param buffer The buffer to contain the data (allocated in this method). + * * @return The number of bytes read (0 in the case of failure) * This method can throw exceptions, and should be used inside * a try-catch block. */ virtual size_t read(ByteBuffer& buffer) const { return 0; } + + /** + * Read data (text format) into the given stream. + * + * @param buffer The buffer stream to contain the data. + * + * @return The number of bytes read (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + virtual size_t read(stringstream& buffer) const { return 0; } + + /** + * Write data (binary format) from the given buffer. + * + * @param buffer The buffer that contains the data. + * @param size The size of the buffer. + * + * @return The number of bytes written (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + virtual size_t write(const ByteBuffer& buffer, size_t size) const { return 0; } + + /** + * Write data (text format) from the given stream. + * + * @param buffer The buffer stream that contains the data. + * + * @return The number of bytes written (0 in the case of failure) + * This method can throw exceptions, and should be used inside + * a try-catch block. + */ + virtual size_t write(const stringstream& buffer) const { return 0; } }; #endif diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 62ef5362f..399e01f15 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -29,6 +29,8 @@ #include "FBSurface.hxx" #include "TIASurface.hxx" #include "FrameBuffer.hxx" +#include "StateManager.hxx" +#include "RewindManager.hxx" #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" @@ -36,9 +38,15 @@ #ifdef GUI_SUPPORT #include "Font.hxx" #include "StellaFont.hxx" + #include "ConsoleMediumFont.hxx" + #include "ConsoleMediumBFont.hxx" #include "StellaMediumFont.hxx" #include "StellaLargeFont.hxx" + #include "Stella12x24tFont.hxx" + #include "Stella14x28tFont.hxx" + #include "Stella16x32tFont.hxx" #include "ConsoleFont.hxx" + #include "ConsoleBFont.hxx" #include "Launcher.hxx" #include "Menu.hxx" #include "CommandMenu.hxx" @@ -93,41 +101,7 @@ bool FrameBuffer::initialize() } #ifdef GUI_SUPPORT - //////////////////////////////////////////////////////////////////// - // Create fonts to draw text - // NOTE: the logic determining appropriate font sizes is done here, - // so that the UI classes can just use the font they expect, - // and not worry about it - // This logic should also take into account the size of the - // framebuffer, and try to be intelligent about font sizes - // We can probably add ifdefs to take care of corner cases, - // but that means we've failed to abstract it enough ... - //////////////////////////////////////////////////////////////////// - - // This font is used in a variety of situations when a really small - // font is needed; we let the specific widget/dialog decide when to - // use it - mySmallFont = make_unique(GUI::stellaDesc); - - // The general font used in all UI elements - // This is determined by the size of the framebuffer - if(myOSystem.settings().getBool("minimal_ui")) - myFont = make_unique(GUI::stellaLargeDesc); - else - myFont = make_unique(GUI::stellaMediumDesc); - - // The info font used in all UI elements - // This is determined by the size of the framebuffer - myInfoFont = make_unique(GUI::consoleDesc); - - // The font used by the ROM launcher - const string& lf = myOSystem.settings().getString("launcherfont"); - if(lf == "small") - myLauncherFont = make_unique(GUI::consoleDesc); - else if(lf == "medium") - myLauncherFont = make_unique(GUI::stellaMediumDesc); - else - myLauncherFont = make_unique(GUI::stellaLargeDesc); + setupFonts(); #endif // Determine possible TIA windowed zoom levels @@ -145,11 +119,100 @@ bool FrameBuffer::initialize() return true; } +#ifdef GUI_SUPPORT // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FBInitStatus FrameBuffer::createDisplay(const string& title, +void FrameBuffer::setupFonts() +{ + //////////////////////////////////////////////////////////////////// + // Create fonts to draw text + // NOTE: the logic determining appropriate font sizes is done here, + // so that the UI classes can just use the font they expect, + // and not worry about it + // This logic should also take into account the size of the + // framebuffer, and try to be intelligent about font sizes + // We can probably add ifdefs to take care of corner cases, + // but that means we've failed to abstract it enough ... + //////////////////////////////////////////////////////////////////// + + // This font is used in a variety of situations when a really small + // font is needed; we let the specific widget/dialog decide when to + // use it + mySmallFont = make_unique(GUI::stellaDesc); // 6x10 + + if(myOSystem.settings().getBool("minimal_ui")) + { + // The general font used in all UI elements + myFont = make_unique(GUI::stella12x24tDesc); // 12x24 + // The info font used in all UI elements + myInfoFont = make_unique(GUI::stellaLargeDesc); // 10x20 + } + else + { + const int NUM_FONTS = 7; + FontDesc FONT_DESC[NUM_FONTS] = {GUI::consoleDesc, GUI::consoleMediumDesc, GUI::stellaMediumDesc, + GUI::stellaLargeDesc, GUI::stella12x24tDesc, GUI::stella14x28tDesc, GUI::stella16x32tDesc}; + const string& dialogFont = myOSystem.settings().getString("dialogfont"); + FontDesc fd = getFontDesc(dialogFont); + + // The general font used in all UI elements + myFont = make_unique(fd); // default: 9x18 + // The info font used in all UI elements, + // automatically determined aiming for 1 / 1.4 (~= 18 / 13) size + int fontIdx = 0; + for(int i = 0; i < NUM_FONTS; ++i) + { + if(fd.height <= FONT_DESC[i].height * 1.4) + { + fontIdx = i; + break; + } + } + myInfoFont = make_unique(FONT_DESC[fontIdx]); // default 8x13 + + // Determine minimal zoom level based on the default font + // So what fits with default font should fit for any font. + // However, we have to make sure all Dialogs are sized using the fontsize. + int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height; + int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth; + myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F); // round to 25% steps, >= 200% + } + + // The font used by the ROM launcher + const string& lf = myOSystem.settings().getString("launcherfont"); + + + myLauncherFont = make_unique(getFontDesc(lf)); // 8x13 +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FontDesc FrameBuffer::getFontDesc(const string& name) const +{ + if(name == "small") + return GUI::consoleBDesc; // 8x13 + else if(name == "low_medium") + return GUI::consoleMediumBDesc; // 9x15 + else if(name == "medium") + return GUI::stellaMediumDesc; // 9x18 + else if(name == "large" || name == "large10") + return GUI::stellaLargeDesc; // 10x20 + else if(name == "large12") + return GUI::stella12x24tDesc; // 12x24 + else if(name == "large14") + return GUI::stella14x28tDesc; // 14x28 + else // "large16" + return GUI::stella16x32tDesc; // 16x32 +} +#endif + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type, uInt32 width, uInt32 height, bool honourHiDPI) { + // always save, maybe only the mode of the window has changed + saveCurrentWindowPosition(); + myBufferType = type; + ++myInitializedCount; myScreenTitle = title; @@ -249,7 +312,12 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, } if(!myMsg.surface) - myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight()+10); + { + const int fontWidth = font().getMaxCharWidth(), + HBORDER = fontWidth * 1.25 / 2.0; + myMsg.surface = allocateSurface(fontWidth * MESSAGE_WIDTH + HBORDER * 2, + font().getFontHeight() * 1.5); + } #endif // Print initial usage message, but only print it later if the status has changed @@ -369,6 +437,44 @@ void FrameBuffer::update(bool force) break; // EventHandlerState::TIMEMACHINE } + case EventHandlerState::PLAYBACK: + { + static Int32 frames = 0; + RewindManager& r = myOSystem.state().rewindManager(); + bool success = true; + Int64 frameCycles = 76 * std::max(myOSystem.console().tia().scanlinesLastFrame(), 240); + + if(--frames <= 0) + { + r.unwindStates(1); + // get time between current and next state + uInt64 startCycles = r.getCurrentCycles(); + success = r.unwindStates(1); + // display larger state gaps faster + frames = std::sqrt((myOSystem.console().tia().cycles() - startCycles) / frameCycles); + + if(success) + r.rewindStates(1); + } + + force = force || success; + if (force) + myTIASurface->render(); + + // Stop playback mode at the end of the state buffer + // and switch to Time Machine or Pause mode + if (!success) + { + frames = 0; + #ifdef GUI_SUPPORT + myOSystem.eventHandler().enterMenuMode(EventHandlerState::TIMEMACHINE); + #else + myOSystem.eventHandler().changeStateByEvent(Event::TogglePauseMode); + #endif + } + break; // EventHandlerState::PLAYBACK + } + case EventHandlerState::LAUNCHER: { force = force || myOSystem.launcher().needsRedraw(); @@ -414,8 +520,6 @@ void FrameBuffer::update(bool force) void FrameBuffer::updateInEmulationMode(float framesPerSecond) { // Update method that is specifically tailored to emulation mode - // Typically called from a thread, so it needs to be separate from - // the normal update() method // // We don't worry about selective rendering here; the rendering // always happens at the full framerate @@ -447,18 +551,78 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position, if(myMsg.surface == nullptr || !(force || myOSystem.settings().getBool("uimessages"))) return; - // Precompute the message coordinates - myMsg.text = message; - myMsg.counter = uInt32(myOSystem.frameRate()) << 1; // Show message for 2 seconds - if(myMsg.counter == 0) myMsg.counter = 60; - myMsg.color = kBtnTextColor; + const int fontWidth = font().getMaxCharWidth(), + fontHeight = font().getFontHeight(); + const int VBORDER = fontHeight / 4; + const int HBORDER = fontWidth * 1.25 / 2.0; + + myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds + if(myMsg.counter == 0) + myMsg.counter = 120; + + // Precompute the message coordinates + myMsg.text = message; + myMsg.color = kBtnTextColor; + myMsg.showGauge = false; + myMsg.w = std::min(fontWidth * (MESSAGE_WIDTH) - HBORDER * 2, + font().getStringWidth(myMsg.text) + HBORDER * 2); + myMsg.h = fontHeight + VBORDER * 2; + myMsg.position = position; + myMsg.enabled = true; - myMsg.w = font().getStringWidth(myMsg.text) + 10; - myMsg.h = font().getFontHeight() + 8; myMsg.surface->setSrcSize(myMsg.w, myMsg.h); myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor()); - myMsg.position = position; - myMsg.enabled = true; +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBuffer::showMessage(const string& message, const string& valueText, + float value, float minValue, float maxValue) +{ +#ifdef GUI_SUPPORT + // Only show messages if they've been enabled + if(myMsg.surface == nullptr || !myOSystem.settings().getBool("uimessages")) + return; + + const int fontWidth = font().getMaxCharWidth(), + fontHeight = font().getFontHeight(); + const int VBORDER = fontHeight / 4; + const int HBORDER = fontWidth * 1.25 / 2.0; + + myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds + if(myMsg.counter == 0) + myMsg.counter = 120; + + // Precompute the message coordinates + myMsg.text = message; + myMsg.color = kBtnTextColor; + myMsg.showGauge = true; + if(maxValue - minValue != 0) + myMsg.value = (value - minValue) / (maxValue - minValue) * 100.F; + else + myMsg.value = 100.F; + myMsg.valueText = valueText; + myMsg.w = std::min(fontWidth * MESSAGE_WIDTH, + font().getStringWidth(myMsg.text) + + fontWidth * (GAUGEBAR_WIDTH + 2) + + font().getStringWidth(myMsg.valueText)) + + HBORDER * 2; + myMsg.h = fontHeight + VBORDER * 2; + myMsg.position = MessagePosition::BottomCenter; + myMsg.enabled = true; + + myMsg.surface->setSrcSize(myMsg.w, myMsg.h); + myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor()); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBuffer::messageShown() const +{ +#ifdef GUI_SUPPORT + return myMsg.enabled; +#else + return false; #endif } @@ -495,7 +659,10 @@ void FrameBuffer::drawFrameStats(float framesPerSecond) ss << std::fixed << std::setprecision(1) << framesPerSecond << "fps @ " - << std::fixed << std::setprecision(0) << 100 * myOSystem.settings().getFloat("speed") + << std::fixed << std::setprecision(0) << 100 * + (myOSystem.settings().getBool("turbo") + ? 20.0F + : myOSystem.settings().getFloat("speed")) << "% speed"; myStatsMsg.surface->drawString(f, ss.str(), xPos, yPos, @@ -518,11 +685,15 @@ void FrameBuffer::drawFrameStats(float framesPerSecond) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBuffer::toggleFrameStats() +void FrameBuffer::toggleFrameStats(bool toggle) { - showFrameStats(!myStatsEnabled); + if (toggle) + showFrameStats(!myStatsEnabled); myOSystem.settings().setValue( myOSystem.settings().getBool("dev.settings") ? "dev.stats" : "plr.stats", myStatsEnabled); + + myOSystem.frameBuffer().showMessage(string("Console info ") + + (myStatsEnabled ? "enabled" : "disabled")); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -570,6 +741,11 @@ inline bool FrameBuffer::drawMessage() // Draw the bounded box and text const Common::Rect& dst = myMsg.surface->dstRect(); + const int fontWidth = font().getMaxCharWidth(), + fontHeight = font().getFontHeight(); + const int VBORDER = fontHeight / 4; + const int HBORDER = fontWidth * 1.25 / 2.0; + constexpr int BORDER = 1; switch(myMsg.position) { @@ -620,10 +796,44 @@ inline bool FrameBuffer::drawMessage() } myMsg.surface->setDstPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y()); - myMsg.surface->fillRect(1, 1, myMsg.w-2, myMsg.h-2, kBtnColor); - myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor); - myMsg.surface->drawString(font(), myMsg.text, 5, 4, - myMsg.w, myMsg.color, TextAlign::Left); + myMsg.surface->fillRect(0, 0, myMsg.w, myMsg.h, kColor); + myMsg.surface->fillRect(BORDER, BORDER, myMsg.w - BORDER * 2, myMsg.h - BORDER * 2, kBtnColor); + myMsg.surface->drawString(font(), myMsg.text, HBORDER, VBORDER, + myMsg.w, myMsg.color); + + if(myMsg.showGauge) + { + constexpr int NUM_TICKMARKS = 4; + // limit gauge bar width if texts are too long + const int swidth = std::min(fontWidth * GAUGEBAR_WIDTH, + fontWidth * (MESSAGE_WIDTH - 2) + - font().getStringWidth(myMsg.text) + - font().getStringWidth(myMsg.valueText)); + const int bwidth = swidth * myMsg.value / 100.F; + const int bheight = fontHeight >> 1; + const int x = HBORDER + font().getStringWidth(myMsg.text) + fontWidth; + // align bar with bottom of text + const int y = VBORDER + font().desc().ascent - bheight; + + // draw gauge bar + myMsg.surface->fillRect(x - BORDER, y, swidth + BORDER * 2, bheight, kSliderBGColor); + myMsg.surface->fillRect(x, y + BORDER, bwidth, bheight - BORDER * 2, kSliderColor); + // draw tickmark in the middle of the bar + for(int i = 1; i < NUM_TICKMARKS; ++i) + { + ColorId color; + int xt = x + swidth * i / NUM_TICKMARKS; + if(bwidth < xt - x) + color = kCheckColor; // kSliderColor; + else + color = kSliderBGColor; + myMsg.surface->vLine(xt, y + bheight / 2, y + bheight - 1, color); + } + // draw value text + myMsg.surface->drawString(font(), myMsg.valueText, + x + swidth + fontWidth, VBORDER, + myMsg.w, myMsg.color); + } myMsg.surface->render(); myMsg.counter--; #endif @@ -707,6 +917,7 @@ void FrameBuffer::setUIPalette() const UIPaletteArray& ui_palette = (myOSystem.settings().getString("uipalette") == "classic") ? ourClassicUIPalette : (myOSystem.settings().getString("uipalette") == "light") ? ourLightUIPalette : + (myOSystem.settings().getString("uipalette") == "dark") ? ourDarkUIPalette : ourStandardUIPalette; for(size_t i = 0, j = myFullPalette.size() - ui_palette.size(); @@ -731,6 +942,58 @@ void FrameBuffer::stateChanged(EventHandlerState state) update(true); // force full update } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string FrameBuffer::getDisplayKey() +{ + // save current window's display and position + switch(myBufferType) + { + case BufferType::Launcher: + return "launcherdisplay"; + + case BufferType::Emulator: + return "display"; + + #ifdef DEBUGGER_SUPPORT + case BufferType::Debugger: + return "dbg.display"; + #endif + + default: + return ""; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string FrameBuffer::getPositionKey() +{ + // save current window's display and position + switch(myBufferType) + { + case BufferType::Launcher: + return "launcherpos"; + + case BufferType::Emulator: + return "windowedpos"; + + #ifdef DEBUGGER_SUPPORT + case BufferType::Debugger: + return "dbg.pos"; + #endif + + default: + return ""; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBuffer::saveCurrentWindowPosition() +{ + myOSystem.settings().setValue(getDisplayKey(), getCurrentDisplayIndex()); + if(isCurrentWindowPositioned()) + myOSystem.settings().setValue(getPositionKey(), getCurrentWindowPos()); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::setFullscreen(bool enable) { @@ -753,6 +1016,7 @@ void FrameBuffer::setFullscreen(bool enable) default: return; } + saveCurrentWindowPosition(); // Changing the video mode can take some time, during which the last // sound played may get 'stuck' @@ -781,11 +1045,67 @@ void FrameBuffer::setFullscreen(bool enable) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBuffer::toggleFullscreen() +void FrameBuffer::toggleFullscreen(bool toggle) { - setFullscreen(!fullScreen()); + switch (myOSystem.eventHandler().state()) + { + case EventHandlerState::LAUNCHER: + case EventHandlerState::EMULATION: + case EventHandlerState::PAUSE: + case EventHandlerState::DEBUGGER: + { + const bool isFullscreen = toggle ? !fullScreen() : fullScreen(); + + setFullscreen(isFullscreen); + + if (myBufferType != BufferType::Launcher) + { + ostringstream msg; + + msg << "Fullscreen "; + if (isFullscreen) + msg << "enabled (" << refreshRate() << " Hz)"; + else + msg << "disabled"; + + showMessage(msg.str()); + } + break; + } + default: + break; + } } +#ifdef ADAPTABLE_REFRESH_SUPPORT +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void FrameBuffer::toggleAdaptRefresh(bool toggle) +{ + bool isAdaptRefresh = myOSystem.settings().getInt("tia.fs_refresh"); + + if(toggle) + isAdaptRefresh = !isAdaptRefresh; + + if(myBufferType == BufferType::Emulator) + { + if(toggle) + { + myOSystem.settings().setValue("tia.fs_refresh", isAdaptRefresh); + // issue a complete framebuffer re-initialization + myOSystem.createFrameBuffer(); + } + + ostringstream msg; + + msg << "Adapt refresh rate "; + msg << (isAdaptRefresh ? "enabled" : "disabled"); + msg << " (" << refreshRate() << " Hz)"; + + showMessage(msg.str()); + } +} +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::changeOverscan(int direction) { @@ -801,14 +1121,18 @@ void FrameBuffer::changeOverscan(int direction) // issue a complete framebuffer re-initialization myOSystem.createFrameBuffer(); } - ostringstream msg; - msg << "Overscan at " << overscan << "%"; - showMessage(msg.str()); + + ostringstream val; + if(overscan) + val << (overscan > 0 ? "+" : "" ) << overscan << "%"; + else + val << "Off"; + myOSystem.frameBuffer().showMessage("Overscan", val.str(), overscan, 0, 10); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FrameBuffer::changeVidMode(int direction) +void FrameBuffer::selectVidMode(int direction) { EventHandlerState state = myOSystem.eventHandler().state(); bool tiaMode = (state != EventHandlerState::DEBUGGER && @@ -816,14 +1140,14 @@ bool FrameBuffer::changeVidMode(int direction) // Only applicable when in TIA/emulation mode if(!tiaMode) - return false; + return; if(direction == +1) myCurrentModeList->next(); else if(direction == -1) myCurrentModeList->previous(); - else - return false; + + saveCurrentWindowPosition(); // Changing the video mode can take some time, during which the last // sound played may get 'stuck' @@ -841,7 +1165,10 @@ bool FrameBuffer::changeVidMode(int direction) myTIASurface->initialize(myOSystem.console(), mode); resetSurfaces(); - showMessage(mode.description); + if(fullScreen()) + showMessage(mode.description); + else + showMessage("Zoom", mode.description, mode.zoom, supportedTIAMinZoom(), myTIAMaxZoom); myOSystem.sound().mute(oldMuteState); if(fullScreen()) @@ -850,11 +1177,9 @@ bool FrameBuffer::changeVidMode(int direction) else myOSystem.settings().setValue("tia.zoom", mode.zoom); - return true; + return; } myOSystem.sound().mute(oldMuteState); - - return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -875,23 +1200,23 @@ void FrameBuffer::setCursorState() // Show/hide cursor in UI/emulation mode based on 'cursor' setting int cursor = myOSystem.settings().getInt("cursor"); // always enable cursor in lightgun games - if (usesLightgun) - cursor |= 1; + if (usesLightgun && !myGrabMouse) + cursor |= 1; // +Emulation switch(cursor) { - case 0: + case 0: // -UI, -Emulation showCursor(false); break; case 1: - showCursor(emulation); + showCursor(emulation); //-UI, +Emulation myGrabMouse = false; // disable grab while cursor is shown in emulation break; - case 2: + case 2: // +UI, -Emulation showCursor(!emulation); break; case 3: - showCursor(true); + showCursor(true); // +UI, +Emulation myGrabMouse = false; // disable grab while cursor is shown in emulation break; } @@ -909,9 +1234,14 @@ void FrameBuffer::enableGrabMouse(bool enable) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::toggleGrabMouse() { + const bool oldState = myGrabMouse; + myGrabMouse = !myGrabMouse; setCursorState(); myOSystem.settings().setValue("grabmouse", myGrabMouse); + myOSystem.frameBuffer().showMessage(oldState != myGrabMouse ? myGrabMouse + ? "Grab mouse enabled" : "Grab mouse disabled" + : "Grab mouse not allowed while cursor shown"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -955,14 +1285,14 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) if(tiaMode) { // TIA windowed modes - uInt32 minZoom = supportedTIAMinZoom(); + float minZoom = supportedTIAMinZoom(); myTIAMaxZoom = maxZoomForScreen(baseWidth, baseHeight, myAbsDesktopSize.w, myAbsDesktopSize.h); // Determine all zoom levels for(float zoom = minZoom; zoom <= myTIAMaxZoom; zoom += ZOOM_STEPS) { ostringstream desc; - desc << "Zoom " << zoom << "x"; + desc << (zoom * 100) << "%"; VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom, VideoMode::Stretch::Fill, 1.0, desc.str(), zoom); @@ -982,12 +1312,12 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight) VideoMode mode1(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, VideoMode::Stretch::Preserve, overscan, - "Preserve aspect, no stretch", myTIAMaxZoom, i); + "Fullscreen: Preserve aspect, no stretch", myTIAMaxZoom, i); myFullscreenModeLists[i].add(mode1); VideoMode mode2(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom, myFullscreenDisplays[i].w, myFullscreenDisplays[i].h, VideoMode::Stretch::Fill, overscan, - "Ignore aspect, full stretch", myTIAMaxZoom, i); + "Fullscreen: Ignore aspect, full stretch", myTIAMaxZoom, i); myFullscreenModeLists[i].add(mode2); } } @@ -1291,3 +1621,16 @@ UIPaletteArray FrameBuffer::ourLightUIPalette = { 0xffffff, 0x333333, 0xf0f0f0, 0x808080, 0xc0c0c0 // other } }; + +UIPaletteArray FrameBuffer::ourDarkUIPalette = { + { 0x646464, 0xc0c0c0, 0x3c3c3c, 0x282828, 0x989898, // base + 0xc0c0c0, 0x1567a5, 0x0059a3, 0xc0c0c0, // text + 0x202020, 0x000000, 0x0059a3, 0xb0b0b0, // UI elements + 0x282828, 0x00467f, 0x646464, 0x0059a3, 0xc0c0c0, 0xc0c0c0, // buttons + 0x989898, // checkbox + 0x3c3c3c, 0x646464, // scrollbar + 0x7f2020, 0xc0c0c0, 0xe00000, 0xc00000, // debugger + 0x989898, 0x0059a3, 0x3c3c3c, 0x000000, 0x3c3c3c, // slider + 0x000000, 0x989898, 0x202020, 0x646464, 0x3c3c3c // other + } +}; diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index ce215345a..58d61dfd3 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -26,9 +26,9 @@ class Settings; class FBSurface; class TIASurface; -namespace GUI { - class Font; -} +#ifdef GUI_SUPPORT + #include "Font.hxx" +#endif #include "Rect.hxx" #include "Variant.hxx" @@ -81,6 +81,20 @@ class FrameBuffer } }; + struct DisplayMode + { + uInt32 display; + Common::Size size; + uInt32 refresh_rate; + }; + + enum class BufferType { + None, + Launcher, + Emulator, + Debugger + }; + enum class ScalingInterpolation { none, sharp, @@ -115,7 +129,8 @@ class FrameBuffer @return Status of initialization (see FBInitStatus 'enum') */ - FBInitStatus createDisplay(const string& title, uInt32 width, uInt32 height, + FBInitStatus createDisplay(const string& title, BufferType type, + uInt32 width, uInt32 height, bool honourHiDPI = true); /** @@ -139,11 +154,24 @@ class FrameBuffer void showMessage(const string& message, MessagePosition position = MessagePosition::BottomCenter, bool force = false); + /** + Shows a message with a gauge bar onscreen. + + @param message The message to be shown + @param valueText The value of the gauge bar as text + @param value The gauge bar percentage + @param minValue The minimal value of the gauge bar + @param maxValue The maximal value of the gauge bar + */ + void showMessage(const string& message, const string& valueText, + float value, float minValue = 0.F, float maxValue = 100.F); + + bool messageShown() const; /** Toggles showing or hiding framerate statistics. */ - void toggleFrameStats(); + void toggleFrameStats(bool toggle = true); /** Shows a message containing frame statistics for the current frame. @@ -223,7 +251,7 @@ class FrameBuffer Get the minimum/maximum supported TIA zoom level (windowed mode) for the framebuffer. */ - float supportedTIAMinZoom() const { return 2 * hidpiScaleFactor(); } + float supportedTIAMinZoom() const { return myTIAMinZoom * hidpiScaleFactor(); } float supportedTIAMaxZoom() const { return myTIAMaxZoom; } /** @@ -239,14 +267,21 @@ class FrameBuffer /** Toggles between fullscreen and window mode. */ - void toggleFullscreen(); + void toggleFullscreen(bool toggle = true); + + #ifdef ADAPTABLE_REFRESH_SUPPORT + /** + Toggles between adapt fullscreen refresh rate on and off. + */ + void toggleAdaptRefresh(bool toggle = true); + #endif /** Changes the fullscreen overscan. - direction = -1 means less overscan - direction = +1 means more overscan + + @param direction +1 indicates increase, -1 indicates decrease. */ - void changeOverscan(int direction); + void changeOverscan(int direction = +1); /** This method is called when the user wants to switch to the next @@ -256,9 +291,9 @@ class FrameBuffer direction = -1 means go to the next lower video mode direction = +1 means go to the next higher video mode - @param direction Described above + @param direction +1 indicates increase, -1 indicates decrease. */ - bool changeVidMode(int direction); + void selectVidMode(int direction = +1); /** Sets the state of the cursor (hidden or grabbed) based on the @@ -299,6 +334,13 @@ class FrameBuffer bool hidpiEnabled() const { return myHiDPIEnabled; } uInt32 hidpiScaleFactor() const { return myHiDPIEnabled ? 2 : 1; } + /** + These methods are used to load/save position and display of the current window. + */ + string getPositionKey(); + string getDisplayKey(); + void saveCurrentWindowPosition(); + #ifdef GUI_SUPPORT /** Get the font object(s) of the framebuffer @@ -307,6 +349,15 @@ class FrameBuffer const GUI::Font& infoFont() const { return *myInfoFont; } const GUI::Font& smallFont() const { return *mySmallFont; } const GUI::Font& launcherFont() const { return *myLauncherFont; } + + /** + Get the font description from the font name + + @param name The settings name of the font + + @return The description of the font + */ + FontDesc getFontDesc(const string& name) const; #endif ////////////////////////////////////////////////////////////////////// @@ -362,6 +413,21 @@ class FrameBuffer */ virtual void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const = 0; + /** + This method is called to query if the current window is not centered or fullscreen. + + @return True, if the current window is positioned + */ + virtual bool isCurrentWindowPositioned() const = 0; + + /** + This method is called to query the video hardware for position of + the current window + + @return The position of the currently displayed window + */ + virtual Common::Point getCurrentWindowPos() const = 0; + /** This method is called to query the video hardware for the index of the display the current window is displayed on @@ -369,19 +435,25 @@ class FrameBuffer @return the current display index or a negative value if no window is displayed */ - virtual Int32 getCurrentDisplayIndex() = 0; - - /** - This method is called to preserve the last current windowed position. - */ - virtual void updateWindowedPos() = 0; + virtual Int32 getCurrentDisplayIndex() const = 0; /** Clear the framebuffer. */ virtual void clear() = 0; + /** + Transform from window to renderer coordinates, x direction + */ + virtual int scaleX(int x) const { return x; } + + /** + Transform from window to renderer coordinates, y direction + */ + virtual int scaleY(int y) const { return y; } + protected: + /** This method is called to query and initialize the video hardware for desktop and fullscreen resolution information. Since several @@ -453,11 +525,21 @@ class FrameBuffer */ virtual string about() const = 0; + /** + Retrieve the current display's refresh rate + */ + virtual int refreshRate() const { return 0; } + protected: // The parent system for the framebuffer OSystem& myOSystem; private: + // Maximum message width [chars] + static constexpr int MESSAGE_WIDTH = 56; + // Maximum gauge bar width [chars] + static constexpr int GAUGEBAR_WIDTH = 30; + /** Draw pending messages. @@ -470,6 +552,13 @@ class FrameBuffer */ void resetSurfaces(); + #ifdef GUI_SUPPORT + /** + Setup the UI fonts + */ + void setupFonts(); + #endif + /** Calculate the maximum level by which the base window can be zoomed and still fit in the given screen dimensions. @@ -528,6 +617,9 @@ class FrameBuffer // Title of the main window/screen string myScreenTitle; + // Type of the frame buffer + BufferType myBufferType{BufferType::None}; + // Number of displays int myNumDisplays{1}; @@ -594,6 +686,9 @@ class FrameBuffer ColorId color{kNone}; shared_ptr surface; bool enabled{false}; + bool showGauge{false}; + float value{0.0F}; + string valueText; }; Message myMsg; Message myStatsMsg; @@ -609,6 +704,8 @@ class FrameBuffer VideoModeList myWindowedModeList; vector myFullscreenModeLists; + // Minimum TIA zoom level that can be used for this framebuffer + float myTIAMinZoom{2.F}; // Maximum TIA zoom level that can be used for this framebuffer float myTIAMaxZoom{1.F}; @@ -617,7 +714,8 @@ class FrameBuffer FullPaletteArray myFullPalette; // Holds UI palette data (for each variation) - static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette, ourLightUIPalette; + static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette, + ourLightUIPalette, ourDarkUIPalette; private: // Following constructors and assignment operators not supported diff --git a/src/emucore/Genesis.cxx b/src/emucore/Genesis.cxx index 488f04980..0b1ef7a2f 100644 --- a/src/emucore/Genesis.cxx +++ b/src/emucore/Genesis.cxx @@ -53,7 +53,7 @@ void Genesis::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFire1Event) == 0); + bool firePressed = myEvent.get(myFire1Event) != 0; // The Genesis has one more button (C) that can be read by the 2600 // However, it seems to work opposite to the BoosterGrip controller, @@ -88,11 +88,12 @@ void Genesis::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); if(myEvent.get(Event::MouseButtonRightValue)) setPin(AnalogPin::Five, MAX_RESISTANCE); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Joystick.cxx b/src/emucore/Joystick.cxx index f9ee75545..ea0d71300 100644 --- a/src/emucore/Joystick.cxx +++ b/src/emucore/Joystick.cxx @@ -52,7 +52,7 @@ void Joystick::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; // Axis events (usually generated by the Stelladaptor) int xaxis = myEvent.get(myXAxisValue); @@ -102,10 +102,11 @@ void Joystick::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Joystick.hxx b/src/emucore/Joystick.hxx index 7acd631bc..505294456 100644 --- a/src/emucore/Joystick.hxx +++ b/src/emucore/Joystick.hxx @@ -19,8 +19,8 @@ #define JOYSTICK_HXX #include "bspf.hxx" -#include "Control.hxx" #include "Event.hxx" +#include "Control.hxx" /** The standard Atari 2600 joystick controller. diff --git a/src/emucore/Keyboard.hxx b/src/emucore/Keyboard.hxx index a241cbc37..9ec176d71 100644 --- a/src/emucore/Keyboard.hxx +++ b/src/emucore/Keyboard.hxx @@ -19,8 +19,8 @@ #define KEYBOARD_HXX #include "bspf.hxx" -#include "Control.hxx" #include "Event.hxx" +#include "Control.hxx" /** The standard Atari 2600 keyboard controller diff --git a/src/emucore/Lightgun.cxx b/src/emucore/Lightgun.cxx index 1c6c82ba7..3ae39d8e5 100644 --- a/src/emucore/Lightgun.cxx +++ b/src/emucore/Lightgun.cxx @@ -116,10 +116,12 @@ bool Lightgun::read(DigitalPin pin) void Lightgun::update() { // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::One, myEvent.get(Event::JoystickZeroFire) == 0); + bool firePressed = myEvent.get(Event::JoystickZeroFire) != 0; // We allow left and right mouse buttons for fire button - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::One, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); + + setPin(DigitalPin::One, !getAutoFireState(firePressed)); } diff --git a/src/emucore/Lightgun.hxx b/src/emucore/Lightgun.hxx index 7bec4f4e2..facdffe1e 100644 --- a/src/emucore/Lightgun.hxx +++ b/src/emucore/Lightgun.hxx @@ -18,6 +18,11 @@ #ifndef LIGHTGUN_HXX #define LIGHTGUN_HXX +class FrameBuffer; + +#include "bspf.hxx" +#include "Control.hxx" + /** This class handles the lightgun controller diff --git a/src/emucore/M6502.cxx b/src/emucore/M6502.cxx index a69213b69..86b050dfb 100644 --- a/src/emucore/M6502.cxx +++ b/src/emucore/M6502.cxx @@ -18,26 +18,20 @@ #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" #include "Expression.hxx" - #include "CartDebug.hxx" + #include "Device.hxx" #include "Base.hxx" - // Flags for disassembly types - #define DISASM_CODE CartDebug::CODE -// #define DISASM_GFX CartDebug::GFX -// #define DISASM_PGFX CartDebug::PGFX - #define DISASM_DATA CartDebug::DATA -// #define DISASM_ROW CartDebug::ROW - #define DISASM_WRITE CartDebug::WRITE - #define DISASM_NONE 0 + // Flags for access types + #define DISASM_CODE Device::CODE + #define DISASM_DATA Device::DATA + #define DISASM_WRITE Device::WRITE + #define DISASM_NONE Device::NONE #else - // Flags for disassembly types + // Flags for access types #define DISASM_CODE 0 -// #define DISASM_GFX 0 -// #define DISASM_PGFX 0 #define DISASM_DATA 0 -// #define DISASM_ROW 0 - #define DISASM_NONE 0 #define DISASM_WRITE 0 + #define DISASM_NONE 0 #endif #include "Settings.hxx" #include "Vec.hxx" @@ -104,7 +98,7 @@ void M6502::reset() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline uInt8 M6502::peek(uInt16 address, uInt8 flags) +inline uInt8 M6502::peek(uInt16 address, Device::AccessFlags flags) { handleHalt(); @@ -144,7 +138,7 @@ inline uInt8 M6502::peek(uInt16 address, uInt8 flags) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline void M6502::poke(uInt16 address, uInt8 value, uInt8 flags) +inline void M6502::poke(uInt16 address, uInt8 value, Device::AccessFlags flags) { //////////////////////////////////////////////// // TODO - move this logic directly into CartAR @@ -300,8 +294,8 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result) mySystem->cart().clearAllRAMAccesses(); #endif // DEBUGGER_SUPPORT - // Reset the peek/poke address pointers - myLastPeekAddress = myLastPokeAddress = myDataAddressForPoke = 0; + // Reset the data poke address pointer + myDataAddressForPoke = 0; try { uInt16 operandAddress = 0, intermediateAddress = 0; diff --git a/src/emucore/M6502.hxx b/src/emucore/M6502.hxx index d4769e0e7..6cb3ccc65 100644 --- a/src/emucore/M6502.hxx +++ b/src/emucore/M6502.hxx @@ -34,6 +34,7 @@ class DispatchResult; #endif #include "bspf.hxx" +#include "Device.hxx" #include "Serializable.hxx" /** @@ -156,13 +157,27 @@ class M6502 : public Serializable @return The address of the last read */ - uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; } + uInt16 lastReadAddress() const { return myLastPeekAddress; } /** Return the last address that was part of a write/poke. @return The address of the last write */ + uInt16 lastWriteAddress() const { return myLastPokeAddress; } + + /** + Return the last (non-mirrored) address that was part of a read/peek. + + @return The address of the last read + */ + uInt16 lastReadBaseAddress() const { return myLastPeekBaseAddress; } + + /** + Return the last (non-mirrored) address that was part of a write/poke. + + @return The address of the last write + */ uInt16 lastWriteBaseAddress() const { return myLastPokeBaseAddress; } /** @@ -255,7 +270,7 @@ class M6502 : public Serializable @return The byte at the specified address */ - uInt8 peek(uInt16 address, uInt8 flags); + uInt8 peek(uInt16 address, Device::AccessFlags flags); /** Change the byte at the specified address to the given value and @@ -264,7 +279,7 @@ class M6502 : public Serializable @param address The address where the value should be stored @param value The value to be stored at the address */ - void poke(uInt16 address, uInt8 value, uInt8 flags = 0); + void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE); /** Get the 8-bit value of the Processor Status register. @@ -377,7 +392,7 @@ class M6502 : public Serializable /// accessed specifically by a peek or poke command uInt16 myLastPeekBaseAddress{0}, myLastPokeBaseAddress{0}; // Indicates the type of the last access - uInt8 myFlags{0}; + uInt16 myFlags{0}; /// Indicates the last address used to access data by a peek command /// for the CPU registers (S/A/X/Y) diff --git a/src/emucore/M6502.ins b/src/emucore/M6502.ins index f48e689eb..e04ac9cb2 100644 --- a/src/emucore/M6502.ins +++ b/src/emucore/M6502.ins @@ -3770,9 +3770,9 @@ case 0x40: } { peek(0x0100 + SP++, DISASM_NONE); - PS(peek(0x0100 + SP++, DISASM_NONE)); - PC = peek(0x0100 + SP++, DISASM_NONE); - PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8); + PS(peek(0x0100 + SP++, DISASM_DATA)); + PC = peek(0x0100 + SP++, DISASM_DATA); + PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8); } break; @@ -3784,8 +3784,8 @@ case 0x60: } { peek(0x0100 + SP++, DISASM_NONE); - PC = peek(0x0100 + SP++, DISASM_NONE); - PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8); + PC = peek(0x0100 + SP++, DISASM_DATA); + PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8); peek(PC++, DISASM_NONE); } break; diff --git a/src/emucore/M6502.m4 b/src/emucore/M6502.m4 index 0c9046018..da097512f 100644 --- a/src/emucore/M6502.m4 +++ b/src/emucore/M6502.m4 @@ -885,15 +885,15 @@ define(M6502_RRA, `{ define(M6502_RTI, `{ peek(0x0100 + SP++, DISASM_NONE); - PS(peek(0x0100 + SP++, DISASM_NONE)); - PC = peek(0x0100 + SP++, DISASM_NONE); - PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8); + PS(peek(0x0100 + SP++, DISASM_DATA)); + PC = peek(0x0100 + SP++, DISASM_DATA); + PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8); }') define(M6502_RTS, `{ peek(0x0100 + SP++, DISASM_NONE); - PC = peek(0x0100 + SP++, DISASM_NONE); - PC |= (uInt16(peek(0x0100 + SP, DISASM_NONE)) << 8); + PC = peek(0x0100 + SP++, DISASM_DATA); + PC |= (uInt16(peek(0x0100 + SP, DISASM_DATA)) << 8); peek(PC++, DISASM_NONE); }') diff --git a/src/emucore/M6532.cxx b/src/emucore/M6532.cxx index dec6d9981..18f950e62 100644 --- a/src/emucore/M6532.cxx +++ b/src/emucore/M6532.cxx @@ -21,9 +21,7 @@ #include "Settings.hxx" #include "Switches.hxx" #include "System.hxx" -#ifdef DEBUGGER_SUPPORT - #include "CartDebug.hxx" -#endif +#include "Base.hxx" #include "M6532.hxx" @@ -61,7 +59,6 @@ void M6532::reset() myTimer = mySystem->randGenerator().next() & 0xff; myDivider = 1024; mySubTimer = 0; - myTimerWrapped = false; myWrappedThisCycle = false; mySetTimerCycle = myLastCycle = 0; @@ -123,16 +120,16 @@ void M6532::updateEmulation() myWrappedThisCycle = false; mySubTimer = (cycles + mySubTimer) % myDivider; - if(!myTimerWrapped) + if ((myInterruptFlag & TimerBit) == 0) { uInt32 timerTicks = (cycles + subTimer) / myDivider; if(timerTicks > myTimer) { cycles -= ((myTimer + 1) * myDivider - subTimer); + myWrappedThisCycle = cycles == 0; myTimer = 0xFF; - myTimerWrapped = true; myInterruptFlag |= TimerBit; } else @@ -142,8 +139,10 @@ void M6532::updateEmulation() } } - if(myTimerWrapped) + if((myInterruptFlag & TimerBit) != 0) { myTimer = (myTimer - cycles) & 0xFF; + myWrappedThisCycle = myTimer == 0xFF; + } myLastCycle = mySystem->cycles(); } @@ -221,7 +220,7 @@ uInt8 M6532::peek(uInt16 addr) { // Timer Flag is always cleared when accessing INTIM if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit; - myTimerWrapped = false; + return myTimer; } @@ -314,10 +313,9 @@ void M6532::setTimerRegister(uInt8 value, uInt8 interval) myTimer = value; mySubTimer = myDivider - 1; - myTimerWrapped = false; // Interrupt timer flag is cleared (and invalid) when writing to the timer - myInterruptFlag &= ~TimerBit; + if (!myWrappedThisCycle) myInterruptFlag &= ~TimerBit; mySetTimerCycle = mySystem->cycles(); } @@ -366,7 +364,6 @@ bool M6532::save(Serializer& out) const out.putInt(myTimer); out.putInt(mySubTimer); out.putInt(myDivider); - out.putBool(myTimerWrapped); out.putBool(myWrappedThisCycle); out.putLong(myLastCycle); out.putLong(mySetTimerCycle); @@ -399,7 +396,6 @@ bool M6532::load(Serializer& in) myTimer = in.getInt(); mySubTimer = in.getInt(); myDivider = in.getInt(); - myTimerWrapped = in.getBool(); myWrappedThisCycle = in.getBool(); myLastCycle = in.getLong(); mySetTimerCycle = in.getLong(); @@ -448,7 +444,7 @@ Int32 M6532::intimClocks() // INTIM value, it will give the current number of clocks between one // INTIM value and the next - return myTimerWrapped ? 1 : (myDivider - mySubTimer); + return ((myInterruptFlag & TimerBit) != 0) ? 1 : (myDivider - mySubTimer); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -460,14 +456,17 @@ uInt32 M6532::timerClocks() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void M6532::createAccessBases() { - myRAMAccessBase.fill(CartDebug::NONE); - myStackAccessBase.fill(CartDebug::NONE); - myIOAccessBase.fill(CartDebug::NONE); + myRAMAccessBase.fill(Device::NONE); + myStackAccessBase.fill(Device::NONE); + myIOAccessBase.fill(Device::NONE); + myRAMAccessCounter.fill(0); + myStackAccessCounter.fill(0); + myIOAccessCounter.fill(0); myZPAccessDelay.fill(ZP_DELAY); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 M6532::getAccessFlags(uInt16 address) const +Device::AccessFlags M6532::getAccessFlags(uInt16 address) const { if (address & IO_BIT) return myIOAccessBase[address & IO_MASK]; @@ -478,10 +477,10 @@ uInt8 M6532::getAccessFlags(uInt16 address) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void M6532::setAccessFlags(uInt16 address, uInt8 flags) +void M6532::setAccessFlags(uInt16 address, Device::AccessFlags flags) { // ignore none flag - if (flags != CartDebug::NONE) { + if (flags != Device::NONE) { if (address & IO_BIT) myIOAccessBase[address & IO_MASK] |= flags; else { @@ -495,4 +494,63 @@ void M6532::setAccessFlags(uInt16 address, uInt8 flags) } } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void M6532::increaseAccessCounter(uInt16 address, bool isWrite) +{ + if (address & IO_BIT) + myIOAccessCounter[(isWrite ? IO_SIZE : 0) + (address & IO_MASK)]++; + else { + // the first access, either by direct RAM or stack access is assumed as initialization + if (myZPAccessDelay[address & RAM_MASK]) + myZPAccessDelay[address & RAM_MASK]--; + else if (address & STACK_BIT) + myStackAccessCounter[(isWrite ? STACK_SIZE : 0) + (address & STACK_MASK)]++; + else + myRAMAccessCounter[(isWrite ? RAM_SIZE : 0) + (address & RAM_MASK)]++; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string M6532::getAccessCounters() const +{ + ostringstream out; + + out << "RAM reads:\n"; + for(uInt16 addr = 0x00; addr < RAM_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x80) << "," + << Common::Base::toString(myRAMAccessCounter[addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + out << "RAM writes:\n"; + for(uInt16 addr = 0x00; addr < RAM_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x80) << "," + << Common::Base::toString(myRAMAccessCounter[RAM_SIZE + addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + + + out << "Stack reads:\n"; + for(uInt16 addr = 0x00; addr < STACK_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x180) << "," + << Common::Base::toString(myStackAccessCounter[addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + out << "Stack writes:\n"; + for(uInt16 addr = 0x00; addr < STACK_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x180) << "," + << Common::Base::toString(myStackAccessCounter[STACK_SIZE + addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + + out << "IO reads:\n"; + for(uInt16 addr = 0x00; addr < IO_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x280) << "," + << Common::Base::toString(myIOAccessCounter[addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + out << "IO writes:\n"; + for(uInt16 addr = 0x00; addr < IO_SIZE; ++addr) + out << Common::Base::HEX4 << (addr | 0x280) << "," + << Common::Base::toString(myIOAccessCounter[IO_SIZE + addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + + return out.str(); +} + #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/M6532.hxx b/src/emucore/M6532.hxx index bbda58e31..6e7408798 100644 --- a/src/emucore/M6532.hxx +++ b/src/emucore/M6532.hxx @@ -130,12 +130,21 @@ class M6532 : public Device */ const uInt8* getRAM() const { return myRAM.data(); } + #ifdef DEBUGGER_SUPPORT + /** + Query the access counters + + @return The access counters as comma separated string + */ + string getAccessCounters() const override; + #endif + private: void setTimerRegister(uInt8 data, uInt8 interval); void setPinState(bool shcha); -#ifdef DEBUGGER_SUPPORT + #ifdef DEBUGGER_SUPPORT // The following are used by the debugger to read INTIM/TIMINT // We need separate methods to do this, so the state of the system // isn't changed @@ -147,19 +156,26 @@ class M6532 : public Device void createAccessBases(); /** - Query the given address type for the associated disassembly flags. + Query the given address type for the associated access flags. @param address The address to query */ - uInt8 getAccessFlags(uInt16 address) const override; + Device::AccessFlags getAccessFlags(uInt16 address) const override; /** - Change the given address to use the given disassembly flags. + Change the given address to use the given access flags. @param address The address to modify - @param flags A bitfield of DisasmType directives for the given address + @param flags A bitfield of AccessType directives for the given address */ - void setAccessFlags(uInt16 address, uInt8 flags) override; -#endif // DEBUGGER_SUPPORT + void setAccessFlags(uInt16 address, Device::AccessFlags flags) override; + + /** + Increase the given address's access counter + + @param address The address to modify + */ + void increaseAccessCounter(uInt16 address, bool isWrite) override; + #endif // DEBUGGER_SUPPORT private: // Reference to the console @@ -180,8 +196,7 @@ class M6532 : public Device // The divider uInt32 myDivider{1}; - // Has the timer wrapped? - bool myTimerWrapped{false}; + // Has the timer wrapped this very cycle? bool myWrappedThisCycle{false}; // Cycle when the timer set. Debugging only. @@ -221,13 +236,18 @@ class M6532 : public Device RAM_SIZE = 0x80, RAM_MASK = RAM_SIZE - 1, STACK_SIZE = RAM_SIZE, STACK_MASK = RAM_MASK, STACK_BIT = 0x100, IO_SIZE = 0x20, IO_MASK = IO_SIZE - 1, IO_BIT = 0x200, - ZP_DELAY = 1; + ZP_DELAY = 1 * 2; // The arrays containing information about every byte of RIOT // indicating whether and how (RW) it is used. - std::array myRAMAccessBase; - std::array myStackAccessBase; - std::array myIOAccessBase; + std::array myRAMAccessBase; + std::array myStackAccessBase; + std::array myIOAccessBase; + // The arrays containing information about every byte of RIOT + // indicating how often it is accessed. + std::array myRAMAccessCounter; + std::array myStackAccessCounter; + std::array myIOAccessCounter; // The array used to skip the first ZP access tracking std::array myZPAccessDelay; #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/MT24LC256.cxx b/src/emucore/MT24LC256.cxx index 93dace04b..b99f2ec2a 100644 --- a/src/emucore/MT24LC256.cxx +++ b/src/emucore/MT24LC256.cxx @@ -43,27 +43,23 @@ */ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MT24LC256::MT24LC256(const string& filename, const System& system, +MT24LC256::MT24LC256(const FilesystemNode& eepromfile, const System& system, const Controller::onMessageCallback& callback) : mySystem(system), myCallback(callback), - myDataFile(filename) + myDataFile(eepromfile) { // Load the data from an external file (if it exists) - ifstream in(myDataFile, std::ios_base::binary); - if(in.is_open()) + try { // Get length of file; it must be 32768 - in.seekg(0, std::ios::end); - if(uInt32(in.tellg()) == FLASH_SIZE) - { - in.seekg(0, std::ios::beg); - in.read(reinterpret_cast(myData.data()), myData.size()); + if(myDataFile.read(myData) == FLASH_SIZE) myDataFileExists = true; - } } - else + catch(...) + { myDataFileExists = false; + } // Then initialize the I2C state jpee_init(); @@ -77,9 +73,8 @@ MT24LC256::~MT24LC256() // Save EEPROM data to external file only when necessary if(!myDataFileExists || myDataChanged) { - ofstream out(myDataFile, std::ios_base::binary); - if(out.is_open()) - out.write(reinterpret_cast(myData.data()), myData.size()); + try { myDataFile.write(myData, FLASH_SIZE); } + catch(...) { } } } @@ -139,7 +134,7 @@ void MT24LC256::eraseAll() // Work around a bug in XCode 11.2 with -O0 and -O1 const uInt8 initialValue = INITIAL_VALUE; - myData.fill(initialValue); + std::fill_n(myData.get(), FLASH_SIZE, initialValue); myDataChanged = true; } @@ -153,7 +148,7 @@ void MT24LC256::eraseCurrent() { if(myPageHit[page]) { - std::fill_n(myData.begin() + page * PAGE_SIZE, PAGE_SIZE, initialValue); + std::fill_n(myData.get() + page * PAGE_SIZE, PAGE_SIZE, initialValue); myDataChanged = true; } } @@ -182,7 +177,7 @@ void MT24LC256::jpee_init() jpee_smallmode = 0; jpee_logmode = -1; if(!myDataFileExists) - myData.fill(initialValue); + std::fill_n(myData.get(), FLASH_SIZE, initialValue); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/MT24LC256.hxx b/src/emucore/MT24LC256.hxx index 2832aef6c..6f51dea26 100644 --- a/src/emucore/MT24LC256.hxx +++ b/src/emucore/MT24LC256.hxx @@ -21,6 +21,7 @@ class System; #include "Control.hxx" +#include "FSNode.hxx" #include "bspf.hxx" /** @@ -36,19 +37,19 @@ class MT24LC256 /** Create a new 24LC256 with its data stored in the given file - @param filename Data file containing the EEPROM data - @param system The system using the controller of this device - @param callback Called to pass messages back to the parent controller + @param eepromfile Data file containing the EEPROM data + @param system The system using the controller of this device + @param callback Called to pass messages back to the parent controller */ - MT24LC256(const string& filename, const System& system, + MT24LC256(const FilesystemNode& eepromfile, const System& system, const Controller::onMessageCallback& callback); ~MT24LC256(); public: // Sizes of the EEPROM - static constexpr uInt32 FLASH_SIZE = 32_KB; - static constexpr uInt32 PAGE_SIZE = 64; - static constexpr uInt32 PAGE_NUM = FLASH_SIZE / PAGE_SIZE; + static constexpr size_t FLASH_SIZE = 32_KB; + static constexpr size_t PAGE_SIZE = 64; + static constexpr size_t PAGE_NUM = FLASH_SIZE / PAGE_SIZE; // Initial state value of flash EEPROM static constexpr uInt8 INITIAL_VALUE = 0xff; @@ -92,7 +93,7 @@ class MT24LC256 Controller::onMessageCallback myCallback; // The EEPROM data - std::array myData; + ByteBuffer myData; // Track which pages are used std::array myPageHit; @@ -110,7 +111,7 @@ class MT24LC256 uInt64 myCyclesWhenSDASet{0}, myCyclesWhenSCLSet{0}; // The file containing the EEPROM data - string myDataFile; + FilesystemNode myDataFile; // Indicates if a valid EEPROM data file exists/was successfully loaded bool myDataFileExists{false}; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index 4258e72b9..774d001c1 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -47,9 +47,10 @@ #include "FSNode.hxx" #include "MD5.hxx" #include "Cart.hxx" -#include "CartDetector.hxx" +#include "CartCreator.hxx" #include "FrameBuffer.hxx" #include "TIASurface.hxx" +#include "PaletteHandler.hxx" #include "TIAConstants.hxx" #include "Settings.hxx" #include "PropsSet.hxx" @@ -124,22 +125,22 @@ bool OSystem::create() << " Features: " << myFeatures << endl << " " << myBuildInfo << endl << endl << "Base directory: '" - << FilesystemNode(myBaseDir).getShortPath() << "'" << endl + << myBaseDir.getShortPath() << "'" << endl << "State directory: '" - << FilesystemNode(myStateDir).getShortPath() << "'" << endl + << myStateDir.getShortPath() << "'" << endl << "NVRam directory: '" - << FilesystemNode(myNVRamDir).getShortPath() << "'" << endl; + << myNVRamDir.getShortPath() << "'" << endl; - if(!myConfigFile.empty()) + if(myConfigFile.getPath() != EmptyString) buf << "Configuration file: '" - << FilesystemNode(myConfigFile).getShortPath() << "'" << endl; + << myConfigFile.getShortPath() << "'" << endl; buf << "Game properties: '" - << FilesystemNode(myPropertiesFile).getShortPath() << "'" << endl + << myPropertiesFile.getShortPath() << "'" << endl << "Cheat file: '" - << FilesystemNode(myCheatFile).getShortPath() << "'" << endl + << myCheatFile.getShortPath() << "'" << endl << "Palette file: '" - << FilesystemNode(myPaletteFile).getShortPath() << "'" << endl; + << myPaletteFile.getShortPath() << "'" << endl; Logger::info(buf.str()); // NOTE: The framebuffer MUST be created before any other object!!! @@ -202,30 +203,27 @@ void OSystem::loadConfig(const Settings::Options& options) { // Get base directory and config file from derived class // It will decide whether it can override its default location - getBaseDirAndConfig(myBaseDir, myConfigFile, - myDefaultSaveDir, myDefaultLoadDir, - ourOverrideBaseDirWithApp, ourOverrideBaseDir); + string baseDir, cfgFile, defSaveDir, defLoadDir; + getBaseDirAndConfig(baseDir, cfgFile, defSaveDir, defLoadDir, + ourOverrideBaseDirWithApp, ourOverrideBaseDir); // Get fully-qualified pathnames, and make directories when needed - FilesystemNode node(myBaseDir); - if(!node.isDirectory()) - node.makeDir(); - myBaseDir = node.getPath(); - if(!myConfigFile.empty()) - myConfigFile = FilesystemNode(myConfigFile).getPath(); + myBaseDir = FilesystemNode(baseDir); + if(!myBaseDir.isDirectory()) + myBaseDir.makeDir(); + if(!cfgFile.empty()) + myConfigFile = FilesystemNode(cfgFile); - FilesystemNode save(myDefaultSaveDir); - if(!save.isDirectory()) - save.makeDir(); - myDefaultSaveDir = save.getShortPath(); + myDefaultSaveDir = FilesystemNode(defSaveDir); + if(!myDefaultSaveDir.isDirectory()) + myDefaultSaveDir.makeDir(); - FilesystemNode load(myDefaultLoadDir); - if(!load.isDirectory()) - load.makeDir(); - myDefaultLoadDir = load.getShortPath(); + myDefaultLoadDir = FilesystemNode(defLoadDir); + if(!myDefaultLoadDir.isDirectory()) + myDefaultLoadDir.makeDir(); #ifdef SQLITE_SUPPORT - mySettingsDb = make_shared(myBaseDir, "settings"); + mySettingsDb = make_shared(myBaseDir.getPath(), "settings"); if(!mySettingsDb->initialize()) mySettingsDb.reset(); #endif @@ -249,11 +247,12 @@ void OSystem::saveConfig() if(myFrameBuffer) { // Save the last windowed position and display on system shutdown - myFrameBuffer->updateWindowedPos(); - settings().setValue("display", myFrameBuffer->getCurrentDisplayIndex()); + myFrameBuffer->saveCurrentWindowPosition(); Logger::debug("Saving TV effects options ..."); myFrameBuffer->tiaSurface().ntsc().saveConfig(settings()); + Logger::debug("Saving palette settings..."); + myFrameBuffer->tiaSurface().paletteHandler().saveConfig(settings()); } Logger::debug("Saving config options ..."); @@ -267,41 +266,55 @@ void OSystem::saveConfig() void OSystem::setConfigPaths() { // Make sure all required directories actually exist - auto buildDirIfRequired = [](string& path, const string& pathToBuild) + auto buildDirIfRequired = [](FilesystemNode& path, + const FilesystemNode& initialPath, + const string& pathToAppend = EmptyString) { - FilesystemNode node(pathToBuild); - if(!node.isDirectory()) - node.makeDir(); - - path = node.getPath(); + path = initialPath; + if(pathToAppend != EmptyString) + path /= pathToAppend; + if(!path.isDirectory()) + path.makeDir(); }; - buildDirIfRequired(myStateDir, myBaseDir + "state"); - buildDirIfRequired(myNVRamDir, myBaseDir + "nvram"); - -#ifdef PNG_SUPPORT - mySnapshotSaveDir = mySettings->getString("snapsavedir"); - if(mySnapshotSaveDir == "") mySnapshotSaveDir = defaultSaveDir(); - buildDirIfRequired(mySnapshotSaveDir, mySnapshotSaveDir); - - mySnapshotLoadDir = mySettings->getString("snaploaddir"); - if(mySnapshotLoadDir == "") mySnapshotLoadDir = defaultLoadDir(); - buildDirIfRequired(mySnapshotLoadDir, mySnapshotLoadDir); + buildDirIfRequired(myStateDir, myBaseDir, "state"); + buildDirIfRequired(myNVRamDir, myBaseDir, "nvram"); +#ifdef DEBUGGER_SUPPORT + buildDirIfRequired(myCfgDir, myBaseDir, "cfg"); #endif - myCheatFile = FilesystemNode(myBaseDir + "stella.cht").getPath(); - myPaletteFile = FilesystemNode(myBaseDir + "stella.pal").getPath(); - myPropertiesFile = FilesystemNode(myBaseDir + "stella.pro").getPath(); +#ifdef PNG_SUPPORT + const string& ssSaveDir = mySettings->getString("snapsavedir"); + if(ssSaveDir == EmptyString) + mySnapshotSaveDir = defaultSaveDir(); + else + mySnapshotSaveDir = FilesystemNode(ssSaveDir); + if(!mySnapshotSaveDir.isDirectory()) + mySnapshotSaveDir.makeDir(); + + const string& ssLoadDir = mySettings->getString("snaploaddir"); + if(ssLoadDir == EmptyString) + mySnapshotLoadDir = defaultLoadDir(); + else + mySnapshotLoadDir = FilesystemNode(ssLoadDir); + if(!mySnapshotLoadDir.isDirectory()) + mySnapshotLoadDir.makeDir(); +#endif + + myCheatFile = myBaseDir; myCheatFile /= "stella.cht"; + myPaletteFile = myBaseDir; myPaletteFile /= "stella.pal"; + myPropertiesFile = myBaseDir; myPropertiesFile /= "stella.pro"; #if 0 // Debug code - auto dbgPath = [](const string& desc, const string& location) + auto dbgPath = [](const string& desc, const FilesystemNode& location) { cerr << desc << ": " << location << endl; }; dbgPath("base dir ", myBaseDir); dbgPath("state dir ", myStateDir); dbgPath("nvram dir ", myNVRamDir); + dbgPath("cfg dir ", myCfgDir); dbgPath("ssave dir ", mySnapshotSaveDir); dbgPath("sload dir ", mySnapshotLoadDir); dbgPath("cheat file", myCheatFile); @@ -314,21 +327,24 @@ void OSystem::setConfigPaths() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool OSystem::checkUserPalette(bool outputError) const { - const string& palette = paletteFile(); - ifstream in(palette, std::ios::binary); - if (!in) - return false; - - // Make sure the contains enough data for the NTSC, PAL and SECAM palettes - // This means 128 colours each for NTSC and PAL, at 3 bytes per pixel - // and 8 colours for SECAM at 3 bytes per pixel - in.seekg(0, std::ios::end); - std::streampos length = in.tellg(); - in.seekg(0, std::ios::beg); - if (length < 128 * 3 * 2 + 8 * 3) + try + { + ByteBuffer palette; + size_t size = paletteFile().read(palette); + + // Make sure the contains enough data for the NTSC, PAL and SECAM palettes + // This means 128 colours each for NTSC and PAL, at 3 bytes per pixel + // and 8 colours for SECAM at 3 bytes per pixel + if(size != 128 * 3 * 2 + 8 * 3) + { + if(outputError) + cerr << "ERROR: invalid palette file " << paletteFile() << endl; + + return false; + } + } + catch(...) { - if (outputError) - cerr << "ERROR: invalid palette file " << palette << endl; return false; } return true; @@ -348,6 +364,7 @@ FBInitStatus OSystem::createFrameBuffer() case EventHandlerState::CMDMENU: case EventHandlerState::TIMEMACHINE: #endif + case EventHandlerState::PLAYBACK: if((fbstatus = myConsole->initializeVideo()) != FBInitStatus::Success) return fbstatus; break; @@ -403,7 +420,7 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum, // Each time a new console is loaded, we simulate a cart removal // Some carts need knowledge of this, as they behave differently // based on how many power-cycles they've been through since plugged in - mySettings->setValue("romloadcount", 0); + mySettings->setValue("romloadcount", -1); // we move to the next game initially } // Create an instance of the 2600 game console @@ -418,7 +435,7 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum, } catch(const runtime_error& e) { - buf << "ERROR: Couldn't create console (" << e.what() << ")"; + buf << "ERROR: " << e.what(); Logger::error(buf.str()); return buf.str(); } @@ -444,8 +461,8 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum, myConsole->initializeAudio(); string saveOnExit = settings().getString("saveonexit"); - bool activeTM = settings().getBool( - settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine"); + bool devSettings = settings().getBool("dev.settings"); + bool activeTM = settings().getBool(devSettings ? "dev.timemachine" : "plr.timemachine"); if (saveOnExit == "all" && activeTM) myEventHandler->handleEvent(Event::LoadAllStates); @@ -460,8 +477,11 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum, myConsole->cartridge().detectedType() + ", loading ROM" + id); } buf << "Game console created:" << endl - << " ROM file: " << myRomFile.getShortPath() << endl << endl - << getROMInfo(*myConsole); + << " ROM file: " << myRomFile.getShortPath() << endl; + FilesystemNode propsFile(myRomFile.getPathWithExt(".pro")); + if(propsFile.exists()) + buf << " PRO file: " << propsFile.getShortPath() << endl; + buf << endl << getROMInfo(*myConsole); Logger::info(buf.str()); myFrameBuffer->setCursorState(); @@ -473,13 +493,27 @@ string OSystem::createConsole(const FilesystemNode& rom, const string& md5sum, if(mySettings->getBool("debug")) myEventHandler->enterDebugMode(); #endif + + if(!showmessage && + settings().getBool(devSettings ? "dev.detectedinfo" : "plr.detectedinfo")) + { + ostringstream msg; + + msg << myConsole->leftController().name() << "/" << myConsole->rightController().name() + << " - " << myConsole->cartridge().detectedType() + << " - " << myConsole->getFormatString(); + myFrameBuffer->showMessage(msg.str()); + } } + return EmptyString; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool OSystem::reloadConsole() +bool OSystem::reloadConsole(bool nextrom) { + mySettings->setValue("romloadprev", !nextrom); + return createConsole(myRomFile, myRomMD5, false) == EmptyString; } @@ -573,7 +607,7 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& string cartmd5 = md5; const string& type = props.get(PropType::Cart_Type); unique_ptr cart = - CartDetector::create(romfile, image, size, cartmd5, type, *mySettings); + CartCreator::create(romfile, image, size, cartmd5, type, *mySettings); // Some properties may not have a name set; we can't leave it blank if(props.get(PropType::Cart_Name) == EmptyString) @@ -610,6 +644,8 @@ unique_ptr OSystem::openConsole(const FilesystemNode& romfile, string& CMDLINE_PROPS_UPDATE("vcenter", PropType::Display_VCenter); CMDLINE_PROPS_UPDATE("pp", PropType::Display_Phosphor); CMDLINE_PROPS_UPDATE("ppblend", PropType::Display_PPBlend); + CMDLINE_PROPS_UPDATE("pxcenter", PropType::Controller_PaddlesXCenter); + CMDLINE_PROPS_UPDATE("pycenter", PropType::Controller_PaddlesYCenter); // Finally, create the cart with the correct properties if(cart) @@ -650,11 +686,8 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size if(md5 == "") md5 = MD5::hash(image, size); - // Some games may not have a name, since there may not - // be an entry in stella.pro. In that case, we use the rom name - // and reinsert the properties object - Properties props; - myPropSet->getMD5WithInsert(rom, md5, props); + // Make sure to load a per-ROM properties entry, if one exists + myPropSet->loadPerROM(rom, md5); return image; } @@ -823,7 +856,7 @@ shared_ptr OSystem::createSettingsRepository() ? shared_ptr(mySettingsDb, &mySettingsDb->settingsRepository()) : make_shared(); #else - if (myConfigFile.empty()) + if (myConfigFile.getPath() == EmptyString) return make_shared(); return make_shared(myConfigFile); diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index 876824231..f335055f4 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -43,7 +43,7 @@ class AudioSettings; class Menu; class MessageMenu; class TimeMachine; - class VideoDialog; + class VideoAudioDialog; #endif #ifdef PNG_SUPPORT class PNGLibrary; @@ -264,46 +264,48 @@ class OSystem void setConfigPaths(); /** - Return the default full/complete directory name for storing data. + Return the default full/complete path name for storing data. */ - const string& baseDir() const { return myBaseDir; } + const FilesystemNode& baseDir() const { return myBaseDir; } /** - Return the full/complete directory name for storing state files. + Return the full/complete path name for storing state files. */ - const string& stateDir() const { return myStateDir; } + const FilesystemNode& stateDir() const { return myStateDir; } /** - Return the full/complete directory name for storing nvram + Return the full/complete path name for storing nvram (flash/EEPROM) files. */ - const string& nvramDir() const { return myNVRamDir; } + const FilesystemNode& nvramDir() const { return myNVRamDir; } #ifdef CHEATCODE_SUPPORT /** - This method should be called to get the full path of the cheat file. - - @return String representing the full path of the cheat filename. + Return the full/complete path name of the cheat file. */ - const string& cheatFile() const { return myCheatFile; } + const FilesystemNode& cheatFile() const { return myCheatFile; } + #endif + + #ifdef DEBUGGER_SUPPORT + /** + Return the full/complete path name for storing Distella cfg files. + */ + const FilesystemNode& cfgDir() const { return myCfgDir; } #endif #ifdef PNG_SUPPORT /** - Return the full/complete directory name for saving and loading + Return the full/complete path name for saving and loading PNG snapshots. */ - const string& snapshotSaveDir() const { return mySnapshotSaveDir; } - const string& snapshotLoadDir() const { return mySnapshotLoadDir; } + const FilesystemNode& snapshotSaveDir() const { return mySnapshotSaveDir; } + const FilesystemNode& snapshotLoadDir() const { return mySnapshotLoadDir; } #endif /** - This method should be called to get the full path of the - (optional) palette file. - - @return String representing the full path of the properties filename. + Return the full/complete path name of the (optional) palette file. */ - const string& paletteFile() const { return myPaletteFile; } + const FilesystemNode& paletteFile() const { return myPaletteFile; } /** Checks if a valid a user-defined palette file exists. @@ -311,10 +313,7 @@ class OSystem bool checkUserPalette(bool outputError = false) const; /** - This method should be called to get the full path of the currently - loaded ROM. - - @return FSNode object representing the ROM file. + Return the full/complete path name of the currently loaded ROM. */ const FilesystemNode& romFile() const { return myRomFile; } @@ -322,8 +321,8 @@ class OSystem The default locations for saving and loading various files that don't already have a specific location. */ - const string& defaultSaveDir() const { return myDefaultSaveDir; } - const string& defaultLoadDir() const { return myDefaultLoadDir; } + const FilesystemNode& defaultSaveDir() const { return myDefaultSaveDir; } + const FilesystemNode& defaultLoadDir() const { return myDefaultLoadDir; } /** Open the given ROM and return an array containing its contents. @@ -356,9 +355,11 @@ class OSystem Reloads the current console (essentially deletes and re-creates it). This can be thought of as a real console off/on toggle. + @param nextrom If true select next multicart ROM, else previous one + @return True on successful creation, otherwise false */ - bool reloadConsole(); + bool reloadConsole(bool nextrom = true); /** Creates a new ROM launcher, to select a new ROM to emulate. @@ -550,21 +551,10 @@ class OSystem bool myQuitLoop{false}; private: - string myBaseDir; - string myStateDir; - string mySnapshotSaveDir; - string mySnapshotLoadDir; - string myNVRamDir; - string myDefaultSaveDir; - string myDefaultLoadDir; - - string myCheatFile; - string myConfigFile; - string myPaletteFile; - string myPropertiesFile; - - FilesystemNode myRomFile; - string myRomMD5; + FilesystemNode myBaseDir, myStateDir, mySnapshotSaveDir, mySnapshotLoadDir, + myNVRamDir, myCfgDir, myDefaultSaveDir, myDefaultLoadDir; + FilesystemNode myCheatFile, myConfigFile, myPaletteFile, myPropertiesFile; + FilesystemNode myRomFile; string myRomMD5; string myFeatures; string myBuildInfo; diff --git a/src/emucore/Paddles.cxx b/src/emucore/Paddles.cxx index d8e60365a..a7f72ce1d 100644 --- a/src/emucore/Paddles.cxx +++ b/src/emucore/Paddles.cxx @@ -186,8 +186,8 @@ void Paddles::update() setPin(DigitalPin::Four, true); // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::Three, myEvent.get(myP1FireEvent) == 0); - setPin(DigitalPin::Four, myEvent.get(myP0FireEvent) == 0); + bool firePressedP0 = myEvent.get(myP0FireEvent) != 0; + bool firePressedP1 = myEvent.get(myP1FireEvent) != 0; // Paddle movement is a very difficult thing to accurately emulate, // since it originally came from an analog device that had very @@ -234,12 +234,14 @@ void Paddles::update() new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter; // only use new dejittered value for larger differences - if (abs(new_val - sa_xaxis) > 10) + if(abs(new_val - sa_xaxis) > 10) sa_xaxis = new_val; - setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0))); + setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * + (BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + XCENTER), 0, 65536) / 65536.0))); sa_changed = true; } + if(abs(myLastAxisY - sa_yaxis) > 10) { // dejitter, suppress small changes only @@ -250,7 +252,8 @@ void Paddles::update() if (abs(new_val - sa_yaxis) > 10) sa_yaxis = new_val; - setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0))); + setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * + (BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + YCENTER), 0, 65536) / 65536.0))); sa_changed = true; } myLastAxisX = sa_xaxis; @@ -266,9 +269,14 @@ void Paddles::update() myCharge[myMPaddleID] = BSPF::clamp(myCharge[myMPaddleID] - (myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(ourButtonPin[myMPaddleID], false); + if(myMPaddleID == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } else { @@ -279,18 +287,30 @@ void Paddles::update() myCharge[myMPaddleIDX] = BSPF::clamp(myCharge[myMPaddleIDX] - (myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(ourButtonPin[myMPaddleIDX], false); + + if(myMPaddleIDX == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonLeftValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonLeftValue); } if(myMPaddleIDY > -1) { myCharge[myMPaddleIDY] = BSPF::clamp(myCharge[myMPaddleIDY] - (myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonRightValue)) - setPin(ourButtonPin[myMPaddleIDY], false); + + if(myMPaddleIDY == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonRightValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonRightValue); } } + setPin(DigitalPin::Four, !getAutoFireState(firePressedP0)); + setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedP1)); // Finally, consider digital input, where movement happens // until a digital event is released @@ -379,6 +399,30 @@ bool Paddles::setMouseControl( return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Paddles::setAnalogXCenter(int xcenter) +{ + // convert into ~5 pixel steps + XCENTER = BSPF::clamp(xcenter, MIN_ANALOG_CENTER, MAX_ANALOG_CENTER) * 860; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Paddles::setAnalogYCenter(int ycenter) +{ + // convert into ~5 pixel steps + YCENTER = BSPF::clamp(ycenter, MIN_ANALOG_CENTER, MAX_ANALOG_CENTER) * 860; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float Paddles::setAnalogSensitivity(int sensitivity) +{ + // BASE_ANALOG_SENSE * (1.1 ^ 20) = 1.0 + SENSITIVITY = BASE_ANALOG_SENSE * std::pow(1.1F, + static_cast(BSPF::clamp(sensitivity, 0, MAX_ANALOG_SENSE))); + + return SENSITIVITY; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Paddles::setDejitterBase(int strength) { @@ -405,21 +449,20 @@ void Paddles::setMouseSensitivity(int sensitivity) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Paddles::setPaddleRange(int range) +void Paddles::setDigitalPaddleRange(int range) { range = BSPF::clamp(range, 1, 100); TRIGRANGE = int(TRIGMAX * (range / 100.0)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int Paddles::XCENTER = 0; +int Paddles::YCENTER = 0; +float Paddles::SENSITIVITY = 1.0; + int Paddles::TRIGRANGE = Paddles::TRIGMAX; int Paddles::DIGITAL_SENSITIVITY = -1; int Paddles::DIGITAL_DISTANCE = -1; int Paddles::MOUSE_SENSITIVITY = -1; int Paddles::DEJITTER_BASE = 0; int Paddles::DEJITTER_DIFF = 0; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const std::array Paddles::ourButtonPin = { - DigitalPin::Four, DigitalPin::Three -}; diff --git a/src/emucore/Paddles.hxx b/src/emucore/Paddles.hxx index 2f64a4df2..bb8144b21 100644 --- a/src/emucore/Paddles.hxx +++ b/src/emucore/Paddles.hxx @@ -48,6 +48,10 @@ class Paddles : public Controller virtual ~Paddles() = default; public: + static constexpr float BASE_ANALOG_SENSE = 0.148643628F; + static constexpr int MAX_ANALOG_SENSE = 30; + static constexpr int MIN_ANALOG_CENTER = -10; + static constexpr int MAX_ANALOG_CENTER = 30; static constexpr int MAX_DIGITAL_SENSE = 20; static constexpr int MAX_MOUSE_SENSE = 20; static constexpr int MIN_DEJITTER = 0; @@ -88,6 +92,28 @@ class Paddles : public Controller bool setMouseControl(Controller::Type xtype, int xid, Controller::Type ytype, int yid) override; + /** + Sets the x-center for analog paddles. + + @param xcenter Value from -10 to 30, representing the center offset/860 + */ + static void setAnalogXCenter(int xcenter); + + /** + Sets the y-center for analog paddles. + + @param ycenter Value from -10 to 30, representing the center offset/860 + */ + static void setAnalogYCenter(int ycenter); + + /** + Sets the sensitivity for analog paddles. + + @param sensitivity Value from 0 to 30, where 20 equals 1 + @return Resulting sensitivity + */ + static float setAnalogSensitivity(int sensitivity); + /** @param strength Value from 0 to 10 */ @@ -127,7 +153,7 @@ class Paddles : public Controller @param range Value from 1 to 100, representing the percentage of the range to use */ - static void setPaddleRange(int range); + static void setDigitalPaddleRange(int range); static constexpr double MAX_RESISTANCE = 1400000.0; @@ -156,14 +182,14 @@ class Paddles : public Controller int myLastAxisX{0}, myLastAxisY{0}; int myAxisDigitalZero{0}, myAxisDigitalOne{0}; + static int XCENTER; + static int YCENTER; + static float SENSITIVITY; + static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; static int DEJITTER_BASE, DEJITTER_DIFF; static int MOUSE_SENSITIVITY; - // Lookup table for associating paddle buttons with controller pins - // Yes, this is hideously complex - static const std::array ourButtonPin; - private: // Following constructors and assignment operators not supported Paddles() = delete; diff --git a/src/emucore/PointingDevice.cxx b/src/emucore/PointingDevice.cxx index 1a2c781b4..05cf7c031 100644 --- a/src/emucore/PointingDevice.cxx +++ b/src/emucore/PointingDevice.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include + #include "Control.hxx" #include "Event.hxx" #include "System.hxx" @@ -90,9 +92,8 @@ void PointingDevice::update() setPin(DigitalPin::Six, myEvent.get(Event::JoystickZeroFire) == 0); // We allow left and right mouse buttons for fire button - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + setPin(DigitalPin::Six, !getAutoFireState( + myEvent.get(Event::MouseButtonLeftValue) || myEvent.get(Event::MouseButtonRightValue))); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/PointingDevice.hxx b/src/emucore/PointingDevice.hxx index 4f0a007b5..11b9fcd2d 100644 --- a/src/emucore/PointingDevice.hxx +++ b/src/emucore/PointingDevice.hxx @@ -18,7 +18,6 @@ #ifndef POINTING_DEVICE_HXX #define POINTING_DEVICE_HXX -class Controller; class Event; #include "Control.hxx" diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx index f561dc7a1..877d35934 100644 --- a/src/emucore/ProfilingRunner.cxx +++ b/src/emucore/ProfilingRunner.cxx @@ -20,8 +20,8 @@ #include "ProfilingRunner.hxx" #include "FSNode.hxx" -#include "CartDetector.hxx" #include "Cart.hxx" +#include "CartCreator.hxx" #include "MD5.hxx" #include "Control.hxx" #include "M6502.hxx" @@ -54,7 +54,6 @@ namespace { } } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ProfilingRunner::ProfilingRunner(int argc, char* argv[]) : profilingRuns(std::max(argc - 2, 0)) @@ -110,7 +109,8 @@ bool ProfilingRunner::runOne(const ProfilingRun& run) string md5 = MD5::hash(image, size); string type = ""; - unique_ptr cartridge = CartDetector::create(imageFile, image, size, md5, type, mySettings); + unique_ptr cartridge = CartCreator::create( + imageFile, image, size, md5, type, mySettings); if (!cartridge) { cout << "ERROR: unable to determine cartridge type" << endl; diff --git a/src/emucore/ProfilingRunner.hxx b/src/emucore/ProfilingRunner.hxx index 1194cfdda..a3523b98f 100644 --- a/src/emucore/ProfilingRunner.hxx +++ b/src/emucore/ProfilingRunner.hxx @@ -18,10 +18,9 @@ #ifndef PROFILING_RUNNER #define PROFILING_RUNNER -class Control; -class Switches; - #include "bspf.hxx" +#include "Control.hxx" +#include "Switches.hxx" #include "Settings.hxx" #include "ConsoleIO.hxx" #include "Props.hxx" @@ -41,13 +40,13 @@ class ProfilingRunner { }; struct IO: public ConsoleIO { - Controller& leftController() const override { return *myLeftControl; } - Controller& rightController() const override { return *myRightControl; } - Switches& switches() const override { return *mySwitches; } + Controller& leftController() const override { return *myLeftControl; } + Controller& rightController() const override { return *myRightControl; } + Switches& switches() const override { return *mySwitches; } - unique_ptr myLeftControl; - unique_ptr myRightControl; - unique_ptr mySwitches; + unique_ptr myLeftControl; + unique_ptr myRightControl; + unique_ptr mySwitches; }; private: diff --git a/src/emucore/Props.cxx b/src/emucore/Props.cxx index efe3ec9e6..995e004a0 100644 --- a/src/emucore/Props.cxx +++ b/src/emucore/Props.cxx @@ -253,6 +253,8 @@ void Properties::print() const << get(PropType::Controller_Left) << "|" << get(PropType::Controller_Right) << "|" << get(PropType::Controller_SwapPaddles) << "|" + << get(PropType::Controller_PaddlesXCenter) << "|" + << get(PropType::Controller_PaddlesYCenter) << "|" << get(PropType::Controller_MouseAxis) << "|" << get(PropType::Display_Format) << "|" << get(PropType::Display_VCenter) << "|" @@ -309,6 +311,8 @@ void Properties::printHeader() << "Controller_Left|" << "Controller_Right|" << "Controller_SwapPaddles|" + << "Controller_PaddlesXCenter|" + << "Controller_PaddlesYCenter|" << "Controller_MouseAxis|" << "Display_Format|" << "Display_VCenter|" @@ -339,6 +343,8 @@ std::array Properties::ourDefaultProperties = "AUTO", // Controller.Left "AUTO", // Controller.Right "NO", // Controller.SwapPaddles + "0", // Controller.PaddlesXCenter + "0", // Controller.PaddlesYCenter "AUTO", // Controller.MouseAxis "AUTO", // Display.Format "0", // Display.VCenter @@ -368,6 +374,8 @@ std::array Properties::ourPropertyNames = "Controller.Left", "Controller.Right", "Controller.SwapPaddles", + "Controller.PaddlesXCenter", + "Controller.PaddlesYCenter", "Controller.MouseAxis", "Display.Format", "Display.VCenter", diff --git a/src/emucore/Props.hxx b/src/emucore/Props.hxx index 38c3cc1c9..d73f38bdf 100644 --- a/src/emucore/Props.hxx +++ b/src/emucore/Props.hxx @@ -37,6 +37,8 @@ enum class PropType : uInt8 { Controller_Left, Controller_Right, Controller_SwapPaddles, + Controller_PaddlesXCenter, + Controller_PaddlesYCenter, Controller_MouseAxis, Display_Format, Display_VCenter, diff --git a/src/emucore/PropsSet.cxx b/src/emucore/PropsSet.cxx index 5375a269e..db6cfc1fe 100644 --- a/src/emucore/PropsSet.cxx +++ b/src/emucore/PropsSet.cxx @@ -19,37 +19,55 @@ #include "bspf.hxx" #include "FSNode.hxx" +#include "Logger.hxx" #include "DefProps.hxx" #include "Props.hxx" #include "PropsSet.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PropertiesSet::load(const string& filename) +void PropertiesSet::load(const FilesystemNode& file, bool save) { - ifstream in(filename); - - Properties prop; - while(in >> prop) - insert(prop); + try + { + stringstream in; + if(file.exists() && file.read(in) > 0) + { + Properties prop; + while(in >> prop) + insert(prop, save); + } + } + catch(...) + { + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool PropertiesSet::save(const string& filename) const +bool PropertiesSet::save(const FilesystemNode& file) const { - // Only save properties when it won't create an empty file - FilesystemNode props(filename); - if(!props.exists() && myExternalProps.size() == 0) - return false; + try + { + // Only save properties when it won't create an empty file + if(!file.exists() && myExternalProps.size() == 0) + return false; - ofstream out(filename); - if(!out) - return false; + // Only save those entries in the external list + stringstream out; + for(const auto& i: myExternalProps) + out << i.second; - // Only save those entries in the external list - for(const auto& i: myExternalProps) - out << i.second; + file.write(out); + return true; + } + catch(const runtime_error& e) + { + Logger::error(e.what()); + } + catch(...) + { + } - return true; + return false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -117,26 +135,6 @@ bool PropertiesSet::getMD5(const string& md5, Properties& properties, return found; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PropertiesSet::getMD5WithInsert(const FilesystemNode& rom, - const string& md5, Properties& properties) -{ - bool toInsert = false; - - if(!getMD5(md5, properties)) - { - properties.set(PropType::Cart_MD5, md5); - toInsert = true; - } - if(toInsert || properties.get(PropType::Cart_Name) == EmptyString) - { - properties.set(PropType::Cart_Name, rom.getNameWithExt("")); - toInsert = true; - } - if(toInsert) - insert(properties, false); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::insert(const Properties& properties, bool save) { @@ -176,6 +174,37 @@ void PropertiesSet::insert(const Properties& properties, bool save) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5) +{ + // Handle ROM properties, do some error checking + // Only add to the database when necessary + bool toInsert = false; + + // First, does this ROM have a per-ROM properties entry? + // If so, load it into the database + FilesystemNode propsNode(rom.getPathWithExt(".pro")); + if(propsNode.exists()) + load(propsNode, false); + + // Next, make sure we have a valid md5 and name + Properties props; + if(!getMD5(md5, props)) + { + props.set(PropType::Cart_MD5, md5); + toInsert = true; + } + if(toInsert || props.get(PropType::Cart_Name) == EmptyString) + { + props.set(PropType::Cart_Name, rom.getNameWithExt("")); + toInsert = true; + } + + // Finally, insert properties if any info was missing + if(toInsert) + insert(props, false); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PropertiesSet::print() const { diff --git a/src/emucore/PropsSet.hxx b/src/emucore/PropsSet.hxx index 684137817..387b79bda 100644 --- a/src/emucore/PropsSet.hxx +++ b/src/emucore/PropsSet.hxx @@ -42,27 +42,29 @@ class PropertiesSet /** Trivial constructor. */ - PropertiesSet() = default; + PropertiesSet() = default; /** Load properties from the specified file, and create an internal searchable list. - @param filename Full pathname of input file to use + @param file The node representing the input file to use + @param save Indicates whether the properties should be saved + when the program exits */ - void load(const string& filename); + void load(const FilesystemNode& file, bool save = true); /** Save properties to the specified file. - @param filename Full pathname of output file to use + @param file The node representing the output file to use @return True on success, false on failure or save not needed Failure occurs if file couldn't be opened for writing, or if the file doesn't exist and a zero-byte file would be created */ - bool save(const string& filename) const; + bool save(const FilesystemNode& file) const; /** Get the property from the set with the given MD5. @@ -78,19 +80,6 @@ class PropertiesSet bool getMD5(const string& md5, Properties& properties, bool useDefaults = false) const; - /** - Get the property from the set with the given MD5, at the same time - checking if it exists. If it doesn't, insert a temporary copy into - the set. - - @param rom The ROM file used to calculate the MD5 - @param md5 The md5 of the property to get - @param properties The properties with the given MD5, or the default - properties if not found - */ - void getMD5WithInsert(const FilesystemNode& rom, const string& md5, - Properties& properties); - /** Insert the properties into the set. If a duplicate is inserted the old properties are overwritten with the new ones. @@ -101,6 +90,21 @@ class PropertiesSet */ void insert(const Properties& properties, bool save = true); + /** + Load properties for a specific ROM from a per-ROM properties file, + if it exists. In any event, also do some error checking, like making + sure that the properties have a valid name, etc. + + NOTE: This method is meant to be called only when starting Stella + and loading a ROM for the first time. Currently, that means + only from the ROM launcher or when actually opening the ROM. + *** FOR ALL OTHER CASES, USE getMD5() *** + + @param rom The node representing the rom file + @param md5 The md5 of the property to get + */ + void loadPerROM(const FilesystemNode& rom, const string& md5); + /** Prints the contents of the PropertiesSet as a flat file. */ diff --git a/src/emucore/SaveKey.cxx b/src/emucore/SaveKey.cxx index b0ca56f89..dcab2b8b3 100644 --- a/src/emucore/SaveKey.cxx +++ b/src/emucore/SaveKey.cxx @@ -22,7 +22,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SaveKey::SaveKey(Jack jack, const Event& event, const System& system, - const string& eepromfile, const onMessageCallback& callback, + const FilesystemNode& eepromfile, const onMessageCallback& callback, Type type) : Controller(jack, event, system, type), myEEPROM(make_unique(eepromfile, system, callback)) @@ -33,7 +33,7 @@ SaveKey::SaveKey(Jack jack, const Event& event, const System& system, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SaveKey::SaveKey(Jack jack, const Event& event, const System& system, - const string& eepromfile, const onMessageCallback& callback) + const FilesystemNode& eepromfile, const onMessageCallback& callback) : SaveKey(jack, event, system, eepromfile, callback, Controller::Type::SaveKey) { } diff --git a/src/emucore/SaveKey.hxx b/src/emucore/SaveKey.hxx index 70ea96e5e..ce5c3e347 100644 --- a/src/emucore/SaveKey.hxx +++ b/src/emucore/SaveKey.hxx @@ -20,6 +20,7 @@ class MT24LC256; class OSystem; +class FilesystemNode; #include "Control.hxx" @@ -45,7 +46,7 @@ class SaveKey : public Controller @param callback Called to pass messages back to the parent controller */ SaveKey(Jack jack, const Event& event, const System& system, - const string& eepromfile, const onMessageCallback& callback); + const FilesystemNode& eepromfile, const onMessageCallback& callback); virtual ~SaveKey(); protected: @@ -54,7 +55,8 @@ class SaveKey : public Controller that inherit from SaveKey (currently, AtariVox) */ SaveKey(Jack jack, const Event& event, const System& system, - const string& eepromfile, const onMessageCallback& callback, Type type); + const FilesystemNode& eepromfile, + const onMessageCallback& callback, Type type); public: using Controller::read; diff --git a/src/emucore/SerialPort.hxx b/src/emucore/SerialPort.hxx index aa08acbe8..f2ac5bf68 100644 --- a/src/emucore/SerialPort.hxx +++ b/src/emucore/SerialPort.hxx @@ -58,6 +58,14 @@ class SerialPort */ virtual bool writeByte(uInt8 data) { return false; } + /** + Test for 'Clear To Send' enabled. By default, assume it's always + OK to send more data. + + @return True if CTS signal enabled, else false + */ + virtual bool isCTS() { return true; } + private: // Following constructors and assignment operators not supported SerialPort(const SerialPort&) = delete; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 21e0b7c52..f043d9f32 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -21,6 +21,8 @@ #include "Version.hxx" #include "Logger.hxx" #include "AudioSettings.hxx" +#include "PaletteHandler.hxx" +#include "Paddles.hxx" #ifdef DEBUGGER_SUPPORT #include "DebuggerDialog.hxx" @@ -36,6 +38,7 @@ Settings::Settings() // If no version is recorded with the persisted settings, we set it to zero setPermanent(SETTINGS_VERSION_KEY, 0); + setPermanent("stella.version", "6.2.1"); // Video-related options setPermanent("video", ""); @@ -44,29 +47,31 @@ Settings::Settings() setPermanent("center", "true"); setPermanent("windowedpos", Common::Point(50, 50)); setPermanent("display", 0); - setPermanent("palette", "standard"); setPermanent("uimessages", "true"); - // TIA specific options - setPermanent("tia.zoom", "3"); setPermanent("tia.inter", "false"); - setPermanent("tia.vsizeadjust", 0); + setPermanent("tia.zoom", "3"); setPermanent("fullscreen", "false"); setPermanent("tia.fs_stretch", "false"); + setPermanent("tia.fs_refresh", "false"); setPermanent("tia.fs_overscan", "0"); + setPermanent("tia.vsizeadjust", 0); setPermanent("tia.dbgcolors", "roygpb"); - + // Palette options + setPermanent("palette", PaletteHandler::SETTING_STANDARD); + setPermanent("pal.phase_ntsc", "26.2"); + setPermanent("pal.phase_pal", "31.3"); + setPermanent("pal.contrast", "0.0"); + setPermanent("pal.brightness", "0.0"); + setPermanent("pal.hue", "0.0"); + setPermanent("pal.saturation", "0.0"); + setPermanent("pal.gamma", "0.0"); // TV filtering options setPermanent("tv.filter", "0"); setPermanent("tv.phosphor", "byrom"); setPermanent("tv.phosblend", "50"); - setPermanent("tv.scanlines", "25"); + setPermanent("tv.scanlines", "0"); // TV options when using 'custom' mode - setPermanent("tv.contrast", "0.0"); - setPermanent("tv.brightness", "0.0"); - setPermanent("tv.hue", "0.0"); - setPermanent("tv.saturation", "0.0"); - setPermanent("tv.gamma", "0.0"); setPermanent("tv.sharpness", "0.0"); setPermanent("tv.resolution", "0.0"); setPermanent("tv.artifacts", "0.0"); @@ -76,6 +81,7 @@ Settings::Settings() // Sound options setPermanent(AudioSettings::SETTING_ENABLED, AudioSettings::DEFAULT_ENABLED); setPermanent(AudioSettings::SETTING_VOLUME, AudioSettings::DEFAULT_VOLUME); + setPermanent(AudioSettings::SETTING_DEVICE, AudioSettings::DEFAULT_DEVICE); setPermanent(AudioSettings::SETTING_PRESET, static_cast(AudioSettings::DEFAULT_PRESET)); setPermanent(AudioSettings::SETTING_FRAGMENT_SIZE, AudioSettings::DEFAULT_FRAGMENT_SIZE); setPermanent(AudioSettings::SETTING_SAMPLE_RATE, AudioSettings::DEFAULT_SAMPLE_RATE); @@ -96,14 +102,17 @@ Settings::Settings() setPermanent("combomap", ""); setPermanent("joydeadzone", "13"); setPermanent("joyallow4", "false"); + setPermanent("autofirerate", "0"); setPermanent("usemouse", "analog"); setPermanent("grabmouse", "true"); setPermanent("cursor", "2"); setPermanent("dejitter.base", "0"); setPermanent("dejitter.diff", "0"); setPermanent("dsense", "10"); + setPermanent("psense", "20"); setPermanent("msense", "10"); setPermanent("tsense", "10"); + setPermanent("dcsense", "10"); setPermanent("saport", "lr"); setPermanent("modcombo", "true"); @@ -122,6 +131,9 @@ Settings::Settings() // ROM browser options setPermanent("exitlauncher", "false"); + setPermanent("followlauncher", "false"); + setPermanent("launcherpos", Common::Point(50, 50)); + setPermanent("launcherdisplay", 0); setPermanent("launcherres", Common::Size(900, 600)); setPermanent("launcherfont", "medium"); setPermanent("launcherroms", "true"); @@ -133,6 +145,8 @@ Settings::Settings() setPermanent("dbg.res", Common::Size(DebuggerDialog::kMediumFontMinW, DebuggerDialog::kMediumFontMinH)); + setPermanent("dbg.pos", Common::Point(50, 50)); + setPermanent("dbg.display", 0); #endif setPermanent("uipalette", "standard"); setPermanent("hidpi", "false"); @@ -142,6 +156,7 @@ Settings::Settings() setPermanent("ctrldelay", "400"); setPermanent("ctrlrate", "20"); setPermanent("basic_settings", false); + setPermanent("dialogfont", "medium"); setPermanent("dialogpos", 0); setPermanent("confirmexit", false); @@ -154,6 +169,7 @@ Settings::Settings() setTemporary("romloadcount", "0"); setTemporary("maxres", ""); setPermanent("initials", ""); + setTemporary("turbo", "0"); #ifdef DEBUGGER_SUPPORT // Debugger/disassembly options @@ -184,6 +200,7 @@ Settings::Settings() setPermanent("plr.tm.uncompressed", 60); setPermanent("plr.tm.interval", "30f"); // = 0.5 seconds setPermanent("plr.tm.horizon", "10m"); // = ~10 minutes + setPermanent("plr.detectedinfo", "false"); setPermanent("plr.eepromaccess", "false"); // Developer settings @@ -213,6 +230,7 @@ Settings::Settings() setPermanent("dev.tm.horizon", "30s"); // = ~30 seconds // Thumb ARM emulation options setPermanent("dev.thumb.trapfatal", "true"); + setPermanent("dev.detectedinfo", "true"); setPermanent("dev.eepromaccess", "true"); } @@ -322,6 +340,10 @@ void Settings::validate() if(i < 0 || i > 3) setValue("cursor", "2"); + i = getInt("psense"); + if(i < 0|| i > Paddles::MAX_ANALOG_SENSE) + setValue("psense", "20"); + i = getInt("dsense"); if(i < 1 || i > 20) setValue("dsense", "10"); @@ -334,16 +356,24 @@ void Settings::validate() if(i < 1 || i > 20) setValue("tsense", "10"); + i = getInt("dcsense"); + if(i < 1 || i > 20) + setValue("dcsense", "10"); + i = getInt("ssinterval"); if(i < 1) setValue("ssinterval", "2"); else if(i > 10) setValue("ssinterval", "10"); s = getString("palette"); - if(s != "standard" && s != "z26" && s != "user") - setValue("palette", "standard"); + if(s != PaletteHandler::SETTING_STANDARD + && s != PaletteHandler::SETTING_Z26 + && s != PaletteHandler::SETTING_USER + && s != PaletteHandler::SETTING_CUSTOM) + setValue("palette", PaletteHandler::SETTING_STANDARD); s = getString("launcherfont"); - if(s != "small" && s != "medium" && s != "large") + if(s != "small" && s != "low_medium" && s != "medium" && s != "large" + && s != "large12" && s != "large14" && s != "large16") setValue("launcherfont", "medium"); s = getString("dbg.fontsize"); @@ -351,8 +381,7 @@ void Settings::validate() setValue("dbg.fontsize", "medium"); i = getInt("romviewer"); - if(i < 0) setValue("romviewer", "0"); - else if(i > 2) setValue("romviewer", "2"); + if(i < 0) setValue("romviewer", "0"); i = getInt("loglevel"); if(i < int(Logger::Level::MIN) || i > int(Logger::Level::MAX)) @@ -383,17 +412,26 @@ void Settings::usage() const << " -vsync <1|0> Enable 'synchronize to vertical blank interrupt'\n" << " -fullscreen <1|0> Enable fullscreen mode\n" << " -center <1|0> Centers game window in windowed modes\n" - << " -windowedpos Sets the window position in windowed modes\n" - << " -display Sets the display for Stella\n" + << " -windowedpos Sets the window position in windowed emulator mode\n" + << " -display Sets the display for Stella's emulator\n" << " -palette \n" + << " z26|user|\n" + << " custom>\n" + << " -pal.phase_ntsc Phase shift for NTSC 'custom' palette\n" + << " -pal.phase_pal Phase shift for PAL 'custom' palette\n" + << " -pal.hue <-1.0 - 1.0> Adjust hue for current palette\n" + << " -pal.saturation <-1.0 - 1.0> Adjust saturation of current palette\n" + << " -pal.contrast <-1.0 - 1.0> Adjust contrast of current palette\n" + << " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n" + << " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n" << " -speed Run emulation at the given speed\n" + << " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n" << " -uimessages <1|0> Show onscreen UI messages for different events\n" << endl #ifdef SOUND_SUPPORT << " -audio.enabled <1|0> Enable audio\n" << " -audio.volume <0-100> Volume\n" + << " -audio.device ID of the audio device (0 = default)\n" << " -audio.preset <1-5> Audio preset (or 1 for custom)\n" << " -audio.sample_rate Output sample rate (44100|48000|96000)\n" << " -audio.fragment_size Fragment size (128|256|512|1024|\n" @@ -411,7 +449,8 @@ void Settings::usage() const << " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA\n" << " image\n" << " -tia.fs_stretch <1|0> Stretch TIA image to fill fullscreen mode\n" - << " -tia.fs_overscan <0-10> Add overscan to TIA image in fill fullscreen mode\n" + << " -tia.fs_refresh <1|0> Try to adapt display refresh rate to game's FPS\n" + << " -tia.fs_overscan <0-10> Add overscan to TIA image in fullscreen mode\n" << " -tia.dbgcolors Debug colors to use for each object (see manual\n" << " for description)\n" << endl @@ -421,11 +460,6 @@ void Settings::usage() const << " -tv.phosblend <0-100> Set default blend level in phosphor mode\n" << " -tv.scanlines <0-100> Set scanline intensity to percentage\n" << " (0 disables completely)\n" - << " -tv.contrast <-1.0 - 1.0> Set TV effects custom contrast\n" - << " -tv.brightness <-1.0 - 1.0> Set TV effects custom brightness\n" - << " -tv.hue <-1.0 - 1.0> Set TV effects custom hue\n" - << " -tv.saturation <-1.0 - 1.0> Set TV effects custom saturation\n" - << " -tv.gamma <-1.0 - 1.0> Set TV effects custom gamma\n" << " -tv.sharpness <-1.0 - 1.0> Set TV effects custom sharpness\n" << " -tv.resolution <-1.0 - 1.0> Set TV effects custom resolution\n" << " -tv.artifacts <-1.0 - 1.0> Set TV effects custom artifacts\n" @@ -446,11 +480,15 @@ void Settings::usage() const << " properties in given mode(see manual)\n" << " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n" << " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n" - << " -dejitter.base <0-10> Strength of paddle value averaging\n" - << " -dejitter.diff <0-10> Strength of paddle reaction to fast movements\n" + << " -dejitter.base <0-10> Strength of analog paddle value averaging\n" + << " -dejitter.diff <0-10> Strength of analog paddle reaction to fast movements\n" + << " -psense <0-30> Sensitivity of analog paddle movement\n" << " -dsense <1-20> Sensitivity of digital emulated paddle movement\n" << " -msense <1-20> Sensitivity of mouse emulated paddle movement\n" << " -tsense <1-20> Sensitivity of mouse emulated trackball movement\n" + << " -dcsense <1-20> Sensitivity of digital emulated driving controller\n" + << " movement\n" + << " -autofirerate <0-30> Set fire button's autofire rate (0 means off)\n" << " -saport How to assign virtual ports to multiple\n" << " Stelladaptor/2600-daptors\n" << " -modcombo <1|0> Enable modifer key combos\n" @@ -468,27 +506,40 @@ void Settings::usage() const << " -ssinterval Number of seconds between snapshots in\n" << " continuous snapshot mode\n" << endl - << " -saveonexit \n" + << " -saveonexit emulation\n" << " -autoslot <1|0> Automatically change to next save slot when\n" << " state saving\n" << endl << " -rominfo Display detailed information for the given ROM\n" << " -listrominfo Display contents of stella.pro, one line per ROM\n" << " entry\n" - << " \n" + << endl << " -exitlauncher <1|0> On exiting a ROM, go back to the ROM launcher\n" + << " -launcherpos Sets the window position in windowed EOM launcher mode\n" + << " -launcherdisplay Sets the display for the ROM launcher\n" << " -launcherres The resolution to use in ROM launcher mode\n" - << " -launcherfont \n" + << " -launcherfont \n" << " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n" - << " -romviewer <0|1|2> Show ROM info viewer at given zoom level in ROM\n" - << " launcher (0 for off)\n" - << " -lastrom Last played ROM, automatically selected in launcher\n" + << " -romviewer Show ROM info viewer at given zoom level in ROM\n" + << " launcher (use 0 for off)\n" + << " -followlauncher <0|1> Default ROM path follows launcher navigation\n" + << " -lastrom Last played ROM, automatically selected in\n" + << " launcher\n" << " -romloadcount Number of ROM to load next from multicard\n" << " -uipalette \n" + << " classic|\n" + << " light|dark>\n" << " -hidpi <0|1> Enable HiDPI mode\n" + << " -dialogfont \n" << " -dialogpos <0..4> Display all dialogs at given positions\n" << " -confirmexit <0|1> Display a confirm dialog when exiting emulation\n" << " -listdelay Time to wait between keypresses in list widgets\n" @@ -497,9 +548,11 @@ void Settings::usage() const << " UI\n" << " -mdouble Mouse double click speed in UI\n" << " -ctrldelay Delay before controller input is repeated in UI\n" - << " -ctrlrate Rate per second of repeated controller input in UI\n" + << " -ctrlrate Rate per second of repeated controller input in\n" + << " UI\n" << " -basic_settings <0|1> Display only a basic settings dialog\n" - << " -romdir Set the directory where the ROM launcher will start\n" + << " -romdir Set the directory where the ROM launcher will\n" + << " start\n" << " -avoxport The name of the serial port where an AtariVox is\n" << " connected\n" << " -holdreset Start the emulator with the Game Reset switch\n" @@ -522,12 +575,14 @@ void Settings::usage() const << " Arguments are more fully explained in the manual\n" << endl << " -dis.resolve <1|0> Attempt to resolve code sections in disassembler\n" - << " -dis.gfxformat <2|16> Set base to use for displaying GFX sections in\n" - << " disassembler\n" + << " -dis.gfxformat <2|16> Set base to use for displaying (P)GFX sections\n" + << " in disassembler\n" << " -dis.showaddr <1|0> Show opcode addresses in disassembler\n" << " -dis.relocate <1|0> Relocate calls out of address range in\n" << " disassembler\n" << endl + << " -dbg.pos Sets the window position in windowed debugger mode\n" + << " -dbg.display Sets the display for the debugger\n" << " -dbg.res The resolution to use in debugger mode\n" << " -dbg.fontsize \n" @@ -550,6 +605,8 @@ void Settings::usage() const << " -rc Sets the 'Controller.Right' property\n" << " -bc Same as using both -lc and -rc\n" << " -cp Sets the 'Controller.SwapPaddles' property\n" + << " -pxcenter Sets the 'Controller.PaddlesXCenter' property\n" + << " -pycenter Sets the 'Controller.PaddlesYCenter' property\n" << " -format Sets the 'Display.Format' property\n" << " -vcenter Sets the 'Display.vcenter' property\n" << " -pp Sets the 'Display.Phosphor' property\n" @@ -563,6 +620,7 @@ void Settings::usage() const << " mode\n" << endl << " -plr.stats <1|0> Overlay console info during emulation\n" + << " -plr.detectedinfo <1|0> Enable initial detected settings info\n" << " -plr.console <2600|7800> Select console for B/W and Pause key\n" << " handling and RAM initialization\n" << " -plr.bankrandom <1|0> Randomize the startup bank on reset\n" @@ -578,6 +636,7 @@ void Settings::usage() const << endl << " The same parameters but for developer settings mode\n" << " -dev.stats <1|0> Overlay console info during emulation\n" + << " -dev.detectedinfo <1|0> Enable initial detected settings info\n" << " -dev.console <2600|7800> Select console for B/W and Pause key\n" << " handling and RAM initialization\n" << " -dev.bankrandom <1|0> Randomize the startup bank on reset\n" diff --git a/src/emucore/Sound.hxx b/src/emucore/Sound.hxx index f74705489..880c47f00 100644 --- a/src/emucore/Sound.hxx +++ b/src/emucore/Sound.hxx @@ -88,20 +88,37 @@ class Sound /** Adjusts the volume of the sound device based on the given direction. - @param direction Increase or decrease the current volume by a predefined - amount based on the direction (1 = increase, -1 =decrease) + @param direction +1 indicates increase, -1 indicates decrease. */ - virtual void adjustVolume(Int8 direction) = 0; + virtual void adjustVolume(int direction = 1) = 0; /** This method is called to provide information about the sound device. */ virtual string about() const = 0; + /** + Get the supported devices for the audio hardware. + + @return An array of supported devices + */ + const VariantList& supportedDevices() const {return myDevices;} + + protected: + /** + This method is called to query the audio devices. + + @param devices List of device names + */ + virtual void queryHardware(VariantList& devices) = 0; + protected: // The OSystem for this sound object OSystem& myOSystem; + // Supported device + VariantList myDevices; + private: // Following constructors and assignment operators not supported Sound() = delete; diff --git a/src/emucore/Switches.hxx b/src/emucore/Switches.hxx index fb7ae4539..16c4dba74 100644 --- a/src/emucore/Switches.hxx +++ b/src/emucore/Switches.hxx @@ -22,8 +22,8 @@ class Event; class Properties; class Settings; -#include "Serializable.hxx" #include "bspf.hxx" +#include "Serializable.hxx" /** This class represents the console switches of the game console. diff --git a/src/emucore/System.cxx b/src/emucore/System.cxx index ee9392b03..28587d0ee 100644 --- a/src/emucore/System.cxx +++ b/src/emucore/System.cxx @@ -99,16 +99,24 @@ void System::clearDirtyPages() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 System::peek(uInt16 addr, uInt8 flags) +uInt8 System::peek(uInt16 addr, Device::AccessFlags flags) { const PageAccess& access = getPageAccess(addr); #ifdef DEBUGGER_SUPPORT // Set access type - if(access.codeAccessBase) - *(access.codeAccessBase + (addr & PAGE_MASK)) |= flags; + if(access.romAccessBase) + *(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR)); else access.device->setAccessFlags(addr, flags); + // Increase access counter + if(flags != Device::NONE) + { + if(access.romPeekCounter) + *(access.romPeekCounter + (addr & PAGE_MASK)) += 1; + else + access.device->increaseAccessCounter(addr); + } #endif // See if this page uses direct accessing or not @@ -127,17 +135,25 @@ uInt8 System::peek(uInt16 addr, uInt8 flags) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void System::poke(uInt16 addr, uInt8 value, uInt8 flags) +void System::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags) { uInt16 page = (addr & ADDRESS_MASK) >> PAGE_SHIFT; const PageAccess& access = myPageAccessTable[page]; #ifdef DEBUGGER_SUPPORT // Set access type - if (access.codeAccessBase) - *(access.codeAccessBase + (addr & PAGE_MASK)) |= flags; + if(access.romAccessBase) + *(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR)); else access.device->setAccessFlags(addr, flags); + // Increase access counter + if(flags != Device::NONE) + { + if(access.romPokeCounter) + *(access.romPokeCounter + (addr & PAGE_MASK)) += 1; + else + access.device->increaseAccessCounter(addr, true); + } #endif // See if this page uses direct accessing or not @@ -159,34 +175,55 @@ void System::poke(uInt16 addr, uInt8 value, uInt8 flags) myDataBusState = value; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 System::getAccessFlags(uInt16 addr) const -{ #ifdef DEBUGGER_SUPPORT +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Device::AccessFlags System::getAccessFlags(uInt16 addr) const +{ const PageAccess& access = getPageAccess(addr); - if(access.codeAccessBase) - return *(access.codeAccessBase + (addr & PAGE_MASK)); + if(access.romAccessBase) + return *(access.romAccessBase + (addr & PAGE_MASK)); else return access.device->getAccessFlags(addr); -#else - return 0; -#endif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void System::setAccessFlags(uInt16 addr, uInt8 flags) +void System::setAccessFlags(uInt16 addr, Device::AccessFlags flags) { -#ifdef DEBUGGER_SUPPORT const PageAccess& access = getPageAccess(addr); - if(access.codeAccessBase) - *(access.codeAccessBase + (addr & PAGE_MASK)) |= flags; + if(access.romAccessBase) + *(access.romAccessBase + (addr & PAGE_MASK)) |= (flags | (addr & Device::HADDR)); else access.device->setAccessFlags(addr, flags); -#endif } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void System::increaseAccessCounter(uInt16 addr, bool isWrite) +{ + const PageAccess& access = getPageAccess(addr); + + + if(isWrite) + { + if(access.romPokeCounter) + { + *(access.romPokeCounter + (addr & PAGE_MASK)) += 1; + return; + } + } + else + { + if(access.romPeekCounter) + { + *(access.romPeekCounter + (addr & PAGE_MASK)) += 1; + return; + } + } + access.device->increaseAccessCounter(addr, isWrite); +} +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool System::save(Serializer& out) const { diff --git a/src/emucore/System.hxx b/src/emucore/System.hxx index a9cf75cc2..b0660fec7 100644 --- a/src/emucore/System.hxx +++ b/src/emucore/System.hxx @@ -18,11 +18,10 @@ #ifndef SYSTEM_HXX #define SYSTEM_HXX -class Device; class M6502; class M6532; class TIA; -class NullDevice; +class Cartridge; #include "bspf.hxx" #include "Device.hxx" @@ -169,28 +168,6 @@ class System : public Serializable */ uInt8 getDataBusState() const { return myDataBusState; } - /** - Get the current state of the data bus in the system, taking into - account that certain bits are in Z-state (undriven). In those - cases, the bits are floating, but will usually be the same as the - last data bus value (the 'usually' is emulated by randomly driving - certain bits high). - - However, some CMOS EPROM chips always drive Z-state bits high. - This is emulated by hmask, which specifies to push a specific - Z-state bit high. - - @param zmask The bits which are in Z-state - @param hmask The bits which should always be driven high - @return The data bus state - */ - uInt8 getDataBusState(uInt8 zmask, uInt8 hmask = 0x00) const - { - // For the pins that are floating, randomly decide which are high or low - // Otherwise, they're specifically driven high - return (myDataBusState | (randGenerator().next() | hmask)) & zmask; - } - /** Get the byte at the specified address. No masking of the address occurs before it's sent to the device mapped at @@ -202,7 +179,7 @@ class System : public Serializable @return The byte at the specified address */ - uInt8 peek(uInt16 address, uInt8 flags = 0); + uInt8 peek(uInt16 address, Device::AccessFlags flags = Device::NONE); /** Change the byte at the specified address to the given value. @@ -217,7 +194,7 @@ class System : public Serializable @param address The address where the value should be stored @param value The value to be stored at the address */ - void poke(uInt16 address, uInt8 value, uInt8 flags = 0); + void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE); /** Lock/unlock the data bus. When the bus is locked, peek() and @@ -231,13 +208,22 @@ class System : public Serializable void lockDataBus() { myDataBusLocked = true; } void unlockDataBus() { myDataBusLocked = false; } + #ifdef DEBUGGER_SUPPORT /** - Access and modify the disassembly type flags for the given + Access and modify the access type flags for the given address. Note that while any flag can be used, the disassembly - only really acts on CODE/GFX/PGFX/DATA/ROW. + only really acts on CODE/GFX/PGFX/COL/PCOL/BCOL/AUD/DATA/ROW. */ - uInt8 getAccessFlags(uInt16 address) const; - void setAccessFlags(uInt16 address, uInt8 flags); + Device::AccessFlags getAccessFlags(uInt16 address) const; + void setAccessFlags(uInt16 address, Device::AccessFlags flags); + + /** + Increase the given address's access counter + + @param address The address to modify + */ + void increaseAccessCounter(uInt16 address, bool isWrite); + #endif public: /** @@ -271,13 +257,27 @@ class System : public Serializable uInt8* directPokeBase{nullptr}; /** - Pointer to a lookup table for marking an address as CODE. A CODE - section is defined as any address that appears in the program + Pointer to a lookup table for marking an address as CODE, DATA, GFX, + COL etc. + A CODE section is defined as any address that appears in the program counter. Currently, this is used by the debugger/disassembler to conclusively determine if a section of address space is CODE, even if the disassembler failed to mark it as such. + A DATA, GFX, COL etc. section is defined as any ROM address from which + data is read. This is used by the debugger/disassembler to format + address sections accordingly. */ - uInt8* codeAccessBase{nullptr}; + Device::AccessFlags* romAccessBase{nullptr}; + + /** + TODO + */ + Device::AccessCounter* romPeekCounter{nullptr}; + + /** + TODO + */ + Device::AccessCounter* romPokeCounter{nullptr}; /** Pointer to the device associated with this page or to the system's diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx index 46b2250c0..781ca203a 100644 --- a/src/emucore/TIASurface.cxx +++ b/src/emucore/TIASurface.cxx @@ -23,14 +23,24 @@ #include "Console.hxx" #include "TIA.hxx" #include "PNGLibrary.hxx" +#include "PaletteHandler.hxx" #include "TIASurface.hxx" namespace { FrameBuffer::ScalingInterpolation interpolationModeFromSettings(const Settings& settings) { +#ifdef RETRON77 + // Witv TV / and or scanline interpolation, the image has a height of ~480px. THe R77 runs at 720p, so there + // is no benefit from QIS in y-direction. In addition, QIS on the R77 has performance issues if TV effects are + // enabled. + return settings.getBool("tia.inter") || settings.getInt("tv.filter") != 0 + ? FrameBuffer::ScalingInterpolation::blur + : FrameBuffer::ScalingInterpolation::sharp; +#else return settings.getBool("tia.inter") ? FrameBuffer::ScalingInterpolation::blur : FrameBuffer::ScalingInterpolation::sharp; +#endif } } @@ -67,6 +77,14 @@ TIASurface::TIASurface(OSystem& system) // Enable/disable threading in the NTSC TV effects renderer myNTSCFilter.enableThreading(myOSystem.settings().getBool("threads")); + + myPaletteHandler = make_unique(myOSystem); + myPaletteHandler->loadConfig(myOSystem.settings()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +TIASurface::~TIASurface() +{ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -80,6 +98,8 @@ void TIASurface::initialize(const Console& console, mySLineSurface->setDstPos(mode.image.x(), mode.image.y()); mySLineSurface->setDstSize(mode.image.w(), mode.image.h()); + myPaletteHandler->setPalette(); + // Phosphor mode can be enabled either globally or per-ROM int p_blend = 0; bool enable = false; @@ -128,32 +148,19 @@ const FBSurface& TIASurface::baseSurface(Common::Rect& rect) const uInt32 tiaw = myTIA->width(), width = tiaw * 2, height = myTIA->height(); rect.setBounds(0, 0, width, height); - // Get Blargg buffer and width - uInt32 *blarggBuf, blarggPitch; - myTiaSurface->basePtr(blarggBuf, blarggPitch); - double blarggXFactor = double(blarggPitch) / width; - bool useBlargg = ntscEnabled(); - // Fill the surface with pixels from the TIA, scaled 2x horizontally uInt32 *buf_ptr, pitch; myBaseTiaSurface->basePtr(buf_ptr, pitch); for(uInt32 y = 0; y < height; ++y) - { for(uInt32 x = 0; x < width; ++x) - { - if (useBlargg) - *buf_ptr++ = blarggBuf[y * blarggPitch + uInt32(nearbyint(x * blarggXFactor))]; - else *buf_ptr++ = myPalette[*(myTIA->frameBuffer() + y * tiaw + x / 2)]; - } - } return *myBaseTiaSurface; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift) +uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift) const { return myPalette[indexedColor | shift]; } @@ -180,25 +187,87 @@ void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIASurface::setScanlineIntensity(int amount) +void TIASurface::changeNTSC(int direction) { - ostringstream buf; - uInt32 intensity = enableScanlines(amount); - buf << "Scanline intensity at " << intensity << "%"; - myOSystem.settings().setValue("tv.scanlines", intensity); + constexpr NTSCFilter::Preset PRESETS[] = { + NTSCFilter::Preset::OFF, NTSCFilter::Preset::RGB, NTSCFilter::Preset::SVIDEO, + NTSCFilter::Preset::COMPOSITE, NTSCFilter::Preset::BAD, NTSCFilter::Preset::CUSTOM + }; + int preset = myOSystem.settings().getInt("tv.filter"); - myFB.showMessage(buf.str()); + if(direction == +1) + { + if(preset == int(NTSCFilter::Preset::CUSTOM)) + preset = int(NTSCFilter::Preset::OFF); + else + preset++; + } + else if (direction == -1) + { + if(preset == int(NTSCFilter::Preset::OFF)) + preset = int(NTSCFilter::Preset::CUSTOM); + else + preset--; + } + setNTSC(PRESETS[preset], true); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIASurface::enableScanlines(int relative, int absolute) +void TIASurface::setNTSCAdjustable(int direction) +{ + string text, valueText; + Int32 value; + + setNTSC(NTSCFilter::Preset::CUSTOM); + ntsc().selectAdjustable(direction, text, valueText, value); + myOSystem.frameBuffer().showMessage(text, valueText, value); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIASurface::changeNTSCAdjustable(int adjustable, int direction) +{ + string text, valueText; + Int32 newValue; + + setNTSC(NTSCFilter::Preset::CUSTOM); + ntsc().changeAdjustable(adjustable, direction, text, valueText, newValue); + myOSystem.frameBuffer().showMessage(text, valueText, newValue); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIASurface::changeCurrentNTSCAdjustable(int direction) +{ + string text, valueText; + Int32 newValue; + + setNTSC(NTSCFilter::Preset::CUSTOM); + ntsc().changeCurrentAdjustable(direction, text, valueText, newValue); + myOSystem.frameBuffer().showMessage(text, valueText, newValue); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIASurface::setScanlineIntensity(int direction) +{ + ostringstream buf; + uInt32 intensity = enableScanlines(direction * 2); + + myOSystem.settings().setValue("tv.scanlines", intensity); + enableNTSC(ntscEnabled()); + + if(intensity) + buf << intensity << "%"; + else + buf << "Off"; + myFB.showMessage("Scanline intensity", buf.str(), intensity); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 TIASurface::enableScanlines(int change) { FBSurface::Attributes& attr = mySLineSurface->attributes(); - if(relative == 0) attr.blendalpha = absolute; - else attr.blendalpha += relative; - attr.blendalpha = std::max(0, Int32(attr.blendalpha)); - attr.blendalpha = std::min(100U, attr.blendalpha); + attr.blendalpha += change; + attr.blendalpha = BSPF::clamp(Int32(attr.blendalpha), 0, 100); mySLineSurface->applyAttributes(); return attr.blendalpha; diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx index c87ddc881..2b6213785 100644 --- a/src/emucore/TIASurface.hxx +++ b/src/emucore/TIASurface.hxx @@ -22,6 +22,7 @@ class TIA; class Console; class OSystem; class FBSurface; +class PaletteHandler; #include @@ -48,6 +49,7 @@ class TIASurface Creates a new TIASurface object */ explicit TIASurface(OSystem& system); + virtual ~TIASurface(); /** Set the TIA object, which is needed for actually rendering the TIA image. @@ -68,14 +70,18 @@ class TIASurface void setPalette(const PaletteArray& tia_palette, const PaletteArray& rgb_palette); /** - Get the TIA base surface for use in saving to a PNG image. + Get a TIA surface that has no post-processing whatsoever. This is + currently used to save PNG image in the so-called '1x mode'. + + @param rect Specifies the area in which the surface data is valid */ const FBSurface& baseSurface(Common::Rect& rect) const; /** - Use the palette to map a single indexed pixel color. This is used by the TIA output widget. + Use the palette to map a single indexed pixel color. This is used by the + TIA output widget. */ - uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0); + uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0) const; /** Get the NTSCFilter object associated with the framebuffer @@ -88,19 +94,53 @@ class TIASurface void setNTSC(NTSCFilter::Preset preset, bool show = true); /** - Increase/decrease current scanline intensity by given relative amount. + Switch to next/previous NTSC filtering effect. + + @param direction +1 indicates increase, -1 indicates decrease. */ - void setScanlineIntensity(int relative); + void changeNTSC(int direction = +1); + + /** + Switch to next/previous NTSC filtering adjustable. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void setNTSCAdjustable(int direction = +1); + + /** + Increase/decrease given NTSC filtering adjustable. + + @param adjustable The adjustable to change + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeNTSCAdjustable(int adjustable, int direction); + + /** + Increase/decrease current NTSC filtering adjustable. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void changeCurrentNTSCAdjustable(int direction = +1); + + /** + Retrieve palette handler. + */ + PaletteHandler& paletteHandler() const { return *myPaletteHandler; } + + /** + Increase/decrease current scanline intensity by given relative amount. + + @param direction +1 indicates increase, -1 indicates decrease. + */ + void setScanlineIntensity(int direction = +1); /** Change scanline intensity and interpolation. - @param relative If non-zero, change current intensity by - 'relative' amount, otherwise set to 'absolute' + @param change change current intensity by 'change' @return New current intensity */ - uInt32 enableScanlines(int relative, int absolute = 50); - void enableScanlineInterpolation(bool enable); + uInt32 enableScanlines(int change); /** Enable/disable/query phosphor effect. @@ -183,6 +223,9 @@ class TIASurface // Flag for saving a snapshot bool mySaveSnapFlag{false}; + // The palette handler + unique_ptr myPaletteHandler; + private: // Following constructors and assignment operators not supported TIASurface() = delete; diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx index c5bd3e637..2984159cd 100644 --- a/src/emucore/Thumbulator.cxx +++ b/src/emucore/Thumbulator.cxx @@ -108,6 +108,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing) case ConsoleTiming::ntsc: timing_factor = NTSC; break; case ConsoleTiming::secam: timing_factor = SECAM; break; case ConsoleTiming::pal: timing_factor = PAL; break; + default: break; // satisfy compiler } } diff --git a/src/emucore/module.mk b/src/emucore/module.mk index e02fcdc2d..71bd33847 100644 --- a/src/emucore/module.mk +++ b/src/emucore/module.mk @@ -5,11 +5,14 @@ MODULE_OBJS := \ src/emucore/Bankswitch.o \ src/emucore/Booster.o \ src/emucore/Cart.o \ + src/emucore/CartCreator.o \ src/emucore/CartDetector.o \ + src/emucore/CartEnhanced.o \ src/emucore/Cart0840.o \ src/emucore/Cart2K.o \ src/emucore/Cart3E.o \ src/emucore/Cart3EPlus.o \ + src/emucore/Cart3EX.o \ src/emucore/Cart3F.o \ src/emucore/Cart4A50.o \ src/emucore/Cart4K.o \ @@ -20,8 +23,6 @@ MODULE_OBJS := \ src/emucore/CartCM.o \ src/emucore/CartCTY.o \ src/emucore/CartCV.o \ - src/emucore/CartCVPlus.o \ - src/emucore/CartDASH.o \ src/emucore/CartDPC.o \ src/emucore/CartDPCPlus.o \ src/emucore/CartE0.o \ @@ -47,6 +48,7 @@ MODULE_OBJS := \ src/emucore/CartFE.o \ src/emucore/CartMDM.o \ src/emucore/CartSB.o \ + src/emucore/CartTVBoy.o \ src/emucore/CartUA.o \ src/emucore/CartWD.o \ src/emucore/CartX07.o \ diff --git a/src/emucore/stella.pro b/src/emucore/stella.pro index f2edd993d..6253c7bfb 100644 --- a/src/emucore/stella.pro +++ b/src/emucore/stella.pro @@ -252,7 +252,7 @@ "Cart.Name" "Princess Rescue (2013) (Sprybug) (PAL60)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -495,7 +495,6 @@ "Cart.MD5" "069c17beb1e8e0557adb8539fdcf6cba" "Cart.Name" "Phantom II & Pirate (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "06b0194ce992584c365278e0d7323279" @@ -679,7 +678,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "0894aa7be77521f9df562be8d9555fe6" @@ -733,7 +731,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.2 (PAL60) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "08f4dc6f118f7c98e2406c180c08e78e" @@ -1027,7 +1024,6 @@ "Cart.ModelNo" "v1.3" "Cart.Name" "Amoeba Jump (2018) (Dionoid) (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "0c7926d660f903a2d6910c254660c32c" @@ -1081,7 +1077,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Challenge of... Nexar, The - Atari Mouse Hack v1.1 (PAL60) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "0cfdd2f3b243cac21f38a0f09f54bead" @@ -1194,7 +1189,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "0e4b2b6e014a93ef8be896823da0d4ec" @@ -1342,7 +1336,6 @@ "Cart.ModelNo" "805.784 6" "Cart.Name" "Labyrinth (1983) (Quelle) (PAL)" "Cart.Note" "AKA Maze Craze" -"Display.Format" "PAL" "" "Cart.MD5" "0fc161704c46e16f7483f92b06c1558d" @@ -1399,6 +1392,7 @@ "Cart.Name" "Princess Rescue (2013) (Sprybug)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -1906,6 +1900,11 @@ "Cart.Name" "JtzBall (Alpha) (TJ)" "" +"Cart.MD5" "16229d61d7b0c89b01853660a8da22bb" +"Cart.Name" "spin4a50" +"Cart.Type" "4A50" +"" + "Cart.MD5" "163e7e757e2dc44469123ff0e5daec5e" "Cart.Name" "Many Blue Bars and Text Demo 2 (PD)" "" @@ -1975,7 +1974,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Challenge of... Nexar, The - Amiga Mouse Hack v1.1 (PAL60) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "1733772165d7b886a94e2b4ed0f74ccd" @@ -2112,7 +2110,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Missile Control - Amiga Mouse Hack v1.15 (PAL60) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "18bebbbd41c234f82b1717b1905e6027" @@ -2294,6 +2291,14 @@ "Cart.Name" "Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]" "" +"Cart.MD5" "1b5a8da0622bffcee4c5b42aed4e0ef0" +"Cart.Manufacturer" "Akor" +"Cart.Name" "TV Boy II (1992) (Akor)" +"Cart.Note" "Includes 127 games" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "1b8c3c0bfb815b2a1010bba95998b66e" "Cart.Manufacturer" "Telegames" "Cart.Name" "Frogs and Flies (1988) (Telegames) (PAL)" @@ -2354,7 +2359,6 @@ "Cart.Manufacturer" "Nukey Shay, Omegamatrix" "Cart.Name" "Double Dragon (Genesis) (PAL60) V2" "Cart.Note" "Genesis controller" -"Display.Format" "PAL60" "" "Cart.MD5" "1c6eb740d3c485766cade566abab8208" @@ -2638,7 +2642,6 @@ "Cart.Name" "Stay Frosty (SpiceWare) (PAL60)" "Cart.Note" "Part of Stella's Stocking 2007 Xmas compilation" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -2701,7 +2704,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "2091af29b4e7b86914d79d9aaa4cbd20" @@ -2898,8 +2900,7 @@ "Cart.Name" "Scramble (PAL60)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" -"Controller.Left" "GENESIS" -"Display.Format" "PAL60" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -3157,7 +3158,6 @@ "Cart.Manufacturer" "Activision, Garry Kitchen" "Cart.ModelNo" "EAX-025" "Cart.Name" "Keystone Kapers (1983) (Activision) (SECAM)" -"Display.Format" "SECAM" "" "Cart.MD5" "25f9cf703575c5d63048c222f5463758" @@ -3218,7 +3218,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "SpaceMaster X-7 (Amiga Mouse) (PAL60) (Omegamatrix)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "271bfd5dc2673d382019f1fb6cab9332" @@ -3294,7 +3293,6 @@ "Cart.Note" "Hack of Video Olympics" "Controller.SwapPaddles" "YES" "Controller.MouseAxis" "AUTO 60" -"Display.Format" "PAL60" "" "Cart.MD5" "27baecd618e7e53dc11f2a9c559f529d" @@ -3721,7 +3719,6 @@ "Cart.Name" "Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) (PAL60)" "Cart.Note" "PAL60 Conversion" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "2c9fadd510509cc7f28f1ccba931855f" @@ -3872,7 +3869,7 @@ "Cart.MD5" "2dbdca3058035d2b40c734dcf06a86d9" "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Asteroids DC+ (Thomas Jentzsch) (Hack)" -"Cart.Note" "Uses the Joystick (left) or Steering (right) Controller" +"Cart.Note" "Uses the Joystick (left) or Driving (right) Controller" "Cart.Rarity" "Hack" "Controller.Right" "DRIVING" "Controller.MouseAxis" "58" @@ -3889,7 +3886,6 @@ "Cart.Manufacturer" "Gray Games & AtariAge" "Cart.Name" "E.T. Book Cart (PAL60)" "Cart.Note" "Charles F. Gray & Michael Rideout" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "Display.PPBlend" "55" "" @@ -4726,7 +4722,6 @@ "Cart.ModelNo" "SS-004" "Cart.Name" "Pyramid War (1983) (Rainbow Vision) (PAL) [a2]" "Cart.Note" "AKA Chopper Command" -"Display.Format" "PAL" "" "Cart.MD5" "384db97670817103dd8c0bbdef132445" @@ -5967,7 +5962,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Atari Trak-Ball) v4 (PAL60) (Omegamatrix)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "4767356fa0ed3ebe21437b4473d4ee28" @@ -6011,7 +6005,7 @@ "Cart.MD5" "47aef18509051bab493589cb2619170b" "Cart.Name" "Stell-A-Sketch (Bob Colbert) (PD)" -"Cart.Note" "Uses Driving, Joystick, or Amiga/Atari ST mouse Controllers" +"Cart.Note" "Uses Driving, Joystick, or Amiga/Atari ST Mouse Controllers" "Cart.Rarity" "New Release" "Display.Phosphor" "YES" "" @@ -6150,6 +6144,13 @@ "Cart.Name" "Pitfall II (1983) (Activision) [a]" "" +"Cart.MD5" "49366f41aa7a54baf263426e99ce4312" +"Cart.Name" "POP-MDM-Test (PAL) (63 games)" +"Cart.Type" "MDM" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "493daaf9fb1ba450eba6b8ed53ffb37d" "Cart.Name" "3-D Corridor Demo (27-03-2003) (MP)" "" @@ -6173,7 +6174,6 @@ "Cart.Manufacturer" "Andreas Dietrich" "Cart.Name" "Donkey Kong VCS (2017) (1.0) (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -6332,7 +6332,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "SpaceMaster X-7 (Atari Mouse) (PAL60) (Omegamatrix)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "4b71197153d651480830638cb6a03249" @@ -6738,7 +6737,6 @@ "Cart.MD5" "50200f697aeef38a3ce31c4f49739551" "Cart.Manufacturer" "Mystique - American Multiple Industries, Joel H. Martin" "Cart.Name" "Custer's Revenge (1982) (Mystique) (PAL60)" -"Display.Format" "PAL60" "" "Cart.MD5" "502044b1ac111b394e6fbb0d821fca41" @@ -7094,6 +7092,16 @@ "Cart.Name" "Carnival Shooter (PD)" "" +"Cart.MD5" "541cac55ebcf7891d9d51c415922303f" +"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr." +"Cart.ModelNo" "SW-05" +"Cart.Name" "Stay Frosty 2" +"Cart.Note" "AtariAge Holiday Greetings 2014" +"Cart.Rarity" "Homebrew" +"Controller.Left" "JOYSTICK" +"Display.Phosphor" "YES" +"" + "Cart.MD5" "5428cdfada281c569c74c7308c7f2c26" "Cart.Manufacturer" "Activision, Larry Kaplan, David Crane" "Cart.ModelNo" "AG-010, AG-010-04" @@ -7280,7 +7288,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Amiga Mouse) v4 (PAL60) (Omegamatrix)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "571c6d9bc71cb97617422851f787f8fe" @@ -7376,7 +7383,6 @@ "Cart.Manufacturer" "Xonox - K-Tel Software - Action Graphics, Michael Schwartz, David Thiel" "Cart.ModelNo" "6230, 7210, 06004, 99004" "Cart.Name" "Artillery Duel (1983) (Xonox) (PAL60)" -"Display.Format" "PAL60" "" "Cart.MD5" "58a82e1da64a692fd727c25faef2ecc9" @@ -7486,8 +7492,7 @@ "Cart.Name" "Super Cobra Arcade (PAL60)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" -"Controller.Left" "GENESIS" -"Display.Format" "PAL60" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -7562,7 +7567,8 @@ "Cart.MD5" "5a9685c4d51a6c1d6a9544946d9e8dc3" "Cart.Manufacturer" "AtariAge" "Cart.Name" "Grandma's Revenge (AtariAge)" -"Cart.Note" "Can use driving controller in right port" +"Cart.Note" "Can use Driving Controller in right port" +"Controller.Right" "DRIVING" "" "Cart.MD5" "5a9d188245aff829efde816fcade0b16" @@ -7783,7 +7789,6 @@ "Cart.Name" "Space Shuttle (1983) (Activision) (SECAM)" "Cart.Note" "A Journey Into Space" "Cart.Type" "FE" -"Display.Format" "SECAM" "" "Cart.MD5" "5d2cc33ca798783dee435eb29debf6d6" @@ -8183,6 +8188,13 @@ "Cart.Name" "Time Warp (Unknown)" "" +"Cart.MD5" "61baadddc2c8f6e5faa57d4d0f285462" +"Cart.Name" "208-in-1 MDM-Test (PAL) (127 games)" +"Cart.Type" "MDM" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "61dbe94f110f30ca4ec524ae5ce2d026" "Cart.Manufacturer" "CCE" "Cart.ModelNo" "C-820" @@ -8532,6 +8544,14 @@ "Display.Phosphor" "YES" "" +"Cart.MD5" "65a6f1255fe22468a8bf84ff28a4d289" +"Cart.Manufacturer" "Akor" +"Cart.Name" "Super TV Boy (1995) (Akor)" +"Cart.Note" "Includes 127 games" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "65b106eba3e45f3dab72ea907f39f8b4" "Cart.Manufacturer" "Christian Software Development - HomeComputer Software, Dan Schafer, Glenn Stohel, Jon Tedesco - Sparrow" "Cart.ModelNo" "GCG 1001T" @@ -8771,7 +8791,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "SpaceMaster X-7 (Atari Trak-Ball) (PAL60) (Omegamatrix)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "6803fa7c2c094b428b859a58dc1dd06a" @@ -8795,7 +8814,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Atari Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "683bb0d0f0c5df58557fba9dffc32c40" @@ -9708,7 +9726,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Missile Control - Atari Trak-Ball Hack v1.15 (PAL60) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "72bda70c75dfa2365b3f8894bace9e6a" @@ -9966,7 +9983,6 @@ "Cart.Name" "Conquest Of Mars (2010) (PAL60)" "Cart.Note" "Rev 2 release" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "75a303fd46ad12457ed8e853016815a0" @@ -10233,6 +10249,16 @@ "Cart.Note" "Abenteuer im Urwald (Jungle Runner)" "" +"Cart.MD5" "791c88eca9836af8c34bf32b07cb58a7" +"Cart.Manufacturer" "SpiceWare - Darrell Spice Jr." +"Cart.ModelNo" "SW-05" +"Cart.Name" "Stay Frosty 2 (PAL60)" +"Cart.Note" "AtariAge Holiday Greetings 2014" +"Cart.Rarity" "Homebrew" +"Controller.Left" "JOYSTICK" +"Display.Phosphor" "YES" +"" + "Cart.MD5" "7926083ad423ed685de3b3a04a914315" "Cart.Manufacturer" "Barry Laws Jr." "Cart.Name" "Face Invaders 2 (Barry Laws Jr.) (Hack)" @@ -10442,7 +10468,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Atari Trak-Ball) (Y Inverted) (PAL60) v4 (Omegamatrix)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "7b5207e68ee85b16998bea861987c690" @@ -10577,7 +10602,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Atari Mouse Hack v1.4 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "7d0b49ea4fe3a5f1e119a6d14843db17" @@ -11000,7 +11024,6 @@ "Cart.Note" "Hack of Kaboom!" "Cart.Rarity" "Hack" "Controller.MouseAxis" "01 50" -"Display.Format" "PAL60" "" "Cart.MD5" "8108162bc88b5a14adc3e031cf4175ad" @@ -11224,7 +11247,7 @@ "Cart.Name" "Super Cobra Arcade (NTSC)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" -"Controller.Left" "GENESIS" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -11383,7 +11406,6 @@ "Cart.ModelNo" "CG-02-P" "Cart.Name" "Conquest Of Mars (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "85e48d68c8d802e3ba9d494a47d6e016" @@ -11404,6 +11426,15 @@ "Cart.Name" "Lochjaw (1982) (Apollo)" "" +"Cart.MD5" "8619da7f6796cedff59e5aa20712fb4e" +"Cart.Manufacturer" "Thomas Jentzsch" +"Cart.Name" "Sadistroids (v1.2) (2003) (Thomas Jentzsch)" +"Cart.Note" "Supports Driving Controller in right port" +"Controller.Right" "DRIVING" +"Display.Phosphor" "YES" +"Display.PPBlend" "30" +"" + "Cart.MD5" "862cf669cbced78f9ed31a5d375b2ebe" "Cart.Name" "Gunfight 2600 - Flicker acceptance (2001) (MP)" "" @@ -11845,7 +11876,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Amiga Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "8c1cc284edba691139d6626d062c606f" @@ -11853,7 +11883,6 @@ "Cart.Name" "Super Breakout Menu (2020) (PAL60) (Hack)" "Cart.Note" "Hack of Super Breakout" "Controller.MouseAxis" "AUTO 45" -"Display.Format" "PAL60" "" "Cart.MD5" "8c2fa33048f055f38358d51eefe417db" @@ -12032,7 +12061,6 @@ "Cart.Name" "Cosmic Commuter (Thomas Jentzsch) (PAL60)" "Cart.Note" "NTSC Conversion" "Cart.Rarity" "Hack" -"Display.Format" "PAL60" "" "Cart.MD5" "8e887d1ba5f3a71ae8a0ea16a4af9fc9" @@ -12059,7 +12087,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Amiga Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "8f33bce5ba1053dcf4cea9c1c69981e4" @@ -12167,7 +12194,6 @@ "Cart.Name" "Crash Dive (Fabrizio Zavagli) (PAL60)" "Cart.Note" "NTSC Conversion" "Cart.Rarity" "Hack" -"Display.Format" "PAL60" "" "Cart.MD5" "90a3c3255f2a54225cdcb50831f8793a" @@ -12429,7 +12455,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Challenge of... Nexar, The - Atari Trak-Ball Hack v1.1 (PAL60) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "93dc15d15e77a7b23162467f95a5f22d" @@ -12478,7 +12503,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Marble Craze - Amiga Mouse Hack v1.0 (PAL60) (TJ)" "Cart.Note" "Uses Amiga Mouse Controllers" -"Display.Format" "PAL60" "" "Cart.MD5" "94507dee401b0a072a481c00d7699ffe" @@ -12591,7 +12615,6 @@ "Cart.Manufacturer" "Suntek" "Cart.ModelNo" "SS-021" "Cart.Name" "Dragon Defender (1983) (Suntek) (PAL)" -"Controller.Left" "MINDLINK" "Display.Phosphor" "YES" "" @@ -13040,7 +13063,6 @@ "Cart.Manufacturer" "Andrew Wallace" "Cart.Name" "Laseresal 2002 (PAL60) (PD)" "Cart.Rarity" "New Release" -"Display.Format" "PAL60" "" "Cart.MD5" "9c729017dd2f9ccbadcb511187f80e6b" @@ -13255,7 +13277,6 @@ "Cart.Name" "Montezuma's Revenge (Thomas Jentzsch) (PAL60)" "Cart.Note" "NTSC Conversion" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "9f8fad4badcd7be61bbd2bcaeef3c58f" @@ -13529,7 +13550,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Atari Mouse) (Y Inverted) (PAL60) v4 (Omegamatrix)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "a2de0fc85548871279ed2a3c1325c13e" @@ -13552,7 +13572,6 @@ "Cart.Manufacturer" "Nukey Shay" "Cart.Name" "Montezuma's Revenge (Genesis) (PAL60) (F6_Conversion)" "Cart.Note" "Genesis controller" -"Display.Format" "PAL60" "" "Cart.MD5" "a302b922a8dbec47743f28b7f91d4cd8" @@ -13634,7 +13653,6 @@ "Cart.Manufacturer" "Aaron Curtis" "Cart.Name" "AStar (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "a406d2f6d84e61d842f4cb13b2b1cfa7" @@ -13687,7 +13705,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Marble Craze - Atari Mouse Hack v1.0 (PAL60) (TJ)" "Cart.Note" "Uses Atari Mouse Controllers" -"Display.Format" "PAL60" "" "Cart.MD5" "a499d720e7ee35c62424de882a3351b6" @@ -14011,6 +14028,12 @@ "Cart.Name" "Boxing (1983) (CCE)" "" +"Cart.MD5" "a8c447efbec3a2b5d08b05a09999bd92" +"Cart.Name" "MegaCart Menu" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "a8c48b4e0bf35fe97cc84fdd2c507f78" "Cart.Manufacturer" "Puzzy - Bit Corporation" "Cart.ModelNo" "PG201" @@ -14106,7 +14129,6 @@ "Cart.ModelNo" "CX26201" "Cart.Name" "Zippy the Porcupine (2014) (Sprybug) (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "a9e3c23599c0d77151602f8e31daf879" @@ -14378,7 +14400,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "ad7e97c19bd25d5aa3999430845c755b" @@ -14710,7 +14731,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Atari Mouse Hack v1.3 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "b1a6c96e9093352106bc335e96caa154" @@ -14869,7 +14889,6 @@ "Cart.Manufacturer" "Omegamatrix" "Cart.Name" "Star Wars Arcade (Atari Mouse) v4 (PAL60) (Omegamatrix)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "b31f178aa0d569cccac7959f84e0a724" @@ -15135,7 +15154,6 @@ "Cart.Name" "Cat Trax (Thomas Jentzsch) (PAL60)" "Cart.Note" "NTSC Conversion" "Cart.Rarity" "Hack" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -15171,7 +15189,6 @@ "Cart.ModelNo" "RC2" "Cart.Name" "Flappy (2014) (AtariAge) (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "b7e459d5416eeb196aaa8e092db14463" @@ -15276,7 +15293,6 @@ "Cart.Manufacturer" "Atari, Omegamatrix" "Cart.Name" "Space Invaders Menu (2020) (PAL60) (Hack)" "Cart.Note" "Hack of Space Invaders" -"Display.Format" "PAL60" "" "Cart.MD5" "b958d5fd9574c5cf9ece4b9421c28ecd" @@ -15391,7 +15407,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Missile Control - Atari Mouse Hack v1.15 (PAL60) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "bb5049e4558daade0f87fed69a244c59" @@ -15482,7 +15497,6 @@ "Cart.Manufacturer" "Bob Montgomery (aka vdub_bobby)" "Cart.Name" "Squish 'Em (2007) (PAL60)" "Cart.Rarity" "Homebrew" -"Display.Format" "PAL60" "" "Cart.MD5" "bccb4e2cfad5efc93f6d55dc992118ce" @@ -15699,7 +15713,6 @@ "Cart.Manufacturer" "Atari" "Cart.Name" "A-Team (Atari) (Prototype) (PAL60)" "Cart.Rarity" "Prototype" -"Display.Format" "PAL60" "" "Cart.MD5" "c032c2bd7017fdfbba9a105ec50f800e" @@ -16477,7 +16490,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Marble Craze - Atari Trak-Ball Hack v1.0 (PAL60) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controllers" -"Display.Format" "PAL60" "" "Cart.MD5" "c9196e28367e46f8a55e04c27743148f" @@ -16496,7 +16508,6 @@ "Cart.Manufacturer" "AtariAge, Omegamatrix" "Cart.Name" "Venture Reloaded (2019) (AtariAge) (PAL60) (Hack)" "Cart.Note" "Transformative hack of Venture" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -16863,7 +16874,6 @@ "Cart.Manufacturer" "SEGA - Teldec" "Cart.ModelNo" "005-10" "Cart.Name" "Buck Rogers - Planet of Zoom (1983) (SEGA) (PAL)" -"Display.Format" "PAL" "Display.Phosphor" "YES" "" @@ -16893,7 +16903,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Amiga Mouse Hack v1.4 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Amiga Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "cdb81bf33d830ee4ee0606ee99e84dba" @@ -16999,7 +17008,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Atari Trak-Ball Hack v1.3 (PAL60) (Half-Speed) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "cedbd67d1ff321c996051eec843f8716" @@ -17152,7 +17160,6 @@ "Cart.Name" "Tomarc the Barbarian (1983) (Xonox) (PAL60)" "Cart.Note" "Genesis controller (B is jump and throw, C switches between players)" "Cart.Rarity" "Hack of Tomarc the Barbarian" -"Display.Format" "PAL60" "" "Cart.MD5" "d00f6f8ba89559e4b20972a478fc0370" @@ -17542,7 +17549,6 @@ "Cart.ModelNo" "CX26140, CX26140P" "Cart.Name" "Desert Falcon (1987) (Atari) (PAL)" "Cart.Note" "AKA Nile Flyer, Sphinx" -"Display.Format" "PAL" "" "Cart.MD5" "d483f65468d9a265661917bae1a54f3e" @@ -17639,7 +17645,6 @@ "Cart.Manufacturer" "Activision, Carol Shaw" "Cart.ModelNo" "EAX-020" "Cart.Name" "River Raid (1982) (Activision) (SECAM)" -"Display.Format" "SECAM" "" "Cart.MD5" "d5e27051512c1e7445a9bf91501bda09" @@ -17998,7 +18003,6 @@ "Cart.ModelNo" "460673" "Cart.Name" "Pick 'n' Pile (1990) (Salu) (PAL)" "Console.SwapPorts" "YES" -"Display.Format" "PAL" "Display.Phosphor" "YES" "" @@ -18923,7 +18927,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Centipede - Atari Trak-Ball Hack v1.4 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Atari Trak-Ball Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "e49ac0ec879a0d7820bc2598fc2cfcd4" @@ -18987,6 +18990,14 @@ "Cart.Name" "Comitoid beta 4 (SnailSoft)" "" +"Cart.MD5" "e4fa739c81b003c92bea7da5e84c7feb" +"Cart.Manufacturer" "Akor" +"Cart.Name" "TV Boy (1992) (Akor) (NTSC) [bad dump]" +"Cart.Note" "Includes 127 games" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "e505bd8e59e31aaed20718d47b15c61b" "Cart.Manufacturer" "Funvision - Fund. Int'l Co." "Cart.Name" "Space War (1982) (Funvision) (PAL)" @@ -19420,7 +19431,7 @@ "Cart.Name" "Scramble (NTSC)" "Cart.Note" "Compatible with Genesis controller" "Cart.Rarity" "Homebrew" -"Controller.Left" "GENESIS" +"Controller.Left" "JOYSTICK" "Display.Phosphor" "YES" "" @@ -19539,7 +19550,6 @@ "Cart.Manufacturer" "Activision, John Van Ryzin" "Cart.ModelNo" "EAZ-036-04" "Cart.Name" "H.E.R.O. (1984) (Activision) (SECAM)" -"Display.Format" "SECAM" "" "Cart.MD5" "eb92193f06b645df0b2a15d077ce435f" @@ -19628,7 +19638,6 @@ "Cart.MD5" "ece908d77ab944f7bac84322b9973549" "Cart.Name" "Tom Boy (Unknown) (PAL60)" "Cart.Note" "AKA Pitfall!" -"Display.Format" "PAL60" "" "Cart.MD5" "ecf51385384b468834611d44a8429c03" @@ -19685,7 +19694,6 @@ "Cart.ModelNo" "CX2635, CX2635P" "Cart.Name" "Maze Craze (1980) (Atari) (PAL)" "Cart.Note" "AKA A Game of Cops 'n Robbers" -"Display.Format" "PAL" "" "Cart.MD5" "ed5ccfc93ad4561075436ee42a15438a" @@ -19711,7 +19719,6 @@ "Cart.Manufacturer" "Activision, David Crane" "Cart.ModelNo" "EAZ-030" "Cart.Name" "Decathlon (1983) (Activision) (SECAM)" -"Display.Format" "SECAM" "" "Cart.MD5" "ede7e8bf865b0afb4744f86d13624f9a" @@ -19980,7 +19987,6 @@ "Cart.Manufacturer" "Thomas Jentzsch" "Cart.Name" "Reactor - Atari Mouse Hack v1.3 (PAL60) (Full-Speed) (TJ)" "Cart.Note" "Uses Atari Mouse Controller" -"Display.Format" "PAL60" "" "Cart.MD5" "f0e0addc07971561ab80d9abe1b8d333" @@ -20033,7 +20039,6 @@ "Cart.Name" "Lady Bug (PAL60)" "Cart.Rarity" "Homebrew" "Console.RightDiff" "A" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -20280,6 +20285,8 @@ "Cart.ModelNo" "649635" "Cart.Name" "See Saw (Double-Game Package) (1983) (Otto Versand) (PAL)" "Cart.Note" "AKA Circus Atari" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" "" "Cart.MD5" "f3f5f72bfdd67f3d0e45d097e11b8091" @@ -20650,6 +20657,14 @@ "Cart.Note" "AKA Play Farm" "" +"Cart.MD5" "f7ec2f2bdbe8fbea048c0d5fa6503b0b" +"Cart.Manufacturer" "Akor" +"Cart.Name" "TV Boy (1992) (Akor) (PAL)" +"Cart.Note" "Includes 127 games" +"Controller.Left" "JOYSTICK" +"Controller.Right" "JOYSTICK" +"" + "Cart.MD5" "f7f50d9c9d28bcc9f7d3075668b7ac89" "Cart.Manufacturer" "Activision, David Crane - Ariola" "Cart.ModelNo" "EAG-008, PAG-008, EAG-008-04I - 711 008-720" @@ -20932,7 +20947,6 @@ "Cart.Note" "AtariVox supported" "Cart.Rarity" "Homebrew" "Controller.Right" "ATARIVOX" -"Display.Format" "PAL60" "Display.Phosphor" "YES" "" @@ -21393,4 +21407,3 @@ "Cart.MD5" "ffebb0070689b9d322687edd9c0a2bae" "Cart.Name" "Spitfire Attack (1983) (Milton Bradley) [h1]" "" - diff --git a/src/emucore/tia/Audio.hxx b/src/emucore/tia/Audio.hxx index 92e854a0d..5ab53ecae 100644 --- a/src/emucore/tia/Audio.hxx +++ b/src/emucore/tia/Audio.hxx @@ -18,12 +18,12 @@ #ifndef TIA_AUDIO_HXX #define TIA_AUDIO_HXX +class AudioQueue; + #include "bspf.hxx" #include "AudioChannel.hxx" #include "Serializable.hxx" -class AudioQueue; - class Audio : public Serializable { public: diff --git a/src/emucore/tia/Background.hxx b/src/emucore/tia/Background.hxx index 3004c7978..ea84aed96 100644 --- a/src/emucore/tia/Background.hxx +++ b/src/emucore/tia/Background.hxx @@ -18,11 +18,11 @@ #ifndef TIA_BACKGROUND #define TIA_BACKGROUND +class TIA; + #include "Serializable.hxx" #include "bspf.hxx" -class TIA; - class Background : public Serializable { public: diff --git a/src/emucore/tia/Ball.hxx b/src/emucore/tia/Ball.hxx index 5b9b3a604..0a40250e2 100644 --- a/src/emucore/tia/Ball.hxx +++ b/src/emucore/tia/Ball.hxx @@ -18,11 +18,11 @@ #ifndef TIA_BALL #define TIA_BALL -#include "Serializable.hxx" +class TIA; + #include "bspf.hxx" #include "TIAConstants.hxx" - -class TIA; +#include "Serializable.hxx" class Ball : public Serializable { diff --git a/src/emucore/tia/DelayQueue.hxx b/src/emucore/tia/DelayQueue.hxx index d3e7e544b..996bde72e 100644 --- a/src/emucore/tia/DelayQueue.hxx +++ b/src/emucore/tia/DelayQueue.hxx @@ -41,7 +41,7 @@ class DelayQueue : public Serializable void reset(); - template void execute(T executor); + template void execute(T executor); /** Serializable methods (see that class for more information). @@ -103,7 +103,7 @@ void DelayQueue::reset() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template -template +template void DelayQueue::execute(T executor) { DelayQueueMember& currentMember = myMembers[myIndex]; diff --git a/src/emucore/tia/DelayQueueIterator.hxx b/src/emucore/tia/DelayQueueIterator.hxx index 31e5251e8..3b615e3d4 100644 --- a/src/emucore/tia/DelayQueueIterator.hxx +++ b/src/emucore/tia/DelayQueueIterator.hxx @@ -19,8 +19,6 @@ #define TIA_DELAY_QUEUE_ITERATOR #include "bspf.hxx" -#include "DelayQueue.hxx" -#include "DelayQueueMember.hxx" class DelayQueueIterator { diff --git a/src/emucore/tia/DelayQueueIteratorImpl.hxx b/src/emucore/tia/DelayQueueIteratorImpl.hxx index b556cb279..9f9e4d4c7 100644 --- a/src/emucore/tia/DelayQueueIteratorImpl.hxx +++ b/src/emucore/tia/DelayQueueIteratorImpl.hxx @@ -20,7 +20,6 @@ #include "bspf.hxx" #include "DelayQueue.hxx" -#include "DelayQueueMember.hxx" #include "DelayQueueIterator.hxx" template diff --git a/src/emucore/tia/DelayQueueMember.hxx b/src/emucore/tia/DelayQueueMember.hxx index f87c9b459..653167b6f 100644 --- a/src/emucore/tia/DelayQueueMember.hxx +++ b/src/emucore/tia/DelayQueueMember.hxx @@ -18,8 +18,8 @@ #ifndef TIA_DELAY_QUEUE_MEMBER #define TIA_DELAY_QUEUE_MEMBER -#include "Serializable.hxx" #include "bspf.hxx" +#include "Serializable.hxx" template class DelayQueueMember : public Serializable { diff --git a/src/emucore/tia/Missile.hxx b/src/emucore/tia/Missile.hxx index dda9b493c..cd5cce582 100644 --- a/src/emucore/tia/Missile.hxx +++ b/src/emucore/tia/Missile.hxx @@ -18,13 +18,13 @@ #ifndef TIA_MISSILE #define TIA_MISSILE +class TIA; +class Player; + #include "Serializable.hxx" #include "bspf.hxx" -#include "Player.hxx" #include "TIAConstants.hxx" -class TIA; - class Missile : public Serializable { public: diff --git a/src/emucore/tia/PaddleReader.hxx b/src/emucore/tia/PaddleReader.hxx index abbc013c6..8071617c6 100644 --- a/src/emucore/tia/PaddleReader.hxx +++ b/src/emucore/tia/PaddleReader.hxx @@ -20,7 +20,7 @@ #include "bspf.hxx" #include "Serializable.hxx" -#include "Console.hxx" +#include "ConsoleTiming.hxx" class PaddleReader : public Serializable { diff --git a/src/emucore/tia/Player.hxx b/src/emucore/tia/Player.hxx index 454bfcd9f..60dfbe3c5 100644 --- a/src/emucore/tia/Player.hxx +++ b/src/emucore/tia/Player.hxx @@ -18,12 +18,12 @@ #ifndef TIA_PLAYER #define TIA_PLAYER +class TIA; + #include "bspf.hxx" #include "Serializable.hxx" #include "TIAConstants.hxx" -class TIA; - class Player : public Serializable { public: diff --git a/src/emucore/tia/Playfield.hxx b/src/emucore/tia/Playfield.hxx index fe811d53a..4a1376991 100644 --- a/src/emucore/tia/Playfield.hxx +++ b/src/emucore/tia/Playfield.hxx @@ -18,11 +18,11 @@ #ifndef TIA_PLAYFIELD #define TIA_PLAYFIELD -#include "Serializable.hxx" +class TIA; + #include "bspf.hxx" #include "TIAConstants.hxx" - -class TIA; +#include "Serializable.hxx" class Playfield : public Serializable { diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 60608b765..b3a48c335 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -24,10 +24,7 @@ #include "frame-manager/FrameManager.hxx" #include "AudioQueue.hxx" #include "DispatchResult.hxx" - -#ifdef DEBUGGER_SUPPORT - #include "CartDebug.hxx" -#endif +#include "Base.hxx" enum CollisionMask: uInt32 { player0 = 0b0111110000000000, @@ -187,7 +184,7 @@ void TIA::initialize() enableFixedColors(mySettings.getBool(devSettings ? "dev.debugcolors" : "plr.debugcolors")); #ifdef DEBUGGER_SUPPORT - createAccessBase(); + createAccessArrays(); #endif // DEBUGGER_SUPPORT } @@ -417,85 +414,81 @@ uInt8 TIA::peek(uInt16 address) { updateEmulation(); - // If pins are undriven, we start with the last databus value - // Otherwise, there is some randomness injected into the mix - // In either case, we start out with D7 and D6 disabled (the only - // valid bits in a TIA read), and selectively enable them - uInt8 lastDataBusValue = - !myTIAPinsDriven ? mySystem->getDataBusState() : mySystem->getDataBusState(0xFF); - - uInt8 result; + // Start with all bits disabled + // In some cases both D7 and D6 are used; in other cases only D7 is used + uInt8 result = 0b0000000; switch (address & 0x0F) { case CXM0P: - result = collCXM0P(); + result = collCXM0P() & 0b11000000; break; case CXM1P: - result = collCXM1P(); + result = collCXM1P() & 0b11000000; break; case CXP0FB: - result = collCXP0FB(); + result = collCXP0FB() & 0b11000000; break; case CXP1FB: - result = collCXP1FB(); + result = collCXP1FB() & 0b11000000; break; case CXM0FB: - result = collCXM0FB(); + result = collCXM0FB() & 0b11000000; break; case CXM1FB: - result = collCXM1FB(); + result = collCXM1FB() & 0b11000000; break; case CXPPMM: - result = collCXPPMM(); + result = collCXPPMM() & 0b11000000; break; case CXBLPF: - result = collCXBLPF(); + result = collCXBLPF() & 0b10000000; break; case INPT0: updatePaddle(0); - result = myPaddleReaders[0].inpt(myTimestamp) | (lastDataBusValue & 0x40); + result = myPaddleReaders[0].inpt(myTimestamp) & 0b10000000; break; case INPT1: updatePaddle(1); - result = myPaddleReaders[1].inpt(myTimestamp) | (lastDataBusValue & 0x40); + result = myPaddleReaders[1].inpt(myTimestamp) & 0b10000000; break; case INPT2: updatePaddle(2); - result = myPaddleReaders[2].inpt(myTimestamp) | (lastDataBusValue & 0x40); + result = myPaddleReaders[2].inpt(myTimestamp) & 0b10000000; break; case INPT3: updatePaddle(3); - result = myPaddleReaders[3].inpt(myTimestamp) | (lastDataBusValue & 0x40); + result = myPaddleReaders[3].inpt(myTimestamp) & 0b10000000; break; case INPT4: - result = - myInput0.inpt(!myConsole.leftController().read(Controller::DigitalPin::Six)) | - (lastDataBusValue & 0x40); + result = myInput0.inpt(!myConsole.leftController().read(Controller::DigitalPin::Six)) + & 0b10000000; break; case INPT5: - result = - myInput1.inpt(!myConsole.rightController().read(Controller::DigitalPin::Six)) | - (lastDataBusValue & 0x40); + result = myInput1.inpt(!myConsole.rightController().read(Controller::DigitalPin::Six)) + & 0b10000000; break; default: - result = 0; + break; } - return (result & 0xC0) | (lastDataBusValue & 0x3F); + // Bits D5 .. D0 are floating + // The options are either to use the last databus value, or use random data + return result | ((!myTIAPinsDriven ? mySystem->getDataBusState() : + mySystem->randGenerator().next()) & 0b00111111); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -534,59 +527,123 @@ bool TIA::poke(uInt16 address, uInt8 value) break; case AUDV0: + { myAudio.channel0().audv(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case AUDV1: + { myAudio.channel1().audv(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case AUDF0: + { myAudio.channel0().audf(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case AUDF1: + { myAudio.channel1().audf(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case AUDC0: + { myAudio.channel0().audc(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case AUDC1: + { myAudio.channel1().audc(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::AUD); + #endif break; + } case HMOVE: myDelayQueue.push(HMOVE, value, Delay::hmove); break; case COLUBK: - myBackground.setColor(value & 0xFE); + { + value &= 0xFE; + myBackground.setColor(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::BCOL); + #endif break; + } case COLUP0: + { value &= 0xFE; myPlayfield.setColorP0(value); myMissile0.setColor(value); myPlayer0.setColor(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::COL); + #endif break; + } case COLUP1: + { value &= 0xFE; myPlayfield.setColorP1(value); myMissile1.setColor(value); myPlayer1.setColor(value); myShadowRegisters[address] = value; + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::COL); + #endif break; + } case CTRLPF: flushLineCache(); @@ -598,9 +655,10 @@ bool TIA::poke(uInt16 address, uInt8 value) break; case COLUPF: + { flushLineCache(); value &= 0xFE; - if (myPFColorDelay) + if(myPFColorDelay) myDelayQueue.push(COLUPF, value, 1); else { @@ -608,7 +666,13 @@ bool TIA::poke(uInt16 address, uInt8 value) myBall.setColor(value); myShadowRegisters[address] = value; } + #ifdef DEBUGGER_SUPPORT + uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); + if(dataAddr) + mySystem->setAccessFlags(dataAddr, Device::PCOL); + #endif break; + } case PF0: { @@ -616,7 +680,7 @@ bool TIA::poke(uInt16 address, uInt8 value) #ifdef DEBUGGER_SUPPORT uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); if(dataAddr) - mySystem->setAccessFlags(dataAddr, CartDebug::PGFX); + mySystem->setAccessFlags(dataAddr, Device::PGFX); #endif break; } @@ -627,7 +691,7 @@ bool TIA::poke(uInt16 address, uInt8 value) #ifdef DEBUGGER_SUPPORT uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); if(dataAddr) - mySystem->setAccessFlags(dataAddr, CartDebug::PGFX); + mySystem->setAccessFlags(dataAddr, Device::PGFX); #endif break; } @@ -638,7 +702,7 @@ bool TIA::poke(uInt16 address, uInt8 value) #ifdef DEBUGGER_SUPPORT uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); if(dataAddr) - mySystem->setAccessFlags(dataAddr, CartDebug::PGFX); + mySystem->setAccessFlags(dataAddr, Device::PGFX); #endif break; } @@ -706,7 +770,7 @@ bool TIA::poke(uInt16 address, uInt8 value) #ifdef DEBUGGER_SUPPORT uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); if(dataAddr) - mySystem->setAccessFlags(dataAddr, CartDebug::GFX); + mySystem->setAccessFlags(dataAddr, Device::GFX); #endif break; } @@ -719,7 +783,7 @@ bool TIA::poke(uInt16 address, uInt8 value) #ifdef DEBUGGER_SUPPORT uInt16 dataAddr = mySystem->m6502().lastDataAddressForPoke(); if(dataAddr) - mySystem->setAccessFlags(dataAddr, CartDebug::GFX); + mySystem->setAccessFlags(dataAddr, Device::GFX); #endif break; } @@ -965,9 +1029,13 @@ bool TIA::toggleBit(TIABit b, uInt8 mode) mask = b; break; - default: + case 2: mask = (~mySpriteEnabledBits & b); break; + + default: + mask = (mySpriteEnabledBits & b); + break; } mySpriteEnabledBits = (mySpriteEnabledBits & ~b) | mask; @@ -983,9 +1051,11 @@ bool TIA::toggleBit(TIABit b, uInt8 mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool TIA::toggleBits() +bool TIA::toggleBits(bool toggle) { - toggleBit(TIABit(0xFF), mySpriteEnabledBits > 0 ? 0 : 1); + toggleBit(TIABit(0xFF), toggle + ? mySpriteEnabledBits > 0 ? 0 : 1 + : mySpriteEnabledBits); return mySpriteEnabledBits; } @@ -1004,9 +1074,13 @@ bool TIA::toggleCollision(TIABit b, uInt8 mode) mask = b; break; - default: + case 2: mask = (~myCollisionsEnabledBits & b); break; + + default: + mask = (myCollisionsEnabledBits & b); + break; } myCollisionsEnabledBits = (myCollisionsEnabledBits & ~b) | mask; @@ -1022,9 +1096,11 @@ bool TIA::toggleCollision(TIABit b, uInt8 mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool TIA::toggleCollisions() +bool TIA::toggleCollisions(bool toggle) { - toggleCollision(TIABit(0xFF), myCollisionsEnabledBits > 0 ? 0 : 1); + toggleCollision(TIABit(0xFF), toggle + ? myCollisionsEnabledBits > 0 ? 0 : 1 + : myCollisionsEnabledBits); return myCollisionsEnabledBits; } @@ -1143,6 +1219,9 @@ bool TIA::toggleJitter(uInt8 mode) myEnableJitter = !myEnableJitter; break; + case 3: + break; + default: throw runtime_error("invalid argument for toggleJitter"); } @@ -1883,24 +1962,25 @@ void TIA::toggleCollBLPF() #ifdef DEBUGGER_SUPPORT // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::createAccessBase() +void TIA::createAccessArrays() { - myAccessBase.fill(CartDebug::NONE); + myAccessBase.fill(Device::NONE); + myAccessCounter.fill(0); myAccessDelay.fill(TIA_DELAY); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::getAccessFlags(uInt16 address) const +Device::AccessFlags TIA::getAccessFlags(uInt16 address) const { return myAccessBase[address & TIA_MASK]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::setAccessFlags(uInt16 address, uInt8 flags) +void TIA::setAccessFlags(uInt16 address, Device::AccessFlags flags) { // ignore none flag - if (flags != CartDebug::NONE) { - if (flags == CartDebug::WRITE) { + if (flags != Device::NONE) { + if (flags == Device::WRITE) { // the first two write accesses are assumed as initialization if (myAccessDelay[address & TIA_MASK]) myAccessDelay[address & TIA_MASK]--; @@ -1910,4 +1990,38 @@ void TIA::setAccessFlags(uInt16 address, uInt8 flags) myAccessBase[address & TIA_READ_MASK] |= flags; } } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIA::increaseAccessCounter(uInt16 address, bool isWrite) +{ + if(isWrite) + { + // the first two write accesses are assumed as initialization + if(myAccessDelay[address & TIA_MASK]) + myAccessDelay[address & TIA_MASK]--; + else + myAccessCounter[address & TIA_MASK]++; + } + else + myAccessCounter[TIA_SIZE + (address & TIA_READ_MASK)]++; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string TIA::getAccessCounters() const +{ + ostringstream out; + + out << "TIA reads:\n"; + for(uInt16 addr = 0x00; addr < TIA_READ_SIZE; ++addr) + out << Common::Base::HEX4 << addr << "," + << Common::Base::toString(myAccessCounter[TIA_SIZE + addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + out << "TIA writes:\n"; + for(uInt16 addr = 0x00; addr < TIA_SIZE; ++addr) + out << Common::Base::HEX4 << addr << "," + << Common::Base::toString(myAccessCounter[addr], Common::Base::Fmt::_10_8) << ", "; + out << "\n"; + + return out.str(); +} #endif // DEBUGGER_SUPPORT diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 0b3cb4eaf..3b2cbea7c 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -356,23 +356,25 @@ class TIA : public Device disabling a graphical object also disables its collisions. @param mode 1/0 indicates on/off, and values greater than 1 mean - flip the bit from its current state + 2 means flip the bit from its current state + and values greater than 2 mean return current state @return Whether the bit was enabled or disabled */ bool toggleBit(TIABit b, uInt8 mode = 2); - bool toggleBits(); + bool toggleBits(bool toggle = true); /** Enables/disable/toggle the specified (or all) TIA bit collision(s). - @param mode 1/0 indicates on/off, and values greater than 1 mean - flip the collision from its current state + @param mode 1/0 indicates on/off, + 2 means flip the collision from its current state + and values greater than 2 mean return current state @return Whether the collision was enabled or disabled */ bool toggleCollision(TIABit b, uInt8 mode = 2); - bool toggleCollisions(); + bool toggleCollisions(bool toggle = true); /** Enables/disable/toggle/query 'fixed debug colors' mode. @@ -530,6 +532,15 @@ class TIA : public Device */ void updateEmulation(); + #ifdef DEBUGGER_SUPPORT + /** + Query the access counters + + @return The access counters as comma separated string + */ + string getAccessCounters() const override; + #endif + private: /** * During each line, the TIA cycles through these two states. @@ -678,21 +689,28 @@ class TIA : public Device void applyDeveloperSettings(); #ifdef DEBUGGER_SUPPORT - void createAccessBase(); + void createAccessArrays(); /** - * Query the given address type for the associated disassembly flags. + * Query the given address type for the associated access flags. * * @param address The address to query */ - uInt8 getAccessFlags(uInt16 address) const override; + Device::AccessFlags getAccessFlags(uInt16 address) const override; /** - * Change the given address to use the given disassembly flags. + * Change the given address to use the given access flags. * * @param address The address to modify - * @param flags A bitfield of DisasmType directives for the given address + * @param flags A bitfield of AccessType directives for the given address */ - void setAccessFlags(uInt16 address, uInt8 flags) override; + void setAccessFlags(uInt16 address, Device::AccessFlags flags) override; + + /** + Increase the given address's access counter + + @param address The address to modify + */ + void increaseAccessCounter(uInt16 address, bool isWrite) override; #endif // DEBUGGER_SUPPORT private: @@ -896,12 +914,17 @@ class TIA : public Device uInt8 myJitterFactor{0}; static constexpr uInt16 - TIA_SIZE = 0x40, TIA_MASK = TIA_SIZE - 1, TIA_READ_MASK = 0x0f, TIA_BIT = 0x080, TIA_DELAY = 2; + TIA_SIZE = 0x40, TIA_MASK = TIA_SIZE - 1, + TIA_READ_SIZE = 0x10, TIA_READ_MASK = TIA_READ_SIZE - 1, + TIA_BIT = 0x080, TIA_DELAY = 2 * 2; #ifdef DEBUGGER_SUPPORT // The arrays containing information about every byte of TIA // indicating whether and how (RW) it is used. - std::array myAccessBase; + std::array myAccessBase; + // The arrays containing information about every byte of TIA + // indicating how often it is accessed (read and write). + std::array myAccessCounter; // The array used to skip the first two TIA access trackings std::array myAccessDelay; diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx index fa7e50308..443b9c20c 100644 --- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx +++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx @@ -18,8 +18,8 @@ #ifndef TIA_FRAME_LAYOUT_DETECTOR #define TIA_FRAME_LAYOUT_DETECTOR -#include "AbstractFrameManager.hxx" #include "FrameLayout.hxx" +#include "AbstractFrameManager.hxx" /** * This frame manager performs frame layout autodetection. It counts the scanlines diff --git a/src/emucore/tia/frame-manager/FrameManager.cxx b/src/emucore/tia/frame-manager/FrameManager.cxx index 81d8d75d7..477f0fd2f 100644 --- a/src/emucore/tia/frame-manager/FrameManager.cxx +++ b/src/emucore/tia/frame-manager/FrameManager.cxx @@ -236,7 +236,7 @@ void FrameManager::recalculateMetrics() { throw runtime_error("frame manager: invalid TV mode"); } - myHeight = BSPF::clamp(roundf(static_cast(baseHeight) * (1.f - myVSizeAdjust / 100.f)), 0, myFrameLines); + myHeight = BSPF::clamp(roundf(static_cast(baseHeight) * (1.F - myVSizeAdjust / 100.F)), 0, myFrameLines); myYStart = BSPF::clamp(ystartBase + (baseHeight - static_cast(myHeight)) / 2 - myVcenter, 0, myFrameLines); // TODO: why "- 1" here: ??? myMaxVcenter = BSPF::clamp(ystartBase + (baseHeight - static_cast(myHeight)) / 2 - 1, 0, TIAConstants::maxVcenter); diff --git a/src/gui/AboutDialog.cxx b/src/gui/AboutDialog.cxx index 168520138..db088d923 100644 --- a/src/gui/AboutDialog.cxx +++ b/src/gui/AboutDialog.cxx @@ -20,6 +20,8 @@ #include "Version.hxx" #include "Widget.hxx" #include "Font.hxx" +#include "WhatsNewDialog.hxx" + #include "AboutDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -28,44 +30,54 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent, : Dialog(osystem, parent, font, "About Stella") { const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Defaults") + 20, - buttonHeight = font.getLineHeight() + 4; + fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; WidgetArray wid; // Set real dimensions - _w = 55 * fontWidth + 8; - _h = 15 * lineHeight + 20 + _th; + _w = 55 * fontWidth + HBORDER * 2; + _h = _th + 14 * lineHeight + VGAP * 3 + buttonHeight + VBORDER * 2; // Add Previous, Next and Close buttons - xpos = 10; ypos = _h - buttonHeight - 10; + xpos = HBORDER; ypos = _h - buttonHeight - VBORDER; myPrevButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Previous", GuiObject::kPrevCmd); myPrevButton->clearFlags(Widget::FLAG_ENABLED); wid.push_back(myPrevButton); - xpos += buttonWidth + 8; + xpos += buttonWidth + fontWidth; myNextButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Next", GuiObject::kNextCmd); wid.push_back(myNextButton); - xpos = _w - buttonWidth - 10; + xpos = _w - buttonWidth - HBORDER; ButtonWidget* b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Close", GuiObject::kCloseCmd); wid.push_back(b); addCancelWidget(b); - xpos = 5; ypos = 5 + _th; + xpos = HBORDER; ypos = _th + VBORDER + (buttonHeight - fontHeight) / 2; myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2, fontHeight, "", TextAlign::Center); myTitle->setTextColor(kTextColorEm); - xpos = 16; ypos += lineHeight + 4; + int bwidth = font.getStringWidth("What's New" + ELLIPSIS) + fontWidth * 2.5; + myWhatsNewButton = + new ButtonWidget(this, font, _w - HBORDER - bwidth, ypos - (buttonHeight - fontHeight) / 2, + bwidth, buttonHeight, "What's New" + ELLIPSIS, kWhatsNew); + wid.push_back(myWhatsNewButton); + + xpos = HBORDER * 2; ypos += lineHeight + VGAP * 2; for(int i = 0; i < myLinesPerPage; i++) { myDesc.push_back(new StaticTextWidget(this, font, xpos, ypos, _w - xpos * 2, @@ -77,6 +89,11 @@ AboutDialog::AboutDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +AboutDialog::~AboutDialog() +{ +} + // The following commands can be put at the start of a line (all subject to change): // \C, \L, \R -- set center/left/right alignment // \c0 - \c5 -- set a custom color: @@ -254,6 +271,13 @@ void AboutDialog::handleCommand(CommandSender* sender, int cmd, int data, int id displayInfo(); break; + case kWhatsNew: + if(myWhatsNewDialog == nullptr) + myWhatsNewDialog = make_unique(instance(), parent(), _font, + 640 * 0.95, 480 * 0.95); + myWhatsNewDialog->open(); + break; + default: Dialog::handleCommand(sender, cmd, data, 0); } diff --git a/src/gui/AboutDialog.hxx b/src/gui/AboutDialog.hxx index 8dc8bc0bf..fd3ad0a4c 100644 --- a/src/gui/AboutDialog.hxx +++ b/src/gui/AboutDialog.hxx @@ -23,6 +23,7 @@ class DialogContainer; class CommandSender; class ButtonWidget; class StaticTextWidget; +class WhatsNewDialog; #include "Dialog.hxx" @@ -31,7 +32,7 @@ class AboutDialog : public Dialog public: AboutDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font); - virtual ~AboutDialog() = default; + virtual ~AboutDialog(); private: void handleCommand(CommandSender* sender, int cmd, int data, int id) override; @@ -41,6 +42,7 @@ class AboutDialog : public Dialog void loadConfig() override { displayInfo(); } private: + ButtonWidget* myWhatsNewButton{nullptr}; ButtonWidget* myNextButton{nullptr}; ButtonWidget* myPrevButton{nullptr}; @@ -52,6 +54,12 @@ class AboutDialog : public Dialog int myNumPages{4}; int myLinesPerPage{13}; + unique_ptr myWhatsNewDialog; + + enum { + kWhatsNew = 'ADWN' + }; + private: // Following constructors and assignment operators not supported AboutDialog() = delete; diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx deleted file mode 100644 index cb73dee42..000000000 --- a/src/gui/AudioDialog.cxx +++ /dev/null @@ -1,351 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include - -#include "bspf.hxx" - -#include "Console.hxx" -#include "Cart.hxx" -#include "CartDPC.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Font.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "PopUpWidget.hxx" -#include "Settings.hxx" -#include "Sound.hxx" -#include "Widget.hxx" -#include "AudioSettings.hxx" - -#include "AudioDialog.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font) - : Dialog(osystem, parent, font, "Audio settings") -{ - const int VBORDER = 10; - const int HBORDER = 10; - const int INDENT = 20; - const int VGAP = 4; - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(); - int xpos, ypos; - int lwidth = font.getStringWidth("Volume "), - pwidth; - - WidgetArray wid; - VariantList items; - - // Set real dimensions - _w = 48 * fontWidth + HBORDER * 2; - _h = 12 * (lineHeight + VGAP) + VBORDER + _th; - - xpos = HBORDER; ypos = VBORDER + _th; - - // Enable sound - mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Enable sound", kSoundEnableChanged); - wid.push_back(mySoundEnableCheckbox); - ypos += lineHeight + VGAP; - xpos += INDENT; - - // Volume - myVolumeSlider = new SliderWidget(this, font, xpos, ypos, - "Volume", lwidth, 0, 4 * fontWidth, "%"); - myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); - myVolumeSlider->setTickmarkIntervals(4); - wid.push_back(myVolumeSlider); - ypos += lineHeight + VGAP; - - // Mode - items.clear(); - VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); - VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); - VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); - VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); - VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); - myModePopup = new PopUpWidget(this, font, xpos, ypos, - font.getStringWidth("Ultry quality, minimal lag"), lineHeight, - items, "Mode", lwidth, kModeChanged); - wid.push_back(myModePopup); - ypos += lineHeight + VGAP; - xpos += INDENT; - - // Fragment size - pwidth = font.getStringWidth("512 samples") + 7; - lwidth = font.getStringWidth("Resampling quality "); - items.clear(); - VarList::push_back(items, "128 samples", 128); - VarList::push_back(items, "256 samples", 256); - VarList::push_back(items, "512 samples", 512); - VarList::push_back(items, "1k samples", 1024); - VarList::push_back(items, "2k samples", 2048); - VarList::push_back(items, "4K samples", 4096); - myFragsizePopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Fragment size", lwidth); - wid.push_back(myFragsizePopup); - ypos += lineHeight + VGAP; - - // Output frequency - items.clear(); - VarList::push_back(items, "44100 Hz", 44100); - VarList::push_back(items, "48000 Hz", 48000); - VarList::push_back(items, "96000 Hz", 96000); - myFreqPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Sample rate", lwidth); - wid.push_back(myFreqPopup); - ypos += lineHeight + VGAP; - - // Resampling quality - items.clear(); - VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); - VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); - VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); - myResamplingPopup = new PopUpWidget(this, font, xpos, ypos, - pwidth, lineHeight, - items, "Resampling quality ", lwidth); - wid.push_back(myResamplingPopup); - ypos += lineHeight + VGAP; - - // Param 1 - int swidth = pwidth+23; - myHeadroomSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); - myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); - myHeadroomSlider->setTickmarkIntervals(5); - wid.push_back(myHeadroomSlider); - ypos += lineHeight + VGAP; - - // Param 2 - myBufferSizeSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight, - "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); - myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); - myBufferSizeSlider->setTickmarkIntervals(5); - wid.push_back(myBufferSizeSlider); - ypos += lineHeight + VGAP; - - // Stereo sound - xpos -= INDENT; - myStereoSoundCheckbox = new CheckboxWidget(this, font, xpos, ypos, - "Stereo for all ROMs"); - wid.push_back(myStereoSoundCheckbox); - ypos += lineHeight + VGAP; - - myDpcPitch = new SliderWidget(this, font, xpos, ypos, swidth - 16, lineHeight, - "Pitfall II music pitch ", 0, 0, 5 * fontWidth); - myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); - myDpcPitch->setStepValue(100); - myDpcPitch->setTickmarkIntervals(2); - wid.push_back(myDpcPitch); - - // Add Defaults, OK and Cancel buttons - addDefaultsOKCancelBGroup(wid, font); - - addToFocusList(wid); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::loadConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enable sound - mySoundEnableCheckbox->setState(audioSettings.enabled()); - - // Volume - myVolumeSlider->setValue(audioSettings.volume()); - - // Stereo - myStereoSoundCheckbox->setState(audioSettings.stereo()); - - // DPC Pitch - myDpcPitch->setValue(audioSettings.dpcPitch()); - - // Preset / mode - myModePopup->setSelected(static_cast(audioSettings.preset())); - - updateSettingsWithPreset(instance().audioSettings()); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) -{ - // Fragsize - myFragsizePopup->setSelected(audioSettings.fragmentSize()); - - // Output frequency - myFreqPopup->setSelected(audioSettings.sampleRate()); - - // Headroom - myHeadroomSlider->setValue(audioSettings.headroom()); - - // Buffer size - myBufferSizeSlider->setValue(audioSettings.bufferSize()); - - // Resampling quality - myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::saveConfig() -{ - AudioSettings& audioSettings = instance().audioSettings(); - - // Enabled - audioSettings.setEnabled(mySoundEnableCheckbox->getState()); - instance().sound().setEnabled(mySoundEnableCheckbox->getState()); - - // Volume - audioSettings.setVolume(myVolumeSlider->getValue()); - instance().sound().setVolume(myVolumeSlider->getValue()); - - // Stereo - audioSettings.setStereo(myStereoSoundCheckbox->getState()); - - // DPC Pitch - audioSettings.setDpcPitch(myDpcPitch->getValue()); - // update if current cart is Pitfall II - if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") - { - CartridgeDPC& cart = static_cast(instance().console().cartridge()); - cart.setDpcPitch(myDpcPitch->getValue()); - } - - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - audioSettings.setPreset(preset); - - if (preset == AudioSettings::Preset::custom) { - // Fragsize - audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); - audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); - audioSettings.setHeadroom(myHeadroomSlider->getValue()); - audioSettings.setBufferSize(myBufferSizeSlider->getValue()); - audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); - } - - // Only force a re-initialization when necessary, since it can - // be a time-consuming operation - if(instance().hasConsole()) - instance().console().initializeAudio(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::setDefaults() -{ - mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); - myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); - myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); - myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); - myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); - - if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { - myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); - myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); - myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); - myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); - myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); - } - else updatePreset(); - - updateEnabledState(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updateEnabledState() -{ - bool active = mySoundEnableCheckbox->getState(); - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - bool userMode = preset == AudioSettings::Preset::custom; - - myVolumeSlider->setEnabled(active); - myStereoSoundCheckbox->setEnabled(active); - myModePopup->setEnabled(active); - // enable only for Pitfall II cart - myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); - - myFragsizePopup->setEnabled(active && userMode); - myFreqPopup->setEnabled(active && userMode); - myResamplingPopup->setEnabled(active && userMode); - myHeadroomSlider->setEnabled(active && userMode); - myBufferSizeSlider->setEnabled(active && userMode); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::updatePreset() -{ - AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); - - // Make a copy that does not affect the actual settings... - AudioSettings audioSettings = instance().audioSettings(); - audioSettings.setPersistent(false); - // ... and set the requested preset - audioSettings.setPreset(preset); - - updateSettingsWithPreset(audioSettings); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AudioDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch(cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kSoundEnableChanged: - updateEnabledState(); - break; - - case kModeChanged: - updatePreset(); - updateEnabledState(); - break; - - case kHeadroomChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; - myHeadroomSlider->setValueLabel(ss.str()); - break; - } - case kBufferSizeChanged: - { - std::ostringstream ss; - ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; - myBufferSizeSlider->setValueLabel(ss.str()); - break; - } - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/AudioDialog.hxx b/src/gui/AudioDialog.hxx deleted file mode 100644 index b7aa35c65..000000000 --- a/src/gui/AudioDialog.hxx +++ /dev/null @@ -1,77 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#ifndef AUDIO_DIALOG_HXX -#define AUDIO_DIALOG_HXX - -class CommandSender; -class Dialog; -class DialogContainer; -class PopUpWidget; -class SliderWidget; -class StaticTextWidget; -class CheckboxWidget; -class OSystem; -class AudioSettings; - -#include "bspf.hxx" - -class AudioDialog : public Dialog -{ - public: - AudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font); - virtual ~AudioDialog() = default; - - private: - void loadConfig() override; - void saveConfig() override; - void setDefaults() override; - - void updatePreset(); - void updateEnabledState(); - void updateSettingsWithPreset(AudioSettings&); - void handleCommand(CommandSender* sender, int cmd, int data, int id) override; - - private: - enum { - kSoundEnableChanged = 'ADse', - kModeChanged = 'ADmc', - kHeadroomChanged = 'ADhc', - kBufferSizeChanged = 'ADbc' - }; - - CheckboxWidget* mySoundEnableCheckbox{nullptr}; - SliderWidget* myVolumeSlider{nullptr}; - CheckboxWidget* myStereoSoundCheckbox{nullptr}; - PopUpWidget* myModePopup{nullptr}; - PopUpWidget* myFragsizePopup{nullptr}; - PopUpWidget* myFreqPopup{nullptr}; - PopUpWidget* myResamplingPopup{nullptr}; - SliderWidget* myHeadroomSlider{nullptr}; - SliderWidget* myBufferSizeSlider{nullptr}; - SliderWidget* myDpcPitch{nullptr}; - - private: - // Following constructors and assignment operators not supported - AudioDialog() = delete; - AudioDialog(const AudioDialog&) = delete; - AudioDialog(AudioDialog&&) = delete; - AudioDialog& operator=(const AudioDialog&) = delete; - AudioDialog& operator=(AudioDialog&&) = delete; -}; - -#endif diff --git a/src/gui/BrowserDialog.cxx b/src/gui/BrowserDialog.cxx index b64edf525..544ff4518 100644 --- a/src/gui/BrowserDialog.cxx +++ b/src/gui/BrowserDialog.cxx @@ -42,13 +42,19 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _h = max_h; const int lineHeight = font.getLineHeight(), - buttonWidth = font.getStringWidth("Defaults") + 20, - buttonHeight = font.getLineHeight() + 4, - selectHeight = lineHeight + 12; + fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25, + buttonWidth = font.getStringWidth("Base Dir") + fontWidth * 2.5; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + const int BUTTON_GAP = fontWidth; + const int selectHeight = lineHeight + VGAP * 3; int xpos, ypos; ButtonWidget* b; - xpos = 10; ypos = 4 + _th; + xpos = HBORDER; ypos = VBORDER + _th; // Current path - TODO: handle long paths ? StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Path "); @@ -56,14 +62,14 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _w - t->getWidth() - 2 * xpos, lineHeight); _currentPath->setEditable(false); // Add file list - ypos += lineHeight + 8; + ypos += lineHeight + VGAP * 2; _fileList = new FileListWidget(this, font, xpos, ypos, _w - 2 * xpos, - _h - selectHeight - buttonHeight - ypos - 20); + _h - selectHeight - buttonHeight - ypos - VBORDER * 2); _fileList->setEditable(false); addFocusWidget(_fileList); // Add currently selected item - ypos += _fileList->getHeight() + 8; + ypos += _fileList->getHeight() + VGAP * 2; _type = new StaticTextWidget(this, font, xpos, ypos + 2, "Name "); _selected = new EditTextWidget(this, font, xpos + _type->getWidth(), ypos, @@ -71,30 +77,30 @@ BrowserDialog::BrowserDialog(GuiObject* boss, const GUI::Font& font, _selected->setEditable(false); // Buttons - _goUpButton = new ButtonWidget(this, font, 10, _h - buttonHeight - 10, + _goUpButton = new ButtonWidget(this, font, xpos, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Go up", kGoUpCmd); addFocusWidget(_goUpButton); _basedirButton = - new ButtonWidget(this, font, 15 + buttonWidth, _h - buttonHeight - 10, + new ButtonWidget(this, font, _goUpButton->getRight() + BUTTON_GAP, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Base Dir", kBaseDirCmd); addFocusWidget(_basedirButton); #ifndef BSPF_MACOS - b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10, + b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Choose", kChooseCmd); addFocusWidget(b); addOKWidget(b); - b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10, + b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Cancel", GuiObject::kCloseCmd); addFocusWidget(b); addCancelWidget(b); #else - b = new ButtonWidget(this, font, _w - 2 * (buttonWidth + 7), _h - buttonHeight - 10, + b = new ButtonWidget(this, font, _w - (2 * buttonWidth + BUTTON_GAP + HBORDER), _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Cancel", GuiObject::kCloseCmd); addFocusWidget(b); addCancelWidget(b); - b = new ButtonWidget(this, font, _w - (buttonWidth + 10), _h - buttonHeight - 10, + b = new ButtonWidget(this, font, _w - (buttonWidth + HBORDER), _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Choose", kChooseCmd); addFocusWidget(b); addOKWidget(b); diff --git a/src/gui/CheckListWidget.cxx b/src/gui/CheckListWidget.cxx index f228407d4..0e5a46d82 100644 --- a/src/gui/CheckListWidget.cxx +++ b/src/gui/CheckListWidget.cxx @@ -29,7 +29,7 @@ CheckListWidget::CheckListWidget(GuiObject* boss, const GUI::Font& font, // rowheight is determined by largest item on a line, // possibly meaning that number of rows will change - _fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize()); + _fontHeight = std::max(_fontHeight, CheckboxWidget::boxSize(_font)); _rows = h / _fontHeight; // Create a CheckboxWidget for each row in the list @@ -100,7 +100,7 @@ void CheckListWidget::drawWidget(bool hilite) // Draw a thin frame around the list and to separate columns s.frameRect(_x, _y, _w, _h, hilite ? kWidColorHi : kColor); - s.vLine(_x + CheckboxWidget::boxSize() + 5, _y, _y + _h - 1, kColor); + s.vLine(_x + CheckboxWidget::boxSize(_font) + 5, _y, _y + _h - 1, kColor); // Draw the list items for (i = 0, pos = _currentPos; i < _rows && pos < len; i++, pos++) @@ -150,7 +150,7 @@ void CheckListWidget::drawWidget(bool hilite) Common::Rect CheckListWidget::getEditRect() const { const int yoffset = (_selectedItem - _currentPos) * _fontHeight, - xoffset = CheckboxWidget::boxSize() + 10; + xoffset = CheckboxWidget::boxSize(_font) + 10; return Common::Rect(2 + xoffset, 1 + yoffset, _w - (xoffset - 15), _fontHeight + yoffset); diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx index 6aa58a049..27f4bc3cf 100644 --- a/src/gui/ColorWidget.cxx +++ b/src/gui/ColorWidget.cxx @@ -25,9 +25,10 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, int cmd) + int x, int y, int w, int h, int cmd, bool framed) : Widget(boss, font, x, y, w, h), CommandSender(boss), + _framed(framed), _cmd(cmd) { _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; @@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite) FBSurface& s = dialog().surface(); bool onTop = _boss->dialog().isOnTop(); + if(_framed) + { // Draw a thin frame around us. - s.frameRect(_x, _y, _w, _h + 1, kColor); + s.frameRect(_x, _y, _w, _h + 1, kColor); - // Show the currently selected color - s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + // Show the currently selected color + s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } + else + { + s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo); + } // Cross out the grid? if(_crossGrid) diff --git a/src/gui/ColorWidget.hxx b/src/gui/ColorWidget.hxx index 7691ff6ad..9169c2153 100644 --- a/src/gui/ColorWidget.hxx +++ b/src/gui/ColorWidget.hxx @@ -36,7 +36,7 @@ class ColorWidget : public Widget, public CommandSender public: ColorWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h, int cmd = 0); + int x, int y, int w, int h, int cmd = 0, bool framed = true); virtual ~ColorWidget() = default; void setColor(ColorId color); @@ -49,6 +49,7 @@ class ColorWidget : public Widget, public CommandSender protected: ColorId _color{kNone}; + bool _framed{true}; int _cmd{0}; bool _crossGrid{false}; diff --git a/src/gui/ComboDialog.cxx b/src/gui/ComboDialog.cxx index a18e3920b..e8b087c53 100644 --- a/src/gui/ComboDialog.cxx +++ b/src/gui/ComboDialog.cxx @@ -32,7 +32,13 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, : Dialog(boss->instance(), boss->parent(), font, "Add...") { const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(); + fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; WidgetArray wid; @@ -42,10 +48,10 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, pwidth = std::max(font.getStringWidth(s.first), pwidth); // Set real dimensions - _w = 11 * fontWidth + pwidth-4 + 10 * 2; - _h = 10 * (lineHeight + 4) + 10 + _th; - xpos = 10; - ypos = 10 + _th; + _w = 8 * fontWidth + pwidth + PopUpWidget::dropDownWidth(font) + HBORDER * 2; + _h = 8 * (lineHeight + VGAP) + VGAP + buttonHeight + VBORDER * 2 + _th; + xpos = HBORDER; + ypos = VBORDER + _th; // Add event popup for 8 events myEvents.fill(nullptr); @@ -54,7 +60,7 @@ ComboDialog::ComboDialog(GuiObject* boss, const GUI::Font& font, myEvents[idx] = new PopUpWidget(this, font, xpos, ypos, pwidth, lineHeight, combolist, label); wid.push_back(myEvents[idx]); - ypos += lineHeight + 4; + ypos += lineHeight + VGAP; }; ADD_EVENT_POPUP(0, "Event 1 "); ADD_EVENT_POPUP(1, "Event 2 "); diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index d33fe3c57..e4c5f610a 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Console.hxx" +#include "PaletteHandler.hxx" #include "TIA.hxx" #include "Switches.hxx" #include "Dialog.hxx" @@ -33,16 +34,18 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent) : Dialog(osystem, parent, osystem.frameBuffer().font(), "Commands") { - const int HBORDER = 10; - const int VBORDER = 10; - const int HGAP = 8; - const int VGAP = 4; - const int buttonWidth = _font.getStringWidth("Time Machine On") + 16, - buttonHeight = _font.getLineHeight() + 6, - rowHeight = buttonHeight + VGAP; + const int fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25, + buttonWidth = _font.getStringWidth("Time Machine On") + fontWidth * 2; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + const int HGAP = fontWidth; + const int rowHeight = buttonHeight + VGAP; // Set real dimensions - _w = 3 * (buttonWidth + 5) + HBORDER * 2; + _w = 3 * (buttonWidth + HGAP) - HGAP + HBORDER * 2; _h = 6 * rowHeight - VGAP + VBORDER * 2 + _th; ButtonWidget* bw = nullptr; WidgetArray wid; @@ -65,7 +68,7 @@ CommandDialog::CommandDialog(OSystem& osystem, DialogContainer& parent) wid.push_back(myColorButton); myLeftDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); wid.push_back(myLeftDiffButton); - myRightDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); + myRightDiffButton = ADD_CD_BUTTON("", kRightDiffCmd); wid.push_back(myRightDiffButton); // Column 2 @@ -196,12 +199,12 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, // Column 3 case kFormatCmd: - instance().console().toggleFormat(); + instance().console().selectFormat(); updateTVFormat(); break; case kPaletteCmd: - instance().console().togglePalette(); + instance().frameBuffer().tiaSurface().paletteHandler().cyclePalette(); updatePalette(); break; @@ -267,11 +270,13 @@ void CommandDialog::updatePalette() string palette, label; palette = instance().settings().getString("palette"); - if(BSPF::equalsIgnoreCase(palette, "standard")) + if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_STANDARD)) label = "Stella Palette"; - else if(BSPF::equalsIgnoreCase(palette, "z26")) + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_Z26)) label = "Z26 Palette"; - else + else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_USER)) label = "User Palette"; + else + label = "Custom Palette"; myPaletteButton->setLabel(label); } diff --git a/src/gui/CommandMenu.cxx b/src/gui/CommandMenu.cxx index a45d99062..3cd687ee2 100644 --- a/src/gui/CommandMenu.cxx +++ b/src/gui/CommandMenu.cxx @@ -16,6 +16,8 @@ //============================================================================ #include "Dialog.hxx" +#include "OSystem.hxx" +#include "Settings.hxx" #include "CommandDialog.hxx" #include "MinUICommandDialog.hxx" #include "CommandMenu.hxx" diff --git a/src/gui/ConsoleBFont.hxx b/src/gui/ConsoleBFont.hxx index c47d4e375..b55797a89 100644 --- a/src/gui/ConsoleBFont.hxx +++ b/src/gui/ConsoleBFont.hxx @@ -42,6 +42,41 @@ namespace GUI { // Font character bitmap data. static const uInt16 consoleB_font_bits[] = { // NOLINT : too complicated to convert + /* MODIFIED + Character 28 (0x1c): + width 8 + bbx ( 8, 13, 0, -2 ) + + +--------+ + | | + | XXXX | + | XX XX | + | XX XX | + | XX XX | + | XXXX | + | | + | | + | | + | | + | | + | | + | | + +--------+ + */ + 0x0000, + 0b0011110000000000, + 0b0110011000000000, + 0b0110011000000000, + 0b0110011000000000, + 0b0011110000000000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + /* MODIFIED Character 29 (0x1d): @@ -3386,8 +3421,8 @@ static const FontDesc consoleBDesc = { 13, 8, 13, 0, -2, 11, - 29, - 98, + 28, + 99, consoleB_font_bits, nullptr, /* no encode table*/ nullptr, /* fixed width*/ diff --git a/src/gui/ConsoleMediumBFont.hxx b/src/gui/ConsoleMediumBFont.hxx index 63116d64e..9c8081619 100644 --- a/src/gui/ConsoleMediumBFont.hxx +++ b/src/gui/ConsoleMediumBFont.hxx @@ -42,6 +42,45 @@ namespace GUI { // Font character bitmap data. static const uInt16 consoleMediumB_font_bits[] = { // NOLINT : too complicated to convert + /* MODIFIED + Character 28 (0x1c): ellipsis + width 9 + bbx ( 9, 15, 0, -3 ) + + +---------+ + | | + | | + | XXXX | + | XX XX | + | XX XX | + | XX XX | + | XXXX | + | | + | | + | | + | | + | | + | | + | | + | | + +---------+ + */ + 0x0000, + 0x0000, + 0b0011110000000000, + 0b0110011000000000, + 0b0110011000000000, + 0b0110011000000000, + 0b0011110000000000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + /* MODIFIED Character 29 (0x1d): ellipsis width 9 @@ -3777,8 +3816,8 @@ static const FontDesc consoleMediumBDesc = { 15, 9, 15, 0, -3, 12, - 29, - 98, + 28, + 99, consoleMediumB_font_bits, nullptr, /* no encode table*/ nullptr, /* fixed width*/ diff --git a/src/gui/ContextMenu.cxx b/src/gui/ContextMenu.cxx index 11e09e475..41f049ba2 100644 --- a/src/gui/ContextMenu.cxx +++ b/src/gui/ContextMenu.cxx @@ -23,6 +23,7 @@ #include "Dialog.hxx" #include "DialogContainer.hxx" #include "ScrollBarWidget.hxx" +#include "PopUpWidget.hxx" #include "ContextMenu.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -35,6 +36,7 @@ ContextMenu::ContextMenu(GuiObject* boss, const GUI::Font& font, _maxWidth(width) { addItems(items); + setArrows(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -49,7 +51,7 @@ void ContextMenu::addItems(const VariantList& items) maxwidth = std::max(maxwidth, _font.getStringWidth(e.first)); _x = _y = 0; - _w = maxwidth + 23; + _w = maxwidth + PopUpWidget::dropDownWidth(_font); // 23; _h = 1; // recalculate this in ::recalc() _scrollUpColor = _firstEntry > 0 ? kScrollColor : kColor; @@ -181,7 +183,7 @@ bool ContextMenu::sendSelectionUp() return false; _selectedItem--; - sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, -1); + sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, _id); return true; } @@ -192,7 +194,7 @@ bool ContextMenu::sendSelectionDown() return false; _selectedItem++; - sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, -1); + sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, _id); return true; } @@ -203,7 +205,7 @@ bool ContextMenu::sendSelectionFirst() return false; _selectedItem = 0; - sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, -1); + sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, _id); return true; } @@ -214,7 +216,7 @@ bool ContextMenu::sendSelectionLast() return false; _selectedItem = int(_entries.size()) - 1; - sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, -1); + sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, _id); return true; } @@ -375,7 +377,7 @@ void ContextMenu::sendSelection() // Send any command associated with the selection _selectedItem = item; - sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, -1); + sendCommand(_cmd ? _cmd : ContextMenu::kItemSelectedCmd, _selectedItem, _id); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -509,7 +511,7 @@ void ContextMenu::scrollDown(int distance) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ContextMenu::drawDialog() +void ContextMenu::setArrows() { static constexpr std::array up_arrow = { 0b00011000, @@ -532,6 +534,55 @@ void ContextMenu::drawDialog() 0b00011000 }; + static constexpr std::array up_arrow_large = { + 0b000001100000, + 0b000001100000, + 0b000011110000, + 0b000011110000, + 0b000111111000, + 0b000111111000, + 0b001111111100, + 0b001111111100, + 0b011111111110, + 0b011111111110, + 0b111111111111, + 0b111111111111 + }; + static constexpr std::array down_arrow_large = { + 0b111111111111, + 0b111111111111, + 0b011111111110, + 0b011111111110, + 0b001111111100, + 0b001111111100, + 0b000111111000, + 0b000111111000, + 0b000011110000, + 0b000011110000, + 0b000001100000, + 0b000001100000 + }; + + if(_font.getFontHeight() < 24) + { + _textOfs = 2; + _arrowSize = 8; + _upImg = up_arrow.data(); + _downImg = down_arrow.data(); + } + else + { + _textOfs = 4; + _arrowSize = 12; + _upImg = up_arrow_large.data(); + _downImg = down_arrow_large.data(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ContextMenu::drawDialog() +{ + // Normally we add widgets and let Dialog::draw() take care of this // logic. But for some reason, this Dialog was written differently // by the ScummVM guys, so I'm not going to mess with it. @@ -549,7 +600,7 @@ void ContextMenu::drawDialog() if(_showScroll) { s.hLine(x, y+_rowHeight-1, w+2, kColor); - s.drawBitmap(up_arrow.data(), ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, 8); + s.drawBitmap(_upImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollUpColor, _arrowSize); y += _rowHeight; offset--; } @@ -558,7 +609,7 @@ void ContextMenu::drawDialog() { bool hilite = offset == current; if(hilite) s.fillRect(x, y, w, _rowHeight, kTextColorHi); - s.drawString(_font, _entries[i].first, x + 1, y + 2, w, + s.drawString(_font, _entries[i].first, x + _textOfs, y + 2, w, !hilite ? kTextColor : kTextColorInv); y += _rowHeight; } @@ -567,7 +618,7 @@ void ContextMenu::drawDialog() if(_showScroll) { s.hLine(x, y, w+2, kColor); - s.drawBitmap(down_arrow.data(), ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, 8); + s.drawBitmap(_downImg, ((_w-_x)>>1)-4, (_rowHeight>>1)+y-4, _scrollDnColor, _arrowSize); } setDirty(); diff --git a/src/gui/ContextMenu.hxx b/src/gui/ContextMenu.hxx index 28d485f1a..221b90a30 100644 --- a/src/gui/ContextMenu.hxx +++ b/src/gui/ContextMenu.hxx @@ -45,6 +45,9 @@ class ContextMenu : public Dialog, public CommandSender const VariantList& items, int cmd = 0, int width = 0); virtual ~ContextMenu() = default; + /** Set the parent widget's ID */ + void setID(uInt32 id) { _id = id; } + /** Add the given items to the widget. */ void addItems(const VariantList& items); @@ -92,6 +95,7 @@ class ContextMenu : public Dialog, public CommandSender bool handleJoyHat(int stick, int hat, JoyHatDir vahdirlue, int button) override; void handleEvent(Event::Type e); + void setArrows(); void drawDialog() override; void recalc(const Common::Rect& image); @@ -121,10 +125,16 @@ class ContextMenu : public Dialog, public CommandSender ColorId _scrollUpColor{kColor}, _scrollDnColor{kColor}; int _cmd{0}; + int _id{-1}; uInt32 _xorig{0}, _yorig{0}; uInt32 _maxWidth{0}; + int _textOfs{0}; + int _arrowSize{0}; + const uInt32* _upImg{nullptr}; + const uInt32* _downImg{nullptr}; + private: // Following constructors and assignment operators not supported ContextMenu() = delete; diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx index 4d6924f11..336c5e1e8 100644 --- a/src/gui/DeveloperDialog.cxx +++ b/src/gui/DeveloperDialog.cxx @@ -39,7 +39,6 @@ #include "M6502.hxx" #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" - #include "CartDebug.hxx" #include "DebuggerDialog.hxx" #endif #include "DeveloperDialog.hxx" @@ -49,18 +48,26 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h) : Dialog(osystem, parent, font, "Developer settings") { - const int VGAP = 4; const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() + 4; + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; // Set real dimensions - setSize(54 * fontWidth + 10, 16 * (lineHeight + VGAP) + 14 + _th, max_w, max_h); + setSize(53 * fontWidth + HBORDER * 2, + _th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, + max_w, max_h); // The tab widget - xpos = 2; ypos = 4; - myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2 * xpos, _h - _th - buttonHeight - 16 - ypos); + xpos = 2; ypos = VGAP; + myTab = new TabWidget(this, font, xpos, ypos + _th, + _w - 2 * xpos, + _h - _th - VGAP - buttonHeight - VBORDER * 2); addTabWidget(myTab); addEmulationTab(font); @@ -80,12 +87,15 @@ DeveloperDialog::DeveloperDialog(OSystem& osystem, DialogContainer& parent, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addEmulationTab(const GUI::Font& font) { - const int HBORDER = 10; - const int INDENT = 16+4; - const int VBORDER = 8; - const int VGAP = 4; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + int ypos = VBORDER; - int lineHeight = font.getLineHeight(); WidgetArray wid; VariantList items; int tabID = myTab->addTab(" Emulation ", TabWidget::AUTO_WIDTH); @@ -101,8 +111,15 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) wid.push_back(r); ypos += lineHeight + VGAP * 1; - myFrameStatsWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, "Console info overlay"); + myFrameStatsWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1, + "Console info overlay"); wid.push_back(myFrameStatsWidget); + + + myDetectedInfoWidget = new CheckboxWidget(myTab, font, + myFrameStatsWidget->getRight() + fontWidth * 2.5, ypos + 1, + "Detected settings info"); + wid.push_back(myDetectedInfoWidget); ypos += lineHeight + VGAP; // 2600/7800 mode @@ -137,13 +154,13 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) myRandomizeCPULabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, "Randomize CPU "); wid.push_back(myRandomizeCPULabel); - int xpos = myRandomizeCPULabel->getRight() + 10; + int xpos = myRandomizeCPULabel->getRight() + fontWidth * 1.25; for(int i = 0; i < 5; ++i) { myRandomizeCPUWidget[i] = new CheckboxWidget(myTab, font, xpos, ypos + 1, ourCPUregs[i], kRandCPUID); wid.push_back(myRandomizeCPUWidget[i]); - xpos += CheckboxWidget::boxSize() + font.getStringWidth("XX") + 20; + xpos += CheckboxWidget::boxSize(font) + font.getStringWidth("XX") + fontWidth * 2.5; } ypos += lineHeight + VGAP; @@ -183,12 +200,15 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addTiaTab(const GUI::Font& font) { - const int HBORDER = 10; - const int INDENT = 16 + 4; - const int VBORDER = 8; - const int VGAP = 4; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + int ypos = VBORDER; - int lineHeight = font.getLineHeight(); int pwidth = font.getStringWidth("Faulty Cosmic Ark stars"); WidgetArray wid; VariantList items; @@ -251,8 +271,9 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font) wid.push_back(myPFColorWidget); ypos += lineHeight + VGAP * 1; - mySwapLabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, - "Delayed VDEL" + ELLIPSIS + " swap for"); + ostringstream ss; + ss << "Delayed VDEL" << ELLIPSIS << " swap for"; + mySwapLabel = new StaticTextWidget(myTab, font, HBORDER + INDENT * 2, ypos + 1, ss.str()); wid.push_back(mySwapLabel); ypos += lineHeight + VGAP * 1; @@ -269,13 +290,15 @@ void DeveloperDialog::addTiaTab(const GUI::Font& font) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DeveloperDialog::addVideoTab(const GUI::Font& font) { - const int HBORDER = 10; - const int INDENT = 16 + 4; - const int VBORDER = 8; - const int VGAP = 4; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + int ypos = VBORDER; - int lineHeight = font.getLineHeight(); - int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(); int lwidth = font.getStringWidth("Intensity "); int pwidth = font.getMaxCharWidth() * 6; WidgetArray wid; @@ -341,7 +364,7 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font) myDbgColour[idx] = new PopUpWidget(myTab, font, x, ypos - 1, pwidth, lineHeight, items, desc, lwidth, dbg_cmds[idx]); wid.push_back(myDbgColour[idx]); - x += myDbgColour[idx]->getWidth() + 10; + x += myDbgColour[idx]->getWidth() + fontWidth * 1.25; myDbgColourSwatch[idx] = new ColorWidget(myTab, font, x, ypos - 1, uInt32(2 * lineHeight), lineHeight); ypos += lineHeight + VGAP * 1; @@ -356,8 +379,11 @@ void DeveloperDialog::addVideoTab(const GUI::Font& font) // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); - ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10; - new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Colors identical for player and developer settings"); + ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; + lwidth = infofont.getStringWidth("(*) Colors identical for player and developer settings"); + new StaticTextWidget(myTab, infofont, HBORDER, ypos, + std::min(lwidth, _w - HBORDER * 2), infofont.getFontHeight(), + "(*) Colors identical for player and developer settings"); // Add items for tab 2 addToFocusList(wid, myTab, tabID); @@ -404,37 +430,41 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) "30m", "60m" }; - const int HBORDER = 10; - const int INDENT = 16+4; - const int VBORDER = 8; - const int VGAP = 4; - int ypos = VBORDER; - int lineHeight = font.getLineHeight(), - fontHeight = font.getFontHeight(), - fontWidth = font.getMaxCharWidth(), - lwidth = fontWidth * 11; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + + int xpos = HBORDER, + ypos = VBORDER, + lwidth = fontWidth * 11; WidgetArray wid; VariantList items; int tabID = myTab->addTab(" Time Machine ", TabWidget::AUTO_WIDTH); // settings set mySettingsGroupTM = new RadioButtonGroup(); - RadioButtonWidget* r = new RadioButtonWidget(myTab, font, HBORDER, ypos + 1, + RadioButtonWidget* r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, "Player settings", mySettingsGroupTM, kPlrSettings); wid.push_back(r); ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, HBORDER, ypos + 1, + r = new RadioButtonWidget(myTab, font, xpos, ypos + 1, "Developer settings", mySettingsGroupTM, kDevSettings); wid.push_back(r); + xpos += INDENT; ypos += lineHeight + VGAP * 1; - myTimeMachineWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT, ypos + 1, + myTimeMachineWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Time Machine", kTimeMachine); wid.push_back(myTimeMachineWidget); + xpos += CheckboxWidget::prefixSize(font); ypos += lineHeight + VGAP; int swidth = fontWidth * 12 + 5; // width of PopUpWidgets below - myStateSizeWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight, + myStateSizeWidget = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, "Buffer size (*) ", 0, kSizeChanged, lwidth, " states"); myStateSizeWidget->setMinValue(20); #ifdef RETRON77 @@ -447,7 +477,7 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) wid.push_back(myStateSizeWidget); ypos += lineHeight + VGAP; - myUncompressedWidget = new SliderWidget(myTab, font, HBORDER + INDENT * 2, ypos - 1, swidth, lineHeight, + myUncompressedWidget = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, "Uncompressed size ", 0, kUncompressedChanged, lwidth, " states"); myUncompressedWidget->setMinValue(0); #ifdef RETRON77 @@ -464,7 +494,7 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) for(int i = 0; i < NUM_INTERVALS; ++i) VarList::push_back(items, INTERVALS[i], INT_SETTINGS[i]); int pwidth = font.getStringWidth("10 seconds"); - myStateIntervalWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth, + myStateIntervalWidget = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Interval ", 0, kIntervalChanged); wid.push_back(myStateIntervalWidget); ypos += lineHeight + VGAP; @@ -472,37 +502,17 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font) items.clear(); for(int i = 0; i < NUM_HORIZONS; ++i) VarList::push_back(items, HORIZONS[i], HOR_SETTINGS[i]); - myStateHorizonWidget = new PopUpWidget(myTab, font, HBORDER + INDENT * 2, ypos, pwidth, + myStateHorizonWidget = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Horizon ~ ", 0, kHorizonChanged); wid.push_back(myStateHorizonWidget); - ypos += lineHeight + VGAP * 2; - new StaticTextWidget(myTab, font, HBORDER, ypos + 1, - "When entering/exiting emulation:"); - ypos += lineHeight + VGAP; - mySaveOnExitGroup = new RadioButtonGroup(); - r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1, - "Do nothing", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1, - "Save current state in current slot", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - r = new RadioButtonWidget(myTab, font, HBORDER + INDENT, ypos + 1, - "Load/save all Time Machine states", mySaveOnExitGroup); - wid.push_back(r); - ypos += lineHeight + VGAP; - - - myAutoSlotWidget = new CheckboxWidget(myTab, font, HBORDER, ypos + 1, "Automatically change save state slots"); - wid.push_back(myAutoSlotWidget); - ypos += lineHeight + VGAP; - // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); - ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10; - new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Any size change clears the buffer"); + ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; + lwidth = infofont.getStringWidth("(*) Any size change clears the buffer"); + new StaticTextWidget(myTab, infofont, HBORDER, ypos, + std::min(lwidth, _w - HBORDER * 2), infofont.getFontHeight(), + "(*) Any size change clears the buffer"); addToFocusList(wid, myTab, tabID); } @@ -514,14 +524,14 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) WidgetArray wid; #ifdef DEBUGGER_SUPPORT - const int HBORDER = 10; - const int VBORDER = 8; - const int VGAP = 4; + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; VariantList items; - int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(), - lineHeight = font.getLineHeight(); int xpos, ypos, pwidth; const Common::Size& ds = instance().frameBuffer().desktopSize(); @@ -538,7 +548,7 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) new PopUpWidget(myTab, font, HBORDER, ypos + 1, pwidth, lineHeight, items, "Font size (*) ", 0, kDFontSizeChanged); wid.push_back(myDebuggerFontSize); - ypos += lineHeight + 4; + ypos += lineHeight + VGAP; // Font style (bold label vs. text, etc) items.clear(); @@ -581,8 +591,8 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font) // Add message concerning usage const GUI::Font& infofont = instance().frameBuffer().infoFont(); - ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10; - new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Changes require a ROM reload"); + ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER; + new StaticTextWidget(myTab, infofont, HBORDER, ypos, "(*) Change requires a ROM reload"); #if defined(DEBUGGER_SUPPORT) && defined(WINDOWED_SUPPORT) // Debugger is only realistically available in windowed modes 800x600 or greater @@ -608,6 +618,7 @@ void DeveloperDialog::loadSettings(SettingsSet set) const string& prefix = devSettings ? "dev." : "plr."; myFrameStats[set] = instance().settings().getBool(prefix + "stats"); + myDetectedInfo[set] = instance().settings().getBool(prefix + "detectedinfo"); myConsole[set] = instance().settings().getString(prefix + "console") == "7800" ? 1 : 0; // Randomization myRandomBank[set] = instance().settings().getBool(prefix + "bankrandom"); @@ -650,8 +661,6 @@ void DeveloperDialog::loadSettings(SettingsSet set) myUncompressed[set] = instance().settings().getInt(prefix + "tm.uncompressed"); myStateInterval[set] = instance().settings().getString(prefix + "tm.interval"); myStateHorizon[set] = instance().settings().getString(prefix + "tm.horizon"); - - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -661,6 +670,7 @@ void DeveloperDialog::saveSettings(SettingsSet set) const string& prefix = devSettings ? "dev." : "plr."; instance().settings().setValue(prefix + "stats", myFrameStats[set]); + instance().settings().setValue(prefix + "detectedinfo", myDetectedInfo[set]); instance().settings().setValue(prefix + "console", myConsole[set] == 1 ? "7800" : "2600"); if(instance().hasConsole()) instance().eventHandler().set7800Mode(); @@ -723,6 +733,7 @@ void DeveloperDialog::saveSettings(SettingsSet set) void DeveloperDialog::getWidgetStates(SettingsSet set) { myFrameStats[set] = myFrameStatsWidget->getState(); + myDetectedInfo[set] = myDetectedInfoWidget->getState(); myConsole[set] = myConsoleWidget->getSelected() == 1; // Randomization myRandomBank[set] = myRandomBankWidget->getState(); @@ -774,6 +785,7 @@ void DeveloperDialog::getWidgetStates(SettingsSet set) void DeveloperDialog::setWidgetStates(SettingsSet set) { myFrameStatsWidget->setState(myFrameStats[set]); + myDetectedInfoWidget->setState(myDetectedInfo[set]); myConsoleWidget->setSelectedIndex(myConsole[set]); // Randomization myRandomBankWidget->setState(myRandomBank[set]); @@ -843,12 +855,6 @@ void DeveloperDialog::loadConfig() // Debug colours handleDebugColours(instance().settings().getString("tia.dbgcolors")); - // Save on exit - string saveOnExit = instance().settings().getString("saveonexit"); - mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); - // Automatically change save state slots - myAutoSlotWidget->setState(instance().settings().getBool("autoslot")); - #ifdef DEBUGGER_SUPPORT uInt32 w, h; @@ -925,13 +931,6 @@ void DeveloperDialog::saveConfig() instance().state().setRewindMode(myTimeMachineWidget->getState() ? StateManager::Mode::TimeMachine : StateManager::Mode::Off); - // Save on exit - int saveOnExit = mySaveOnExitGroup->getSelected(); - instance().settings().setValue("saveonexit", - saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); - // Automatically change save state slots - instance().settings().setValue("autoslot", myAutoSlotWidget->getState()); - #ifdef DEBUGGER_SUPPORT // Debugger font style instance().settings().setValue("dbg.fontstyle", @@ -967,6 +966,7 @@ void DeveloperDialog::setDefaults() { case 0: // Emulation myFrameStats[set] = devSettings ? true : false; + myDetectedInfo[set] = devSettings ? true : false; myConsole[set] = 0; // Randomization myRandomBank[set] = devSettings ? true : false; @@ -1022,8 +1022,6 @@ void DeveloperDialog::setDefaults() myStateHorizon[set] = devSettings ? "30s" : "10m"; setWidgetStates(set); - mySaveOnExitGroup->setSelected(0); - myAutoSlotWidget->setState(false); break; case 4: // Debugger options diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx index ddee5468d..8dd2dc4e2 100644 --- a/src/gui/DeveloperDialog.hxx +++ b/src/gui/DeveloperDialog.hxx @@ -90,6 +90,7 @@ class DeveloperDialog : public Dialog // Emulator widgets RadioButtonGroup* mySettingsGroupEmulation{nullptr}; CheckboxWidget* myFrameStatsWidget{nullptr}; + CheckboxWidget* myDetectedInfoWidget{nullptr}; PopUpWidget* myConsoleWidget{nullptr}; StaticTextWidget* myLoadingROMLabel{nullptr}; CheckboxWidget* myRandomBankWidget{nullptr}; @@ -135,8 +136,6 @@ class DeveloperDialog : public Dialog SliderWidget* myUncompressedWidget{nullptr}; PopUpWidget* myStateIntervalWidget{nullptr}; PopUpWidget* myStateHorizonWidget{nullptr}; - RadioButtonGroup* mySaveOnExitGroup{nullptr}; - CheckboxWidget* myAutoSlotWidget{nullptr}; #ifdef DEBUGGER_SUPPORT // Debugger UI widgets @@ -150,6 +149,7 @@ class DeveloperDialog : public Dialog bool mySettings; // Emulator sets std::array myFrameStats; + std::array myDetectedInfo; std::array myConsole; std::array myRandomBank; std::array myRandomizeRAM; diff --git a/src/gui/Dialog.cxx b/src/gui/Dialog.cxx index a14cb5614..85c95349f 100644 --- a/src/gui/Dialog.cxx +++ b/src/gui/Dialog.cxx @@ -139,7 +139,7 @@ void Dialog::setTitle(const string& title) if(title.empty()) _th = 0; else - _th = _font.getLineHeight() + 4; + _th = _font.getLineHeight() * 1.25; _h += _th; } @@ -383,7 +383,8 @@ void Dialog::drawDialog() if(_th) { s.fillRect(_x, _y, _w, _th, _onTop ? kColorTitleBar : kColorTitleBarLo); - s.drawString(_font, _title, _x + 10, _y + 2 + 1, _font.getStringWidth(_title), + s.drawString(_font, _title, _x + _font.getMaxCharWidth() * 1.25, _y + _font.getFontHeight() / 6, + _font.getStringWidth(_title), _onTop ? kColorTitleText : kColorTitleTextLo); } } @@ -766,20 +767,44 @@ Widget* Dialog::findWidget(int x, int y) const return Widget::findWidgetInChain(_firstWidget, x, y); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Dialog::addOKBGroup(WidgetArray& wid, const GUI::Font& font, + const string& okText, int buttonWidth) +{ + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int BTN_BORDER = fontWidth * 2.5; + const int BUTTON_GAP = fontWidth; + + buttonWidth = fontWidth * 6 + BTN_BORDER; + buttonWidth = std::max(buttonWidth, font.getStringWidth(okText) + BTN_BORDER); + + _w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w); + + addOKWidget(new ButtonWidget(this, font, (_w - buttonWidth) / 2, + _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, okText, GuiObject::kCloseCmd)); + wid.push_back(_okWidget); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Dialog::addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, const string& okText, const string& cancelText, bool focusOKButton, int buttonWidth) { - const int HBORDER = 10; - const int VBORDER = 10; - const int BTN_BORDER = 20; - const int BUTTON_GAP = 8; + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int BTN_BORDER = fontWidth * 2.5; + const int BUTTON_GAP = fontWidth; buttonWidth = std::max(buttonWidth, std::max(font.getStringWidth("Defaults"), std::max(font.getStringWidth(okText), font.getStringWidth(cancelText))) + BTN_BORDER); - int buttonHeight = Dialog::buttonHeight(font); _w = std::max(HBORDER * 2 + buttonWidth * 2 + BUTTON_GAP, _w); @@ -817,11 +842,13 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, const string& defaultsText, bool focusOKButton) { - const int HBORDER = 10; - const int VBORDER = 10; - const int BTN_BORDER = 20; - int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; - int buttonHeight = Dialog::buttonHeight(font); + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int BTN_BORDER = fontWidth * 2.5; + const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); @@ -831,9 +858,31 @@ void Dialog::addDefaultsOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int Dialog::buttonHeight(const GUI::Font& font) const +void Dialog::addDefaultsExtraOKCancelBGroup( + WidgetArray& wid, const GUI::Font& font, + const string& extraText, int extraCmd, + const string& okText, const string& cancelText, const string& defaultsText, + bool focusOKButton) { - return font.getLineHeight() + 4; + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int BTN_BORDER = fontWidth * 2.5; + const int BUTTON_GAP = fontWidth; + const int buttonWidth = font.getStringWidth(defaultsText) + BTN_BORDER; + + addDefaultWidget(new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, + buttonWidth, buttonHeight, defaultsText, GuiObject::kDefaultsCmd)); + wid.push_back(_defaultWidget); + + wid.push_back(new ButtonWidget(this, font, HBORDER + buttonWidth + BUTTON_GAP, + _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, + extraText, extraCmd) + ); + + addOKCancelBGroup(wid, font, okText, cancelText, focusOKButton, buttonWidth); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/Dialog.hxx b/src/gui/Dialog.hxx index 2aa9d9727..43c957b0b 100644 --- a/src/gui/Dialog.hxx +++ b/src/gui/Dialog.hxx @@ -146,6 +146,11 @@ class Dialog : public GuiObject Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any + + void addOKBGroup(WidgetArray& wid, const GUI::Font& font, + const string& okText = "OK", + int buttonWidth = 0); + void addOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, const string& okText = "OK", const string& cancelText = "Cancel", @@ -159,7 +164,16 @@ class Dialog : public GuiObject bool focusOKButton = true); int buttonHeight(const GUI::Font& font) const; - void processCancelWithoutWidget(bool state) { _processCancel = state; } + // NOTE: This method, and the three above it, are due to be refactored at some + // point, since the parameter list is kind of getting ridiculous + void addDefaultsExtraOKCancelBGroup(WidgetArray& wid, const GUI::Font& font, + const string& extraText, int extraCmd, + const string& okText = "OK", + const string& cancelText = "Cancel", + const string& defaultsText = "Defaults", + bool focusOKButton = true); + + void processCancelWithoutWidget(bool state = true) { _processCancel = state; } virtual void processCancel() { close(); } /** Define the size (allowed) for the dialog. */ diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx index b60faf6d4..950d71c06 100644 --- a/src/gui/DialogContainer.cxx +++ b/src/gui/DialogContainer.cxx @@ -384,4 +384,3 @@ void DialogContainer::reset() uInt64 DialogContainer::_DOUBLE_CLICK_DELAY = 500; uInt64 DialogContainer::_REPEAT_INITIAL_DELAY = 400; uInt64 DialogContainer::_REPEAT_SUSTAIN_DELAY = 50; - diff --git a/src/gui/EditTextWidget.cxx b/src/gui/EditTextWidget.cxx index 09c9f3106..ff53ced5a 100644 --- a/src/gui/EditTextWidget.cxx +++ b/src/gui/EditTextWidget.cxx @@ -29,6 +29,15 @@ EditTextWidget::EditTextWidget(GuiObject* boss, const GUI::Font& font, _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS; EditableWidget::startEditMode(); // We're always in edit mode + + if(_font.getFontHeight() < 24) + { + _textOfs = 3; + } + else + { + _textOfs = 5; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -92,7 +101,7 @@ void EditTextWidget::drawWidget(bool hilite) // Draw the text adjustOffset(); - s.drawString(_font, editString(), _x + 2, _y + 2, getEditRect().w(), getEditRect().h(), + s.drawString(_font, editString(), _x + _textOfs, _y + 2, getEditRect().w(), getEditRect().h(), _changed && onTop && isEnabled() ? kDbgChangedTextColor : onTop && isEnabled() ? _textcolor : kColor, @@ -105,7 +114,7 @@ void EditTextWidget::drawWidget(bool hilite) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Common::Rect EditTextWidget::getEditRect() const { - return Common::Rect(2, 1, _w - 2, _h); + return Common::Rect(_textOfs, 1, _w - _textOfs, _h); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/EditTextWidget.hxx b/src/gui/EditTextWidget.hxx index 50f8bfdc8..c7a346804 100644 --- a/src/gui/EditTextWidget.hxx +++ b/src/gui/EditTextWidget.hxx @@ -21,7 +21,6 @@ #include "Rect.hxx" #include "EditableWidget.hxx" - /* EditTextWidget */ class EditTextWidget : public EditableWidget { @@ -32,6 +31,18 @@ class EditTextWidget : public EditableWidget void setText(const string& str, bool changed = false) override; + // Get total width of widget + static int calcWidth(const GUI::Font& font, int length = 0) + { + return length * font.getMaxCharWidth() + + (font.getFontHeight() < 24 ? 3 * 2 : 5 * 2); + } + // Get total width of widget + static int calcWidth(const GUI::Font& font, const string& str) + { + return calcWidth(font, int(str.length())); + } + protected: void drawWidget(bool hilite) override; void lostFocusWidget() override; @@ -49,6 +60,7 @@ class EditTextWidget : public EditableWidget protected: string _backupString; bool _changed{false}; + int _textOfs{0}; private: // Following constructors and assignment operators not supported diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx new file mode 100644 index 000000000..dcbb42859 --- /dev/null +++ b/src/gui/EmulationDialog.cxx @@ -0,0 +1,285 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "OSystem.hxx" +#include "Console.hxx" +#include "FrameBuffer.hxx" +#include "RadioButtonWidget.hxx" +#include "TIASurface.hxx" + +#include "EmulationDialog.hxx" + +namespace { + // Emulation speed is a positive float that multiplies the framerate. However, the UI controls + // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following + // mapping and formatting functions implement this conversion. The speedup factor is represented + // by an integer value between -900 and 900 (0 means no speedup). + + constexpr int MAX_SPEED = 900; + constexpr int MIN_SPEED = -900; + constexpr int SPEED_STEP = 10; + + int mapSpeed(float speed) + { + speed = std::abs(speed); + + return BSPF::clamp( + static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), + MIN_SPEED, MAX_SPEED + ); + } + + float unmapSpeed(int speed) + { + float f_speed = static_cast(speed) / 100; + + return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; + } + + string formatSpeed(int speed) { + stringstream ss; + + ss + << std::setw(3) << std::fixed << std::setprecision(0) + << (unmapSpeed(speed) * 100); + + return ss.str(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Emulation settings") +{ + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = font.getStringWidth("Emulation speed "); + WidgetArray wid; + VariantList items; + const int swidth = fontWidth * 10; + + // Set real dimensions + _w = 37 * fontWidth + HBORDER * 2 + CheckboxWidget::prefixSize(_font); + _h = 12 * (lineHeight + VGAP) + VGAP * 7 + VBORDER * 3 + _th + buttonHeight; + + xpos = HBORDER; ypos = VBORDER + _th; + + // Speed + mySpeed = + new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight, + "Emulation speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); + mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); + mySpeed->setStepValue(SPEED_STEP); + mySpeed->setTickmarkIntervals(2); + wid.push_back(mySpeed); + ypos += lineHeight + VGAP; + + // Use sync to vblank + myUseVSync = new CheckboxWidget(this, _font, xpos, ypos + 1, "VSync"); + wid.push_back(myUseVSync); + ypos += lineHeight + VGAP; + + + myTurbo = new CheckboxWidget(this, _font, xpos, ypos + 1, "Turbo mode"); + wid.push_back(myTurbo); + ypos += lineHeight + VGAP * 3; + + // Use multi-threading + myUseThreads = new CheckboxWidget(this, _font, xpos, ypos + 1, "Multi-threading"); + wid.push_back(myUseThreads); + ypos += lineHeight + VGAP; + + // Skip progress load bars for SuperCharger ROMs + // Doesn't really belong here, but I couldn't find a better place for it + myFastSCBios = new CheckboxWidget(this, _font, xpos, ypos + 1, "Fast SuperCharger load"); + wid.push_back(myFastSCBios); + ypos += lineHeight + VGAP; + + // Show UI messages onscreen + myUIMessages = new CheckboxWidget(this, _font, xpos, ypos + 1, "Show UI messages"); + wid.push_back(myUIMessages); + ypos += lineHeight + VGAP; + + // Confirm dialog when exiting emulation + xpos = HBORDER; ypos += VGAP * 3; + myConfirmExitWidget = new CheckboxWidget(this, _font, xpos, ypos, "Confirm exiting emulation"); + wid.push_back(myConfirmExitWidget); + + xpos = HBORDER + INDENT; + ypos += lineHeight + VGAP * 3; + new StaticTextWidget(this, font, HBORDER, ypos + 1, + "When entering/exiting emulation:"); + ypos += lineHeight + VGAP; + mySaveOnExitGroup = new RadioButtonGroup(); + RadioButtonWidget* r; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Do nothing", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Save current state in current slot", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + r = new RadioButtonWidget(this, font, xpos, ypos + 1, + "Load/save all Time Machine states", mySaveOnExitGroup); + wid.push_back(r); + ypos += lineHeight + VGAP; + xpos = HBORDER; + + + myAutoSlotWidget = new CheckboxWidget(this, font, xpos, ypos + 1, "Automatically change save state slots"); + wid.push_back(myAutoSlotWidget); + ypos += lineHeight + VGAP; + + // Add Defaults, OK and Cancel buttons + addDefaultsOKCancelBGroup(wid, font); + + addToFocusList(wid); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::loadConfig() +{ + Settings& settings = instance().settings(); + + // Emulation speed + int speed = mapSpeed(settings.getFloat("speed")); + mySpeed->setValue(speed); + mySpeed->setValueLabel(formatSpeed(speed)); + + // Use sync to vertical blank + myUseVSync->setState(settings.getBool("vsync")); + + // Enable 'Turbo' mode + myTurbo->setState(settings.getBool("turbo")); + + // Show UI messages + myUIMessages->setState(settings.getBool("uimessages")); + + // Fast loading of Supercharger BIOS + myFastSCBios->setState(settings.getBool("fastscbios")); + + // Multi-threaded rendering + myUseThreads->setState(settings.getBool("threads")); + + // Confirm dialog when exiting emulation + myConfirmExitWidget->setState(settings.getBool("confirmexit")); + + // Save on exit + string saveOnExit = settings.getString("saveonexit"); + mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0); + // Automatically change save state slots + myAutoSlotWidget->setState(settings.getBool("autoslot")); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::saveConfig() +{ + Settings& settings = instance().settings(); + + // Speed + const int speedup = mySpeed->getValue(); + settings.setValue("speed", unmapSpeed(speedup)); + if(instance().hasConsole()) + instance().console().initializeAudio(); + + // Use sync to vertical blank + settings.setValue("vsync", myUseVSync->getState()); + + // Enable 'Turbo' mode + settings.setValue("turbo", myTurbo->getState()); + + // Show UI messages + settings.setValue("uimessages", myUIMessages->getState()); + + // Fast loading of Supercharger BIOS + settings.setValue("fastscbios", myFastSCBios->getState()); + + // Multi-threaded rendering + settings.setValue("threads", myUseThreads->getState()); + + // Confirm dialog when exiting emulation + settings.setValue("confirmexit", myConfirmExitWidget->getState()); + + // Save on exit + int saveOnExit = mySaveOnExitGroup->getSelected(); + settings.setValue("saveonexit", + saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all"); + // Automatically change save state slots + settings.setValue("autoslot", myAutoSlotWidget->getState()); + + if(instance().hasConsole()) + { + // update speed + instance().console().initializeAudio(); + // update VSync + instance().console().initializeVideo(); + instance().createFrameBuffer(); + + instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::setDefaults() +{ + // speed + mySpeed->setValue(0); + myUseVSync->setState(true); + // misc + myUIMessages->setState(true); + myFastSCBios->setState(true); + myUseThreads->setState(false); + myConfirmExitWidget->setState(false); + + mySaveOnExitGroup->setSelected(0); + myAutoSlotWidget->setState(false); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EmulationDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch(cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + close(); + break; + + case GuiObject::kDefaultsCmd: + setDefaults(); + break; + + case kSpeedupChanged: + mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); + break; + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} diff --git a/src/gui/EmulationDialog.hxx b/src/gui/EmulationDialog.hxx new file mode 100644 index 000000000..f1470d7bb --- /dev/null +++ b/src/gui/EmulationDialog.hxx @@ -0,0 +1,63 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef EMULATION_DIALOG_HXX +#define EMULATION_DIALOG_HXX + +class RadioButtonGroup; + +#include "Dialog.hxx" + +class EmulationDialog : public Dialog +{ +public: + EmulationDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + int max_w, int max_h); + virtual ~EmulationDialog() = default; + +private: + void loadConfig() override; + void saveConfig() override; + void setDefaults() override; + + void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + +private: + SliderWidget* mySpeed{nullptr}; + CheckboxWidget* myUseVSync{nullptr}; + CheckboxWidget* myTurbo{nullptr}; + CheckboxWidget* myUIMessages{nullptr}; + CheckboxWidget* myFastSCBios{nullptr}; + CheckboxWidget* myUseThreads{nullptr}; + CheckboxWidget* myConfirmExitWidget{nullptr}; + RadioButtonGroup* mySaveOnExitGroup{nullptr}; + CheckboxWidget* myAutoSlotWidget{nullptr}; + + enum { + kSpeedupChanged = 'EDSp', + }; + +private: + // Following constructors and assignment operators not supported + EmulationDialog() = delete; + EmulationDialog(const EmulationDialog&) = delete; + EmulationDialog(EmulationDialog&&) = delete; + EmulationDialog& operator=(const EmulationDialog&) = delete; + EmulationDialog& operator=(EmulationDialog&&) = delete; +}; + +#endif diff --git a/src/gui/EventMappingWidget.cxx b/src/gui/EventMappingWidget.cxx index 3d55dffe7..8051e4a56 100644 --- a/src/gui/EventMappingWidget.cxx +++ b/src/gui/EventMappingWidget.cxx @@ -44,13 +44,15 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, { const int fontHeight = font.getFontHeight(), lineHeight = font.getLineHeight(), - buttonWidth = font.getStringWidth("Defaults") + 10, - buttonHeight = font.getLineHeight() + 4; - const int HBORDER = 8; - const int VBORDER = 8; + fontWidth = font.getMaxCharWidth(), + buttonWidth = font.getStringWidth("Defaults") + fontWidth * 1.25, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; const int ACTION_LINES = 2; int xpos = HBORDER, ypos = VBORDER; - const int listWidth = _w - buttonWidth - HBORDER * 2 - 8; + const int listWidth = _w - buttonWidth - HBORDER * 2 - fontWidth; int listHeight = _h - (2 + ACTION_LINES) * lineHeight - VBORDER + 2; if(mode == EventMode::kEmulationMode) @@ -70,12 +72,12 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, VarList::push_back(items, "Debug", Event::Group::Debug); myFilterPopup = new PopUpWidget(boss, font, xpos, ypos, - listWidth - font.getStringWidth("Events ") - 23, lineHeight, - items, "Events ", 0, kFilterCmd); + listWidth - font.getStringWidth("Events ") - PopUpWidget::dropDownWidth(font), + lineHeight, items, "Events ", 0, kFilterCmd); myFilterPopup->setTarget(this); addFocusWidget(myFilterPopup); - ypos += lineHeight + 8; - listHeight -= lineHeight + 8; + ypos += lineHeight * 1.5; + listHeight -= lineHeight * 1.5; } myActionsList = new StringListWidget(boss, font, xpos, ypos, listWidth, listHeight); @@ -84,14 +86,14 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, addFocusWidget(myActionsList); // Add remap, erase, cancel and default buttons - xpos = _w - HBORDER - buttonWidth; + xpos = _w - HBORDER - buttonWidth + 2; myMapButton = new ButtonWidget(boss, font, xpos, ypos, buttonWidth, buttonHeight, "Map" + ELLIPSIS, kStartMapCmd); myMapButton->setTarget(this); addFocusWidget(myMapButton); - ypos += lineHeight + 10; + ypos += buttonHeight + VGAP; myCancelMapButton = new ButtonWidget(boss, font, xpos, ypos, buttonWidth, buttonHeight, "Cancel", kStopMapCmd); @@ -99,14 +101,14 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, myCancelMapButton->clearFlags(Widget::FLAG_ENABLED); addFocusWidget(myCancelMapButton); - ypos += lineHeight + 20; + ypos += buttonHeight + VGAP * 2; myEraseButton = new ButtonWidget(boss, font, xpos, ypos, buttonWidth, buttonHeight, "Erase", kEraseCmd); myEraseButton->setTarget(this); addFocusWidget(myEraseButton); - ypos += lineHeight + 10; + ypos += buttonHeight + VGAP; myResetButton = new ButtonWidget(boss, font, xpos, ypos, buttonWidth, buttonHeight, "Reset", kResetCmd); @@ -115,7 +117,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, if(mode == EventMode::kEmulationMode) { - ypos += lineHeight + 20; + ypos += buttonHeight + VGAP * 2; myComboButton = new ButtonWidget(boss, font, xpos, ypos, buttonWidth, buttonHeight, "Combo" + ELLIPSIS, kComboCmd); @@ -128,13 +130,13 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font, // Show message for currently selected event xpos = HBORDER; - ypos = myActionsList->getBottom() + 8; + ypos = myActionsList->getBottom() + VGAP * 2; StaticTextWidget* t; t = new StaticTextWidget(boss, font, xpos, ypos+2, font.getStringWidth("Action"), fontHeight, "Action", TextAlign::Left); - myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + 8, ypos, - _w - xpos - t->getWidth() - 8 - HBORDER, + myKeyMapping = new EditTextWidget(boss, font, xpos + t->getWidth() + fontWidth, ypos, + _w - xpos - t->getWidth() - fontWidth - HBORDER + 2, lineHeight + font.getFontHeight() * (ACTION_LINES - 1), ""); myKeyMapping->setEditable(false, true); myKeyMapping->clearFlags(Widget::FLAG_RETAIN_FOCUS); diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 98ad978d7..bd1bd32ef 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -26,6 +26,7 @@ #include "OSystem.hxx" #include "CartDetector.hxx" #include "ControllerDetector.hxx" +#include "Paddles.hxx" #include "PopUpWidget.hxx" #include "PropsSet.hxx" #include "TabWidget.hxx" @@ -52,26 +53,30 @@ GameInfoDialog::GameInfoDialog( : Dialog(osystem, parent, font, "Game properties"), CommandSender(boss) { - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(), + + const int lineHeight = font.getLineHeight(), + fontHeight = font.getFontHeight(), + fontWidth = font.getMaxCharWidth(), + buttonHeight = font.getLineHeight() * 1.25, infoLineHeight = ifont.getLineHeight(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; WidgetArray wid; // Set real dimensions - setSize(HBORDER * 2 + 53 * fontWidth, - 8 * (lineHeight + VGAP) + 1 * (infoLineHeight + VGAP) + VBORDER * 2 + _th + - buttonHeight(font) + fontHeight + ifont.getLineHeight() + 20, + setSize(54 * fontWidth + HBORDER * 2, + _th + VGAP * 3 + lineHeight + 8 * (lineHeight + VGAP) + 1 * (infoLineHeight + VGAP) + + ifont.getLineHeight() + VGAP + buttonHeight + VBORDER * 2, max_w, max_h); // The tab widget - myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2 * 2, - _h - (_th + buttonHeight(font) + 20)); + myTab = new TabWidget(this, font, 2, 4 + _th, + _w - 2 * 2, + _h - _th - VGAP - buttonHeight - VBORDER * 2); + addTabWidget(myTab); ////////////////////////////////////////////////////////////////////////////// @@ -93,13 +98,13 @@ GameInfoDialog::GameInfoDialog( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::addEmulationTab() { - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const GUI::Font& ifont = instance().frameBuffer().infoFont(); - const int lineHeight = _font.getLineHeight(), - fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(); + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; int ypos, pwidth, tabID; WidgetArray wid; @@ -116,12 +121,12 @@ void GameInfoDialog::addEmulationTab() items.clear(); for(uInt32 i = 0; i < uInt32(Bankswitch::Type::NumSchemes); ++i) VarList::push_back(items, Bankswitch::BSList[i].desc, Bankswitch::BSList[i].name); - myBSType = new PopUpWidget(myTab, _font, t->getRight() + 8, ypos, - pwidth, lineHeight, items, ""); + myBSType = new PopUpWidget(myTab, _font, t->getRight() + fontWidth, ypos, + pwidth, lineHeight, items, ""); wid.push_back(myBSType); ypos += lineHeight + VGAP; - myTypeDetected = new StaticTextWidget(myTab, ifont, t->getRight() + 8, ypos, + myTypeDetected = new StaticTextWidget(myTab, ifont, t->getRight() + fontWidth, ypos, "CM (SpectraVideo CompuMate) detected"); ypos += ifont.getLineHeight() + VGAP; @@ -147,16 +152,18 @@ void GameInfoDialog::addEmulationTab() pwidth, lineHeight, items, "", 0, 0); wid.push_back(myFormat); - myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + 8, ypos + 4, "SECAM60 detected"); + myFormatDetected = new StaticTextWidget(myTab, ifont, myFormat->getRight() + fontWidth, ypos + 4, + "SECAM60 detected"); // Phosphor ypos += lineHeight + VGAP; - myPhosphor = new CheckboxWidget(myTab, _font, HBORDER, ypos + 1, "Phosphor (enabled for all ROMs)", kPhosphorChanged); + myPhosphor = new CheckboxWidget(myTab, _font, HBORDER, ypos + 1, + "Phosphor (enabled for all ROMs)", kPhosphorChanged); wid.push_back(myPhosphor); ypos += lineHeight + VGAP * 0; myPPBlend = new SliderWidget(myTab, _font, - HBORDER + 20, ypos, + HBORDER + fontWidth * 2, ypos, "Blend ", 0, kPPBlendChanged, 4 * fontWidth, "%"); myPPBlend->setMinValue(0); myPPBlend->setMaxValue(100); myPPBlend->setTickmarkIntervals(2); @@ -164,7 +171,7 @@ void GameInfoDialog::addEmulationTab() ypos += lineHeight + VGAP; t = new StaticTextWidget(myTab, _font, HBORDER, ypos + 1, "V-Center "); - myVCenter = new SliderWidget(myTab, _font, t->getRight() + 2, ypos, "", + myVCenter = new SliderWidget(myTab, _font, t->getRight(), ypos, "", 0, kVCenterChanged, 7 * fontWidth, "px", 0, true); myVCenter->setMinValue(TIAConstants::minVcenter); @@ -177,9 +184,9 @@ void GameInfoDialog::addEmulationTab() wid.push_back(mySound); // Add message concerning usage - ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10; + ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER; new StaticTextWidget(myTab, ifont, HBORDER, ypos, - "(*) Changes require a ROM reload"); + "(*) Change requires a ROM reload"); // Add items for tab 0 addToFocusList(wid, myTab, tabID); @@ -189,17 +196,18 @@ void GameInfoDialog::addEmulationTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::addConsoleTab() { - // 2) Console properties - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(); + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; int xpos, ypos, lwidth, tabID; WidgetArray wid; - VariantList items; + // 2) Console properties tabID = myTab->addTab(" Console ", TabWidget::AUTO_WIDTH); xpos = HBORDER; ypos = VBORDER; @@ -241,50 +249,52 @@ void GameInfoDialog::addConsoleTab() addToFocusList(wid, myTab, tabID); } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::addControllersTab() { - // 3) Controller properties - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), fontWidth = _font.getMaxCharWidth(), - fontHeight = _font.getFontHeight(); + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; int xpos, ypos, pwidth, tabID; + VariantList items, ctrls; WidgetArray wid; - VariantList items, ports, ctrls;; + // 3) Controller properties + wid.clear(); tabID = myTab->addTab("Controllers", TabWidget::AUTO_WIDTH); - ctrls.clear(); - VarList::push_back(ctrls, "Auto-detect", "AUTO"); - VarList::push_back(ctrls, "Joystick", "JOYSTICK"); - VarList::push_back(ctrls, "Paddles", "PADDLES"); - VarList::push_back(ctrls, "Paddles_IAxis", "PADDLES_IAXIS"); - VarList::push_back(ctrls, "Paddles_IAxDr", "PADDLES_IAXDR"); - VarList::push_back(ctrls, "BoosterGrip", "BOOSTERGRIP"); - VarList::push_back(ctrls, "Driving", "DRIVING"); - VarList::push_back(ctrls, "Keyboard", "KEYBOARD"); - VarList::push_back(ctrls, "AmigaMouse", "AMIGAMOUSE"); - VarList::push_back(ctrls, "AtariMouse", "ATARIMOUSE"); - VarList::push_back(ctrls, "Trakball", "TRAKBALL"); - VarList::push_back(ctrls, "AtariVox", "ATARIVOX"); - VarList::push_back(ctrls, "SaveKey", "SAVEKEY"); - VarList::push_back(ctrls, "Sega Genesis", "GENESIS"); - VarList::push_back(ctrls, "KidVid", "KIDVID"); - VarList::push_back(ctrls, "Lightgun", "LIGHTGUN"); - VarList::push_back(ctrls, "MindLink", "MINDLINK"); + items.clear(); + VarList::push_back(items, "Auto-detect", "AUTO"); + VarList::push_back(items, "Joystick", "JOYSTICK"); + VarList::push_back(items, "Paddles", "PADDLES"); + VarList::push_back(items, "Paddles_IAxis", "PADDLES_IAXIS"); + VarList::push_back(items, "Paddles_IAxDr", "PADDLES_IAXDR"); + VarList::push_back(items, "BoosterGrip", "BOOSTERGRIP"); + VarList::push_back(items, "Driving", "DRIVING"); + VarList::push_back(items, "Keyboard", "KEYBOARD"); + VarList::push_back(items, "AmigaMouse", "AMIGAMOUSE"); + VarList::push_back(items, "AtariMouse", "ATARIMOUSE"); + VarList::push_back(items, "Trakball", "TRAKBALL"); + VarList::push_back(items, "AtariVox", "ATARIVOX"); + VarList::push_back(items, "SaveKey", "SAVEKEY"); + VarList::push_back(items, "Sega Genesis", "GENESIS"); + VarList::push_back(items, "KidVid", "KIDVID"); + VarList::push_back(items, "Lightgun", "LIGHTGUN"); + VarList::push_back(items, "MindLink", "MINDLINK"); xpos = HBORDER; ypos = VBORDER; pwidth = _font.getStringWidth("Paddles_IAxis"); myLeftPortLabel = new StaticTextWidget(myTab, _font, HBORDER, ypos+1, "Left port "); myLeftPort = new PopUpWidget(myTab, _font, myLeftPortLabel->getRight(), myLeftPortLabel->getTop()-1, - pwidth, lineHeight, ctrls, "", 0, kLeftCChanged); + pwidth, lineHeight, items, "", 0, kLeftCChanged); wid.push_back(myLeftPort); ypos += lineHeight + VGAP; @@ -295,7 +305,7 @@ void GameInfoDialog::addControllersTab() myRightPortLabel = new StaticTextWidget(myTab, _font, HBORDER, ypos+1, "Right port "); myRightPort = new PopUpWidget(myTab, _font, myRightPortLabel->getRight(), myRightPortLabel->getTop()-1, - pwidth, lineHeight, ctrls, "", 0, kRightCChanged); + pwidth, lineHeight, items, "", 0, kRightCChanged); wid.push_back(myRightPort); ypos += lineHeight + VGAP; myRightPortDetected = new StaticTextWidget(myTab, ifont, myRightPort->getLeft(), ypos, @@ -314,44 +324,67 @@ void GameInfoDialog::addControllersTab() pwidth = myRightPort->getWidth(); //_font.getStringWidth("Erase EEPROM ") + 23; myEraseEEPROMLabel = new StaticTextWidget(myTab, _font, HBORDER, ypos, "AtariVox/SaveKey "); myEraseEEPROMButton = new ButtonWidget(myTab, _font, myEraseEEPROMLabel->getRight(), ypos - 4, - pwidth, buttonHeight(_font), "Erase EEPROM", + pwidth, buttonHeight, "Erase EEPROM", kEEButtonPressed); wid.push_back(myEraseEEPROMButton); myEraseEEPROMInfo = new StaticTextWidget(myTab, ifont, myEraseEEPROMButton->getRight() + 4, myEraseEEPROMLabel->getTop() + 3, "(for this game only)"); - ypos += lineHeight + VGAP * 4; + + // Paddles + myPaddlesCenter = new StaticTextWidget(myTab, _font, xpos, ypos, "Paddles center:"); + ypos += lineHeight + VGAP; + + xpos += INDENT; + myPaddleXCenter = new SliderWidget(myTab, _font, xpos, ypos - 1, "X ", 0, kPXCenterChanged, + fontWidth * 6, "px", 0 ,true); + myPaddleXCenter->setMinValue(Paddles::MIN_ANALOG_CENTER); + myPaddleXCenter->setMaxValue(Paddles::MAX_ANALOG_CENTER); + myPaddleXCenter->setTickmarkIntervals(4); + wid.push_back(myPaddleXCenter); + ypos += lineHeight + VGAP; + + myPaddleYCenter = new SliderWidget(myTab, _font, xpos, ypos - 1, "Y ", 0, kPYCenterChanged, + fontWidth * 6, "px", 0 ,true); + myPaddleYCenter->setMinValue(Paddles::MIN_ANALOG_CENTER); + myPaddleYCenter->setMaxValue(Paddles::MAX_ANALOG_CENTER); + myPaddleYCenter->setTickmarkIntervals(4); + wid.push_back(myPaddleYCenter); + + // Mouse + xpos = HBORDER + fontWidth * 24 - INDENT; + ypos = myPaddlesCenter->getTop(); myMouseControl = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Specific mouse axes", kMCtrlChanged); wid.push_back(myMouseControl); // Mouse controller specific axis pwidth = _font.getStringWidth("MindLink 0"); - items.clear(); - VarList::push_back(items, "None", static_cast(MouseControl::Type::NoControl)); - VarList::push_back(items, "Paddle 0", static_cast(MouseControl::Type::Paddle0)); - VarList::push_back(items, "Paddle 1", static_cast(MouseControl::Type::Paddle1)); - VarList::push_back(items, "Paddle 2", static_cast(MouseControl::Type::Paddle2)); - VarList::push_back(items, "Paddle 3", static_cast(MouseControl::Type::Paddle3)); - VarList::push_back(items, "Driving 0", static_cast(MouseControl::Type::Driving0)); - VarList::push_back(items, "Driving 1", static_cast(MouseControl::Type::Driving1)); - VarList::push_back(items, "MindLink 0", static_cast(MouseControl::Type::MindLink0)); - VarList::push_back(items, "MindLink 1", static_cast(MouseControl::Type::MindLink1)); + ctrls.clear(); + VarList::push_back(ctrls, "None", static_cast(MouseControl::Type::NoControl)); + VarList::push_back(ctrls, "Paddle 0", static_cast(MouseControl::Type::Paddle0)); + VarList::push_back(ctrls, "Paddle 1", static_cast(MouseControl::Type::Paddle1)); + VarList::push_back(ctrls, "Paddle 2", static_cast(MouseControl::Type::Paddle2)); + VarList::push_back(ctrls, "Paddle 3", static_cast(MouseControl::Type::Paddle3)); + VarList::push_back(ctrls, "Driving 0", static_cast(MouseControl::Type::Driving0)); + VarList::push_back(ctrls, "Driving 1", static_cast(MouseControl::Type::Driving1)); + VarList::push_back(ctrls, "MindLink 0", static_cast(MouseControl::Type::MindLink0)); + VarList::push_back(ctrls, "MindLink 1", static_cast(MouseControl::Type::MindLink1)); - xpos += 20; + xpos += CheckboxWidget::prefixSize(_font); ypos += lineHeight + VGAP; - myMouseX = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, items, + myMouseX = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, ctrls, "X-Axis is "); wid.push_back(myMouseX); ypos += lineHeight + VGAP; - myMouseY = new PopUpWidget(myTab, _font, myMouseX->getLeft(), ypos, pwidth, lineHeight, items, + myMouseY = new PopUpWidget(myTab, _font, myMouseX->getLeft(), ypos, pwidth, lineHeight, ctrls, "Y-Axis is "); wid.push_back(myMouseY); - xpos = HBORDER; ypos += lineHeight + VGAP; - myMouseRange = new SliderWidget(myTab, _font, HBORDER, ypos, + xpos -= CheckboxWidget::prefixSize(_font); ypos += lineHeight + VGAP; + myMouseRange = new SliderWidget(myTab, _font, xpos, ypos, "Mouse axes range ", 0, 0, fontWidth * 4, "%"); myMouseRange->setMinValue(1); myMouseRange->setMaxValue(100); myMouseRange->setTickmarkIntervals(4); @@ -365,11 +398,12 @@ void GameInfoDialog::addControllersTab() void GameInfoDialog::addCartridgeTab() { // 4) Cartridge properties - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(); + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; int xpos, ypos, lwidth, fwidth, tabID; WidgetArray wid; @@ -421,16 +455,16 @@ void GameInfoDialog::addCartridgeTab() addToFocusList(wid, myTab, tabID); } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::addHighScoresTab() { // 4) High Scores properties - const int VBORDER = 8; - const int HBORDER = 10; - const int VGAP = 4; const int lineHeight = _font.getLineHeight(), - fontHeight = _font.getFontHeight(); + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; int xpos, ypos, lwidth, fwidth, pwidth, tabID; WidgetArray wid; @@ -600,11 +634,13 @@ void GameInfoDialog::loadConfig() if(instance().hasConsole()) { myGameProperties = instance().console().properties(); + myGameFile = instance().romFile(); } else { const string& md5 = instance().launcher().selectedRomMD5(); instance().propSet().getMD5(md5, myGameProperties); + myGameFile = FilesystemNode(instance().launcher().selectedRom()); } loadEmulationProperties(myGameProperties); @@ -656,7 +692,7 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props) VarList::push_back(items, "Auto", "AUTO"); if(instance().hasConsole()) { - uInt16 numBanks = instance().console().cartridge().bankCount(); + uInt16 numBanks = instance().console().cartridge().romBankCount(); for(uInt16 i = 0; i < numBanks; ++i) VarList::push_back(items, i, i); @@ -730,6 +766,10 @@ void GameInfoDialog::loadControllerProperties(const Properties& props) mySwapPorts->setState(props.get(PropType::Console_SwapPorts) == "YES"); mySwapPaddles->setState(props.get(PropType::Controller_SwapPaddles) == "YES"); + // Paddle centers + myPaddleXCenter->setValue(BSPF::stringToInt(props.get(PropType::Controller_PaddlesXCenter))); + myPaddleYCenter->setValue(BSPF::stringToInt(props.get(PropType::Controller_PaddlesYCenter))); + // MouseAxis property (potentially contains 'range' information) istringstream m_axis(props.get(PropType::Controller_MouseAxis)); string m_control, m_range; @@ -821,7 +861,7 @@ void GameInfoDialog::loadHighScoresProperties(const Properties& props) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void GameInfoDialog::saveConfig() +void GameInfoDialog::saveProperties() { // Emulation properties myGameProperties.set(PropType::Cart_Type, myBSType->getSelectedTag().toString()); @@ -844,7 +884,11 @@ void GameInfoDialog::saveConfig() myGameProperties.set(PropType::Controller_Left, myLeftPort->getSelectedTag().toString()); myGameProperties.set(PropType::Controller_Right, myRightPort->getSelectedTag().toString()); myGameProperties.set(PropType::Console_SwapPorts, (mySwapPorts->isEnabled() && mySwapPorts->getState()) ? "YES" : "NO"); - myGameProperties.set(PropType::Controller_SwapPaddles, (/*mySwapPaddles->isEnabled() &&*/ mySwapPaddles->getState()) ? "YES" : "NO"); + myGameProperties.set(PropType::Controller_SwapPaddles, mySwapPaddles->getState() ? "YES" : "NO"); + + // Paddle center + myGameProperties.set(PropType::Controller_PaddlesXCenter, std::to_string(myPaddleXCenter->getValue())); + myGameProperties.set(PropType::Controller_PaddlesYCenter, std::to_string(myPaddleYCenter->getValue())); // MouseAxis property (potentially contains 'range' information) string mcontrol = "AUTO"; @@ -862,6 +906,12 @@ void GameInfoDialog::saveConfig() myGameProperties.set(PropType::Cart_ModelNo, myModelNo->getText()); myGameProperties.set(PropType::Cart_Rarity, myRarity->getText()); myGameProperties.set(PropType::Cart_Note, myNote->getText()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void GameInfoDialog::saveConfig() +{ + saveProperties(); saveHighScoresProperties(); @@ -877,7 +927,7 @@ void GameInfoDialog::saveConfig() // update 'Emulation' tab settings immediately instance().console().setFormat(myFormat->getSelected()); instance().frameBuffer().tiaSurface().enablePhosphor(myPhosphor->getState(), myPPBlend->getValue()); - instance().console().updateVcenter(vcenter); + instance().console().updateVcenter(myVCenter->getValue()); instance().console().initializeAudio(); // update 'Console' tab settings immediately @@ -887,6 +937,9 @@ void GameInfoDialog::saveConfig() // update 'Controllers' tab settings immediately instance().console().setControllers(myGameProperties.get(PropType::Cart_MD5)); + + Paddles::setAnalogXCenter(myPaddleXCenter->getValue()); + Paddles::setAnalogYCenter(myPaddleYCenter->getValue()); } } @@ -1011,7 +1064,7 @@ void GameInfoDialog::updateControllerStates() label = (!swapPorts ? instance().console().leftController().name() : instance().console().rightController().name()) + " detected"; else if(autoDetect) - label = ControllerDetector::detectName(image.get(), size, type, + label = ControllerDetector::detectName(image, size, type, !swapPorts ? Controller::Jack::Left : Controller::Jack::Right, instance().settings()) + " detected"; } @@ -1026,7 +1079,7 @@ void GameInfoDialog::updateControllerStates() label = (!swapPorts ? instance().console().rightController().name() : instance().console().leftController().name()) + " detected"; else if(autoDetect) - label = ControllerDetector::detectName(image.get(), size, type, + label = ControllerDetector::detectName(image, size, type, !swapPorts ? Controller::Jack::Right : Controller::Jack::Left, instance().settings()) + " detected"; } @@ -1039,10 +1092,10 @@ void GameInfoDialog::updateControllerStates() // Compumate bankswitching scheme doesn't allow to select controllers bool enableSelectControl = myBSType->getSelectedTag() != "CM"; // Enable Swap Paddles checkbox only for paddle games - bool enableSwapPaddles = startsWithIgnoreCase(contrLeft, "PADDLES") || - startsWithIgnoreCase(contrRight, "PADDLES") || - startsWithIgnoreCase(myLeftPortDetected->getLabel(), "Paddles") || - startsWithIgnoreCase(myRightPortDetected->getLabel(), "Paddles"); + bool enablePaddles = BSPF::startsWithIgnoreCase(contrLeft, "PADDLES") || + BSPF::startsWithIgnoreCase(contrRight, "PADDLES") || + BSPF::startsWithIgnoreCase(myLeftPortDetected->getLabel(), "Paddles") || + BSPF::startsWithIgnoreCase(myRightPortDetected->getLabel(), "Paddles"); if(instance().hasConsole()) { @@ -1065,11 +1118,27 @@ void GameInfoDialog::updateControllerStates() myRightPort->setEnabled(enableSelectControl); mySwapPorts->setEnabled(enableSelectControl); - mySwapPaddles->setEnabled(enableSwapPaddles); + mySwapPaddles->setEnabled(enablePaddles); myEraseEEPROMLabel->setEnabled(enableEEEraseButton); myEraseEEPROMButton->setEnabled(enableEEEraseButton); myEraseEEPROMInfo->setEnabled(enableEEEraseButton); + + myPaddlesCenter->setEnabled(enablePaddles); + myPaddleXCenter->setEnabled(enablePaddles); + myPaddleYCenter->setEnabled(enablePaddles); + + + bool enableMouse = enablePaddles || + BSPF::startsWithIgnoreCase(contrLeft, "Driving") || + BSPF::startsWithIgnoreCase(contrRight, "Driving") || + BSPF::startsWithIgnoreCase(contrLeft, "MindLink") || + BSPF::startsWithIgnoreCase(contrRight, "MindLink"); + + myMouseControl->setEnabled(enableMouse); + myMouseX->setEnabled(enableMouse); + myMouseY->setEnabled(enableMouse); + myMouseRange->setEnabled(enableMouse); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1078,13 +1147,15 @@ void GameInfoDialog::eraseEEPROM() Controller& lport = instance().console().leftController(); Controller& rport = instance().console().rightController(); - if(lport.type() == Controller::Type::SaveKey || lport.type() == Controller::Type::AtariVox) + if(lport.type() == Controller::Type::SaveKey || + lport.type() == Controller::Type::AtariVox) { SaveKey& skey = static_cast(lport); skey.eraseCurrent(); } - if(rport.type() == Controller::Type::SaveKey || rport.type() == Controller::Type::AtariVox) + if(rport.type() == Controller::Type::SaveKey || + rport.type() == Controller::Type::AtariVox) { SaveKey& skey = static_cast(rport); skey.eraseCurrent(); @@ -1207,6 +1278,27 @@ void GameInfoDialog::setAddressVal(EditTextWidget* addressWidget, EditTextWidget valWidget->setText(""); } +void GameInfoDialog::saveCurrentPropertiesToDisk() +{ + saveProperties(); + stringstream out; + out << myGameProperties; + + try + { + FilesystemNode propfile = instance().defaultSaveDir(); + propfile /= myGameFile.getNameWithExt(".pro"); + + propfile.write(out); + instance().frameBuffer().showMessage("Properties saved to " + + propfile.getShortPath()); + } + catch(...) + { + instance().frameBuffer().showMessage("Error saving properties"); + } +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) @@ -1222,6 +1314,10 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; + case kSavePressed: + saveCurrentPropertiesToDisk(); + break; + case TabWidget::kTabChangedCmd: if(data == 2) // 'Controllers' tab selected updateControllerStates(); @@ -1266,6 +1362,14 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, myVCenter->setValueUnit("px"); break; + case kPXCenterChanged: + myPaddleXCenter->setValueLabel(myPaddleXCenter->getValue() * 5); + break; + + case kPYCenterChanged: + myPaddleYCenter->setValueLabel(myPaddleYCenter->getValue() * 5); + break; + case kMCtrlChanged: { bool state = myMouseControl->getState(); diff --git a/src/gui/GameInfoDialog.hxx b/src/gui/GameInfoDialog.hxx index dd031a46c..7f892fc16 100644 --- a/src/gui/GameInfoDialog.hxx +++ b/src/gui/GameInfoDialog.hxx @@ -64,6 +64,8 @@ class GameInfoDialog : public Dialog, public CommandSender void loadHighScoresProperties(const Properties& props); // load the properties of the 'High Scores' tab void saveHighScoresProperties(); + // save properties from all tabs into the local properties object + void saveProperties(); // update 'Controller' tab widgets void updateControllerStates(); @@ -74,6 +76,7 @@ class GameInfoDialog : public Dialog, public CommandSender // set formatted memory value for given address field void setAddressVal(EditTextWidget* address, EditTextWidget* val, bool isBCD = true, bool zeroBased = false, uInt8 maxVal = 255); + void saveCurrentPropertiesToDisk(); private: TabWidget* myTab{nullptr}; @@ -107,6 +110,9 @@ class GameInfoDialog : public Dialog, public CommandSender StaticTextWidget* myEraseEEPROMLabel{nullptr}; ButtonWidget* myEraseEEPROMButton{nullptr}; StaticTextWidget* myEraseEEPROMInfo{nullptr}; + StaticTextWidget* myPaddlesCenter{nullptr}; + SliderWidget* myPaddleXCenter{nullptr}; + SliderWidget* myPaddleYCenter{nullptr}; CheckboxWidget* myMouseControl{nullptr}; PopUpWidget* myMouseX{nullptr}; PopUpWidget* myMouseY{nullptr}; @@ -166,10 +172,15 @@ class GameInfoDialog : public Dialog, public CommandSender kMCtrlChanged = 'MCch', kEEButtonPressed = 'EEgb', kHiScoresChanged = 'HSch', + kPXCenterChanged = 'Pxch', + kPYCenterChanged = 'Pych', + kSavePressed = 'GIsp' }; // Game properties for currently loaded ROM Properties myGameProperties; + // Filename of the currently loaded ROM + FilesystemNode myGameFile; private: // Following constructors and assignment operators not supported diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index b4f296596..232968f1c 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -36,20 +36,24 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() + 4; + buttonHeight = lineHeight * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; int lwidth = font.getStringWidth("Right difficulty "), pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)"); - const int VGAP = 4; WidgetArray wid; VariantList items; const GUI::Font& infofont = instance().frameBuffer().infoFont(); // Set real dimensions - _w = lwidth + pwidth + fontWidth*3 + 15; - _h = 15 * (lineHeight + 4) + buttonHeight + 16 + _th; + _w = HBORDER * 2 + std::max(lwidth + pwidth + PopUpWidget::dropDownWidth(font), + 49 * infofont.getMaxCharWidth()); + _h = _th + 11 * (lineHeight + VGAP) + 3 * infofont.getLineHeight() + VGAP * 12 + buttonHeight + VBORDER * 2; - xpos = 10; ypos = 10 + _th; + xpos = HBORDER; ypos = VBORDER + _th; // Bankswitch type new StaticTextWidget(this, font, xpos, ypos+1, "Bankswitch type"); @@ -112,12 +116,12 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) "(automatically released shortly after start)"); // Start with console joystick direction/buttons held down - xpos = 32; ypos += infofont.getLineHeight() + VGAP * 2; + xpos = fontWidth * 4; ypos += infofont.getLineHeight() + VGAP * 2; ypos = addHoldWidgets(font, xpos, ypos, wid); // Add message concerning usage - xpos = 10; ypos += 2 * fontHeight; - ypos = _h - fontHeight * 2 - infofont.getLineHeight() - 24; + xpos = HBORDER; + ypos = _h - VBORDER - buttonHeight - VGAP * 3 - infofont.getLineHeight() * 2; new StaticTextWidget(this, infofont, xpos, ypos, "(*) These options are not saved, but apply to all"); ypos += infofont.getLineHeight(); @@ -134,21 +138,24 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y, WidgetArray& wid) { - int xpos = x, ypos = y; - const int VGAP = 4; + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(); + const int VGAP = fontHeight / 4; + + int xpos = x, ypos = y, xdiff = CheckboxWidget::boxSize(font) - 9; // Left joystick - StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Left joy"); - xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP; + StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos + 2, "Left joy"); + xpos += t->getWidth()/2 - xdiff - 2; ypos += t->getHeight() + VGAP; myJoy[kJ0Up] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Up); ypos += myJoy[kJ0Up]->getHeight() * 2 + VGAP * 2; myJoy[kJ0Down] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Down); - xpos -= myJoy[kJ0Up]->getWidth() + 5; + xpos -= myJoy[kJ0Up]->getWidth() + xdiff; ypos -= myJoy[kJ0Up]->getHeight() + VGAP; myJoy[kJ0Left] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Left); - xpos += (myJoy[kJ0Up]->getWidth() + 5) * 2; + xpos += (myJoy[kJ0Up]->getWidth() + xdiff) * 2; myJoy[kJ0Right] = new CheckboxWidget(this, font, xpos, ypos, "", kJ0Right); - xpos -= (myJoy[kJ0Up]->getWidth() + 5) * 2; + xpos -= (myJoy[kJ0Up]->getWidth() + xdiff) * 2; ypos += myJoy[kJ0Down]->getHeight() * 2 + VGAP * 2; myJoy[kJ0Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire", kJ0Fire); @@ -157,20 +164,20 @@ int GlobalPropsDialog::addHoldWidgets(const GUI::Font& font, int x, int y, // Right joystick t = new StaticTextWidget(this, font, xpos, ypos + 2, "Right joy"); - xpos += t->getWidth()/2 - 7; ypos += t->getHeight() + VGAP; + xpos += t->getWidth()/2 - xdiff - 2; ypos += t->getHeight() + VGAP; myJoy[kJ1Up] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Up); ypos += myJoy[kJ1Up]->getHeight() * 2 + VGAP * 2; myJoy[kJ1Down] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Down); - xpos -= myJoy[kJ1Up]->getWidth() + 5; + xpos -= myJoy[kJ1Up]->getWidth() + xdiff; ypos -= myJoy[kJ1Up]->getHeight() + VGAP; myJoy[kJ1Left] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Left); - xpos += (myJoy[kJ1Up]->getWidth() + 5) * 2; + xpos += (myJoy[kJ1Up]->getWidth() + xdiff) * 2; myJoy[kJ1Right] = new CheckboxWidget(this, font, xpos, ypos, "", kJ1Right); - xpos -= (myJoy[kJ1Up]->getWidth() + 5) * 2; + xpos -= (myJoy[kJ1Up]->getWidth() + xdiff) * 2; ypos += myJoy[kJ1Down]->getHeight() * 2 + VGAP * 2; myJoy[kJ1Fire] = new CheckboxWidget(this, font, xpos, ypos, "Fire", kJ1Fire); - xpos = 2 * _w / 3 + 8; ypos = y; + xpos = 2 * _w / 3 + fontWidth; ypos = y; // Console Select/Reset t = new StaticTextWidget(this, font, xpos, ypos+2, "Console"); diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx index 4e4325132..fc8f77285 100644 --- a/src/gui/GuiObject.hxx +++ b/src/gui/GuiObject.hxx @@ -27,7 +27,6 @@ class Widget; class OSystem; #include "Command.hxx" -#include "OSystem.hxx" #include "Vec.hxx" using WidgetArray = vector; @@ -90,8 +89,9 @@ class GuiObject : public CommandReceiver /** Redraw the focus list */ virtual void redrawFocus() { } - /** Special character for menues */ + /** Special characters for menues */ const string ELLIPSIS = "\x1d"; + const string DEGREE = "\x1c"; protected: virtual void releaseFocus() = 0; diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx index bc86026b0..77c01f174 100644 --- a/src/gui/HelpDialog.cxx +++ b/src/gui/HelpDialog.cxx @@ -31,49 +31,54 @@ HelpDialog::HelpDialog(OSystem& osystem, DialogContainer& parent, const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Defaults") + 20, - buttonHeight = font.getLineHeight() + 4; + buttonWidth = font.getStringWidth("Previous") + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; WidgetArray wid; // Set real dimensions - _w = 46 * fontWidth + 10; - _h = 12 * lineHeight + 20 + _th; + _w = 46 * fontWidth + HBORDER * 2; + _h = _th + 11 * lineHeight + VGAP * 3 + buttonHeight + VBORDER * 2; // Add Previous, Next and Close buttons - xpos = 10; ypos = _h - buttonHeight - 10; + xpos = HBORDER; ypos = _h - buttonHeight - VBORDER; myPrevButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Previous", GuiObject::kPrevCmd); myPrevButton->clearFlags(Widget::FLAG_ENABLED); wid.push_back(myPrevButton); - xpos += buttonWidth + 8; + xpos += buttonWidth + fontWidth; myNextButton = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Next", GuiObject::kNextCmd); wid.push_back(myNextButton); - xpos = _w - buttonWidth - 10; + xpos = _w - buttonWidth - HBORDER; ButtonWidget* b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Close", GuiObject::kCloseCmd); wid.push_back(b); addCancelWidget(b); - xpos = 5; ypos = 5 + _th; - myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - 10, fontHeight, + xpos = HBORDER; ypos = VBORDER + _th; + myTitle = new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2, fontHeight, "", TextAlign::Center); + myTitle->setTextColor(kTextColorEm); - int lwidth = 13 * fontWidth; - xpos += 5; ypos += lineHeight + 4; - for(uInt8 i = 0; i < LINES_PER_PAGE; ++i) + int lwidth = 15 * fontWidth; + ypos += lineHeight + VGAP * 2; + for(uInt32 i = 0; i < LINES_PER_PAGE; ++i) { myKey[i] = new StaticTextWidget(this, font, xpos, ypos, lwidth, fontHeight, "", TextAlign::Left); myDesc[i] = - new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - 5, + new StaticTextWidget(this, font, xpos+lwidth, ypos, _w - xpos - lwidth - HBORDER, fontHeight, "", TextAlign::Left); ypos += fontHeight; } @@ -116,7 +121,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) case 2: title = "Special commands"; ADD_EVENT(Event::FormatIncrease, "Switch between NTSC/PAL/SECAM"); - ADD_EVENT(Event::TogglePalette, "Switch palette"); + ADD_EVENT(Event::PaletteIncrease, "Switch to next palette"); ADD_EVENT(Event::TogglePhosphor, "Toggle 'phosphor' effect"); ADD_LINE(); ADD_EVENT(Event::ToggleGrabMouse, "Grab mouse (keep in window)"); @@ -158,7 +163,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) case 5: title = "All other commands"; ADD_LINE(); - ADD_BIND("Remapped Even", "ts"); + ADD_BIND("Remapped Events", ""); ADD_TEXT("Most other commands can be"); ADD_TEXT("remapped. Please consult the"); ADD_TEXT("'Options/Input" + ELLIPSIS + "' dialog for"); diff --git a/src/gui/HighScoresDialog.cxx b/src/gui/HighScoresDialog.cxx index 8afa0719a..4df3db06e 100644 --- a/src/gui/HighScoresDialog.cxx +++ b/src/gui/HighScoresDialog.cxx @@ -72,11 +72,13 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, { const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), fontWidth = _font.getMaxCharWidth(), - infoLineHeight = ifont.getLineHeight(); - const int VBORDER = 10; - const int HBORDER = 10; - const int VGAP = 4; + infoLineHeight = ifont.getLineHeight(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; int xpos, ypos; WidgetArray wid; @@ -87,7 +89,7 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, StaticTextWidget* s = new StaticTextWidget(this, _font, xpos, ypos + 1, "Variation "); myVariationPopup = new PopUpWidget(this, _font, s->getRight(), ypos, - _font.getStringWidth("256") - 4, lineHeight, items, "", 0, + _font.getStringWidth("256"), lineHeight, items, "", 0, kVariationChanged); wid.push_back(myVariationPopup); myPrevVarButton = new ButtonWidget(this, _font, myVariationPopup->getRight() + 157, ypos - 1, @@ -147,7 +149,7 @@ HighScoresDialog::HighScoresDialog(OSystem& osystem, DialogContainer& parent, myMD5Widget = new StaticTextWidget(this, ifont, xpos, ypos + 1, "MD5: 12345678901234567890123456789012"); - _h = myMD5Widget->getBottom() + VBORDER + buttonHeight(_font) + VBORDER; + _h = myMD5Widget->getBottom() + VBORDER + buttonHeight + VBORDER; myGameNameWidget = new StaticTextWidget(this, _font, HBORDER, VBORDER + _th + 1, _w - HBORDER * 2, lineHeight); @@ -472,7 +474,7 @@ string HighScoresDialog::cartName() const instance().propSet().getMD5(myMD5, props); if(props.get(PropType::Cart_Name).empty()) - return instance().launcher().currentNode().getNameWithExt(""); + return instance().launcher().currentDir().getNameWithExt(""); else return props.get(PropType::Cart_Name); } diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index fa3a38340..727c9a874 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -22,6 +22,7 @@ #include "Joystick.hxx" #include "Paddles.hxx" #include "PointingDevice.hxx" +#include "Driving.hxx" #include "SaveKey.hxx" #include "AtariVox.hxx" #include "Settings.hxx" @@ -42,40 +43,50 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, myMaxWidth(max_w), myMaxHeight(max_h) { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() + 4; - const int vBorder = 4; + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int VGAP = fontHeight / 4; + const int HBORDER = fontWidth * 1.25; int xpos, ypos, tabID; // Set real dimensions - setSize(51 * fontWidth + 10, 17 * (lineHeight + 4) + 16 + _th, max_w, max_h); + setSize(48 * fontWidth + PopUpWidget::dropDownWidth(_font) + HBORDER * 2, + _th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + VGAP * 8 + buttonHeight + VBORDER * 3, + max_w, max_h); // The tab widget - xpos = 2; ypos = vBorder + _th; - myTab = new TabWidget(this, font, xpos, ypos, _w - 2*xpos, _h -_th - buttonHeight - 20); + xpos = 2; ypos = VGAP + _th; + myTab = new TabWidget(this, _font, xpos, ypos, + _w - 2*xpos, + _h -_th - VGAP - buttonHeight - VBORDER * 2); addTabWidget(myTab); // 1) Event mapper for emulation actions - tabID = myTab->addTab(" Emulation Events ", TabWidget::AUTO_WIDTH); - myEmulEventMapper = new EventMappingWidget(myTab, font, 2, 2, + tabID = myTab->addTab(" Emul. Events ", TabWidget::AUTO_WIDTH); + myEmulEventMapper = new EventMappingWidget(myTab, _font, 2, 2, myTab->getWidth(), - myTab->getHeight() - 4, + myTab->getHeight() - VGAP, EventMode::kEmulationMode); myTab->setParentWidget(tabID, myEmulEventMapper); addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID); // 2) Event mapper for UI actions - tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); - myMenuEventMapper = new EventMappingWidget(myTab, font, 2, 2, + tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); + myMenuEventMapper = new EventMappingWidget(myTab, _font, 2, 2, myTab->getWidth(), - myTab->getHeight() - 4, + myTab->getHeight() - VGAP, EventMode::kMenuMode); myTab->setParentWidget(tabID, myMenuEventMapper); addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID); // 3) Devices & ports - addDevicePortTab(font); + addDevicePortTab(); + + // 4) Mouse + addMouseTab(); // Finalize the tabs, and activate the first tab myTab->activateTabs(); @@ -83,7 +94,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, // Add Defaults, OK and Cancel buttons WidgetArray wid; - addDefaultsOKCancelBGroup(wid, font); + addDefaultsOKCancelBGroup(wid, _font); addBGroupToFocusList(wid); } @@ -93,206 +104,262 @@ InputDialog::~InputDialog() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputDialog::addDevicePortTab(const GUI::Font& font) +void InputDialog::addDevicePortTab() { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(); - int xpos, ypos, lwidth, pwidth, tabID; + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos, lwidth, tabID; WidgetArray wid; - VariantList items; - const int VGAP = 4; - const int VBORDER = 9; - const int HBORDER = 8; // Devices/ports - tabID = myTab->addTab(" Devices & Ports ", TabWidget::AUTO_WIDTH); + tabID = myTab->addTab("Devices & Ports", TabWidget::AUTO_WIDTH); ypos = VBORDER; - lwidth = font.getStringWidth("Digital paddle sensitivity "); // was: "Use mouse as a controller " - pwidth = font.getStringWidth("-UI, -Emulation"); - - // Use mouse as controller - items.clear(); - VarList::push_back(items, "Always", "always"); - VarList::push_back(items, "Analog devices", "analog"); - VarList::push_back(items, "Never", "never"); - myMouseControl = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items, - "Use mouse as a controller ", lwidth); - wid.push_back(myMouseControl); - - // Mouse cursor state - ypos += lineHeight + VGAP; - items.clear(); - VarList::push_back(items, "-UI, -Emulation", "0"); - VarList::push_back(items, "-UI, +Emulation", "1"); - VarList::push_back(items, "+UI, -Emulation", "2"); - VarList::push_back(items, "+UI, +Emulation", "3"); - myCursorState = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items, - "Mouse cursor visibility ", lwidth, kCursorStateChanged); - wid.push_back(myCursorState); -#ifndef WINDOWED_SUPPORT - myCursorState->clearFlags(Widget::FLAG_ENABLED); -#endif - - lwidth = font.getStringWidth("Digital paddle sensitivity "); + lwidth = _font.getStringWidth("Digital paddle sensitivity "); // Add joystick deadzone setting - ypos += lineHeight + VGAP*3; - myDeadzone = new SliderWidget(myTab, font, HBORDER, ypos, 13 * fontWidth, lineHeight, - "Joystick deadzone size ", lwidth, kDeadzoneChanged); + myDeadzone = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Joystick deadzone size", lwidth, kDeadzoneChanged, 5 * fontWidth); myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29); myDeadzone->setTickmarkIntervals(4); - xpos = HBORDER + myDeadzone->getWidth() + 5; - myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth, lineHeight, ""); wid.push_back(myDeadzone); - // Add dejitter (Stelladaptor emulation for now only) + xpos = HBORDER; ypos += lineHeight + VGAP * 4; + new StaticTextWidget(myTab, _font, xpos, ypos+1, "Analog paddle:"); + xpos += fontWidth * 2; + + // Add analog paddle sensitivity + ypos += lineHeight; + myPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Sensitivity", + lwidth - fontWidth * 2, kPSpeedChanged, 4 * fontWidth, "%"); + myPaddleSpeed->setMinValue(0); myPaddleSpeed->setMaxValue(Paddles::MAX_ANALOG_SENSE); + myPaddleSpeed->setTickmarkIntervals(3); + wid.push_back(myPaddleSpeed); + + + // Add dejitter (analog paddles) ypos += lineHeight + VGAP; - myDejitterBase = new SliderWidget(myTab, font, HBORDER, ypos, 6 * fontWidth, lineHeight, - "Paddle dejitter strength", lwidth, kDejitterChanged); - myDejitterBase->setMinValue(Paddles::MIN_DEJITTER); myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER); - myDejitterBase->setTickmarkIntervals(2); - xpos = HBORDER + myDejitterBase->getWidth() + fontWidth; + myDejitterBase = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Dejitter averaging", lwidth - fontWidth * 2, + kDejitterAvChanged, 3 * fontWidth); + myDejitterBase->setMinValue(Paddles::MIN_DEJITTER); + myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER); + myDejitterBase->setTickmarkIntervals(5); + //xpos += myDejitterBase->getWidth() + fontWidth - 4; wid.push_back(myDejitterBase); - myDejitterDiff = new SliderWidget(myTab, font, xpos, ypos, 6 * fontWidth, lineHeight, - "", 0, kDejitterChanged); - myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER); myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER); - myDejitterDiff->setTickmarkIntervals(2); - xpos += myDejitterDiff->getWidth() + 5; + ypos += lineHeight + VGAP; + myDejitterDiff = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Dejitter reaction", lwidth - fontWidth * 2, + kDejitterReChanged, 3 * fontWidth); + myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER); + myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER); + myDejitterDiff->setTickmarkIntervals(5); wid.push_back(myDejitterDiff); - myDejitterLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, 7 * fontWidth, lineHeight, ""); - // Add paddle speed (digital emulation) - ypos += lineHeight + VGAP; - myDPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos, 13 * fontWidth, lineHeight, - "Digital paddle sensitivity ", - lwidth, kDPSpeedChanged); + ypos += lineHeight + VGAP * 4; + myDPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Digital paddle sensitivity", + lwidth, kDPSpeedChanged, 4 * fontWidth, "%"); myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20); myDPaddleSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myDPaddleSpeed->getWidth() + 5; - myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); wid.push_back(myDPaddleSpeed); - // Add paddle speed (mouse emulation) - ypos += lineHeight + VGAP; - myMPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos, 13 * fontWidth, lineHeight, - "Mouse paddle sensitivity ", - lwidth, kMPSpeedChanged); - myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); - myMPaddleSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myMPaddleSpeed->getWidth() + 5; - myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); - wid.push_back(myMPaddleSpeed); - - // Add trackball speed - ypos += lineHeight + VGAP; - myTrackBallSpeed = new SliderWidget(myTab, font, HBORDER, ypos, 13 * fontWidth, lineHeight, - "Trackball sensitivity ", - lwidth, kTBSpeedChanged); - myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); - myTrackBallSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myTrackBallSpeed->getWidth() + 5; - myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); - wid.push_back(myTrackBallSpeed); + ypos += lineHeight + VGAP * 4; + myAutoFireRate = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Autofire rate", + lwidth, kAutoFireChanged, 5 * fontWidth, "Hz"); + myAutoFireRate->setMinValue(0); myAutoFireRate->setMaxValue(30); + myAutoFireRate->setTickmarkIntervals(6); + wid.push_back(myAutoFireRate); // Add 'allow all 4 directions' for joystick - ypos += lineHeight + VGAP*3; - myAllowAll4 = new CheckboxWidget(myTab, font, HBORDER, ypos, + ypos += lineHeight + VGAP * 4; + myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos, "Allow all 4 directions on joystick"); wid.push_back(myAllowAll4); - // Grab mouse (in windowed mode) - ypos += lineHeight + VGAP; - myGrabMouse = new CheckboxWidget(myTab, font, HBORDER, ypos, - "Grab mouse in emulation mode"); - wid.push_back(myGrabMouse); -#ifndef WINDOWED_SUPPORT - myGrabMouse->clearFlags(Widget::FLAG_ENABLED); -#endif - // Enable/disable modifier key-combos ypos += lineHeight + VGAP; - myModCombo = new CheckboxWidget(myTab, font, HBORDER, ypos, - "Use modifier key combos"); + myModCombo = new CheckboxWidget(myTab, _font, HBORDER, ypos, + "Use modifier key combos"); wid.push_back(myModCombo); ypos += lineHeight + VGAP; // Stelladaptor mappings - mySAPort = new CheckboxWidget(myTab, font, HBORDER, ypos, + mySAPort = new CheckboxWidget(myTab, _font, HBORDER, ypos, "Swap Stelladaptor ports"); wid.push_back(mySAPort); int fwidth; // Add EEPROM erase (part 1/2) - ypos += VGAP*4; - fwidth = font.getStringWidth("AtariVox/SaveKey"); - lwidth = font.getStringWidth("AtariVox/SaveKey"); - new StaticTextWidget(myTab, font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos, + ypos += VGAP * 3; + fwidth = _font.getStringWidth("AtariVox/SaveKey"); + new StaticTextWidget(myTab, _font, _w - HBORDER - 2 - fwidth, ypos, "AtariVox/SaveKey"); // Show joystick database ypos += lineHeight; - myJoyDlgButton = new ButtonWidget(myTab, font, HBORDER, ypos, 20, - "Joystick Database" + ELLIPSIS, kDBButtonPressed); + lwidth = _font.getStringWidth("Joystick Database" + ELLIPSIS) + fontWidth * 2.5; + myJoyDlgButton = new ButtonWidget(myTab, _font, HBORDER, ypos, lwidth, buttonHeight, + "Joystick Database" + ELLIPSIS, kDBButtonPressed); wid.push_back(myJoyDlgButton); // Add EEPROM erase (part 1/2) - myEraseEEPROMButton = new ButtonWidget(myTab, font, _w - HBORDER - 4 - fwidth, ypos, - fwidth, lineHeight+4, + myEraseEEPROMButton = new ButtonWidget(myTab, _font, _w - HBORDER - 2 - fwidth, ypos, + fwidth, buttonHeight, "Erase EEPROM", kEEButtonPressed); wid.push_back(myEraseEEPROMButton); // Add AtariVox serial port - ypos += lineHeight + VGAP*2; - lwidth = font.getStringWidth("AVox serial port "); - fwidth = _w - HBORDER * 2 - 4 - lwidth; - new StaticTextWidget(myTab, font, HBORDER, ypos + 2, "AVox serial port "); - myAVoxPort = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos, + ypos += lineHeight + VGAP * 3; + lwidth = _font.getStringWidth("AtariVox serial port "); + fwidth = _w - HBORDER * 2 - 2 - lwidth; + new StaticTextWidget(myTab, _font, HBORDER, ypos + 2, "AtariVox serial port "); + myAVoxPort = new EditTextWidget(myTab, _font, HBORDER + lwidth, ypos, fwidth, fontHeight); - wid.push_back(myAVoxPort); // Add items for virtual device ports addToFocusList(wid, myTab, tabID); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::addMouseTab() +{ + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(); + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + int xpos = HBORDER, ypos, lwidth, pwidth, tabID; + WidgetArray wid; + VariantList items; + + // Mouse + tabID = myTab->addTab(" Mouse ", TabWidget::AUTO_WIDTH); + + ypos = VBORDER; + lwidth = _font.getStringWidth("Use mouse as a controller "); + pwidth = _font.getStringWidth("-UI, -Emulation"); + + // Use mouse as controller + VarList::push_back(items, "Always", "always"); + VarList::push_back(items, "Analog devices", "analog"); + VarList::push_back(items, "Never", "never"); + myMouseControl = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, items, + "Use mouse as a controller ", lwidth, kMouseCtrlChanged); + wid.push_back(myMouseControl); + + ypos += lineHeight + VGAP; + myMouseSensitivity = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Sensitivity:"); + + // Add paddle speed (mouse emulation) + xpos += INDENT; ypos += lineHeight + VGAP; + lwidth -= INDENT; + myMPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Paddle", + lwidth, kMPSpeedChanged, 4 * fontWidth, "%"); + myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); + myMPaddleSpeed->setTickmarkIntervals(4); + wid.push_back(myMPaddleSpeed); + + // Add trackball speed + ypos += lineHeight + VGAP; + myTrackBallSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Trackball", + lwidth, kTBSpeedChanged, 4 * fontWidth, "%"); + myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); + myTrackBallSpeed->setTickmarkIntervals(4); + wid.push_back(myTrackBallSpeed); + + // Add driving controller speed + ypos += lineHeight + VGAP; + myDrivingSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Driving controller", + lwidth, kDCSpeedChanged, 4 * fontWidth, "%"); + myDrivingSpeed->setMinValue(1); myDrivingSpeed->setMaxValue(20); + myDrivingSpeed->setTickmarkIntervals(4); + wid.push_back(myDrivingSpeed); + + // Mouse cursor state + lwidth += INDENT; + ypos += lineHeight + VGAP * 4; + items.clear(); + VarList::push_back(items, "-UI, -Emulation", "0"); + VarList::push_back(items, "-UI, +Emulation", "1"); + VarList::push_back(items, "+UI, -Emulation", "2"); + VarList::push_back(items, "+UI, +Emulation", "3"); + myCursorState = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items, + "Mouse cursor visibility ", lwidth, kCursorStateChanged); + wid.push_back(myCursorState); +#ifndef WINDOWED_SUPPORT + myCursorState->clearFlags(Widget::FLAG_ENABLED); +#endif + + // Grab mouse (in windowed mode) + ypos += lineHeight + VGAP; + myGrabMouse = new CheckboxWidget(myTab, _font, HBORDER, ypos, + "Grab mouse in emulation mode"); + wid.push_back(myGrabMouse); +#ifndef WINDOWED_SUPPORT + myGrabMouse->clearFlags(Widget::FLAG_ENABLED); +#endif + + // Add items for mouse + addToFocusList(wid, myTab, tabID); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::loadConfig() { + Settings& settings = instance().settings(); + // Left & right ports - mySAPort->setState(instance().settings().getString("saport") == "rl"); + mySAPort->setState(settings.getString("saport") == "rl"); // Use mouse as a controller myMouseControl->setSelected( - instance().settings().getString("usemouse"), "analog"); + settings.getString("usemouse"), "analog"); + handleMouseControlState(); // Mouse cursor state - myCursorState->setSelected(instance().settings().getString("cursor"), "2"); + myCursorState->setSelected(settings.getString("cursor"), "2"); handleCursorState(); // Joystick deadzone - myDeadzone->setValue(instance().settings().getInt("joydeadzone")); - myDeadzoneLabel->setValue(Joystick::deadzone()); + myDeadzone->setValue(settings.getInt("joydeadzone")); + + // Paddle speed (analog) + myPaddleSpeed->setValue(settings.getInt("psense")); + // Paddle dejitter (analog) + myDejitterBase->setValue(settings.getInt("dejitter.base")); + myDejitterDiff->setValue(settings.getInt("dejitter.diff")); // Paddle speed (digital and mouse) - myDejitterBase->setValue(instance().settings().getInt("dejitter.base")); - myDejitterDiff->setValue(instance().settings().getInt("dejitter.diff")); - updateDejitter(); - myDPaddleSpeed->setValue(instance().settings().getInt("dsense")); - myDPaddleLabel->setLabel(instance().settings().getString("dsense")); - myMPaddleSpeed->setValue(instance().settings().getInt("msense")); - myMPaddleLabel->setLabel(instance().settings().getString("msense")); + myDPaddleSpeed->setValue(settings.getInt("dsense")); + myMPaddleSpeed->setValue(settings.getInt("msense")); // Trackball speed - myTrackBallSpeed->setValue(instance().settings().getInt("tsense")); - myTrackBallLabel->setLabel(instance().settings().getString("tsense")); + myTrackBallSpeed->setValue(settings.getInt("tsense")); + // Driving controller speed + myDrivingSpeed->setValue(settings.getInt("dcsense")); + + // Autofire rate + myAutoFireRate->setValue(settings.getInt("autofirerate")); // AtariVox serial port - myAVoxPort->setText(instance().settings().getString("avoxport")); + myAVoxPort->setText(settings.getString("avoxport")); // EEPROM erase (only enable in emulation mode and for valid controllers) if(instance().hasConsole()) @@ -307,13 +374,13 @@ void InputDialog::loadConfig() myEraseEEPROMButton->setEnabled(false); // Allow all 4 joystick directions - myAllowAll4->setState(instance().settings().getBool("joyallow4")); + myAllowAll4->setState(settings.getBool("joyallow4")); // Grab mouse - myGrabMouse->setState(instance().settings().getBool("grabmouse")); + myGrabMouse->setState(settings.getBool("grabmouse")); // Enable/disable modifier key-combos - myModCombo->setState(instance().settings().getBool("modcombo")); + myModCombo->setState(settings.getBool("modcombo")); myTab->loadConfig(); } @@ -321,60 +388,77 @@ void InputDialog::loadConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::saveConfig() { + Settings& settings = instance().settings(); + // Left & right ports instance().eventHandler().mapStelladaptors(mySAPort->getState() ? "rl": "lr"); // Use mouse as a controller const string& usemouse = myMouseControl->getSelectedTag().toString(); - instance().settings().setValue("usemouse", usemouse); + settings.setValue("usemouse", usemouse); instance().eventHandler().setMouseControllerMode(usemouse); // Joystick deadzone int deadzone = myDeadzone->getValue(); - instance().settings().setValue("joydeadzone", deadzone); + settings.setValue("joydeadzone", deadzone); Joystick::setDeadZone(deadzone); + // Paddle speed (analog) + int sensitivity = myPaddleSpeed->getValue(); + settings.setValue("psense", sensitivity); + Paddles::setAnalogSensitivity(sensitivity); + // Paddle speed (digital and mouse) int dejitter = myDejitterBase->getValue(); - instance().settings().setValue("dejitter.base", dejitter); + settings.setValue("dejitter.base", dejitter); Paddles::setDejitterBase(dejitter); dejitter = myDejitterDiff->getValue(); - instance().settings().setValue("dejitter.diff", dejitter); + settings.setValue("dejitter.diff", dejitter); Paddles::setDejitterDiff(dejitter); - int sensitivity = myDPaddleSpeed->getValue(); - instance().settings().setValue("dsense", sensitivity); + sensitivity = myDPaddleSpeed->getValue(); + settings.setValue("dsense", sensitivity); Paddles::setDigitalSensitivity(sensitivity); sensitivity = myMPaddleSpeed->getValue(); - instance().settings().setValue("msense", sensitivity); + settings.setValue("msense", sensitivity); Paddles::setMouseSensitivity(sensitivity); // Trackball speed sensitivity = myTrackBallSpeed->getValue(); - instance().settings().setValue("tsense", sensitivity); + settings.setValue("tsense", sensitivity); PointingDevice::setSensitivity(sensitivity); + // Driving controller speed + sensitivity = myDrivingSpeed->getValue(); + settings.setValue("dcsense", sensitivity); + Driving::setSensitivity(sensitivity); + + // Autofire rate + int rate = myAutoFireRate->getValue(); + settings.setValue("autofirerate", rate); + Controller::setAutoFireRate(rate); + // AtariVox serial port - instance().settings().setValue("avoxport", myAVoxPort->getText()); + settings.setValue("avoxport", myAVoxPort->getText()); // Allow all 4 joystick directions bool allowall4 = myAllowAll4->getState(); - instance().settings().setValue("joyallow4", allowall4); + settings.setValue("joyallow4", allowall4); instance().eventHandler().allowAllDirections(allowall4); // Grab mouse and hide cursor const string& cursor = myCursorState->getSelectedTag().toString(); - instance().settings().setValue("cursor", cursor); + settings.setValue("cursor", cursor); // only allow grab mouse if cursor is hidden in emulation int state = myCursorState->getSelected(); bool enableGrab = state != 1 && state != 3; bool grab = enableGrab ? myGrabMouse->getState() : false; - instance().settings().setValue("grabmouse", grab); + settings.setValue("grabmouse", grab); instance().frameBuffer().enableGrabMouse(grab); // Enable/disable modifier key-combos - instance().settings().setValue("modcombo", myModCombo->getState()); + settings.setValue("modcombo", myModCombo->getState()); instance().eventHandler().saveKeyMapping(); instance().eventHandler().saveJoyMapping(); @@ -394,26 +478,18 @@ void InputDialog::setDefaults() myMenuEventMapper->setDefaults(); break; - case 2: // Virtual devices - { + case 2: // Devices & Ports // Left & right ports mySAPort->setState(false); - // Use mouse as a controller - myMouseControl->setSelected("analog"); - - // Mouse cursor state - myCursorState->setSelected("2"); - // Joystick deadzone myDeadzone->setValue(0); - myDeadzoneLabel->setValue(3200); - // Paddle speed (digital and mouse) + // Paddle speed (analog) + myPaddleSpeed->setValue(20); + + // Paddle speed (digital) myDPaddleSpeed->setValue(10); - myDPaddleLabel->setLabel("10"); - myMPaddleSpeed->setValue(10); - myMPaddleLabel->setLabel("10"); #if defined(RETRON77) myDejitterBase->setValue(2); myDejitterDiff->setValue(6); @@ -421,26 +497,37 @@ void InputDialog::setDefaults() myDejitterBase->setValue(0); myDejitterDiff->setValue(0); #endif - updateDejitter(); - myTrackBallSpeed->setValue(10); - myTrackBallLabel->setLabel("10"); - + // Autofire rate + myAutoFireRate->setValue(0); // AtariVox serial port myAVoxPort->setText(""); // Allow all 4 joystick directions myAllowAll4->setState(false); - // Grab mouse - myGrabMouse->setState(true); - // Enable/disable modifier key-combos myModCombo->setState(true); - handleCursorState(); - break; - } + + case 3: // Mouse + // Use mouse as a controller + myMouseControl->setSelected("analog"); + + // Paddle speed (mouse) + myMPaddleSpeed->setValue(10); + myTrackBallSpeed->setValue(10); + myDrivingSpeed->setValue(10); + + // Mouse cursor state + myCursorState->setSelected("2"); + + // Grab mouse + myGrabMouse->setState(true); + + handleMouseControlState(); + handleCursorState(); + break; default: break; @@ -566,28 +653,36 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; - case kCursorStateChanged: - handleCursorState(); + case kDeadzoneChanged: + myDeadzone->setValueLabel(3200 + 1000 * myDeadzone->getValue()); break; - case kDeadzoneChanged: - myDeadzoneLabel->setValue(3200 + 1000*myDeadzone->getValue()); + case kPSpeedChanged: + myPaddleSpeed->setValueLabel(Paddles::setAnalogSensitivity(myPaddleSpeed->getValue()) * 100.F + 0.5F); + break; + + case kDejitterAvChanged: + updateDejitterAveraging(); + break; + + case kDejitterReChanged: + updateDejitterReaction(); break; case kDPSpeedChanged: - myDPaddleLabel->setValue(myDPaddleSpeed->getValue()); + myDPaddleSpeed->setValueLabel(myDPaddleSpeed->getValue() * 10); break; - case kMPSpeedChanged: - myMPaddleLabel->setValue(myMPaddleSpeed->getValue()); - break; - - case kDejitterChanged: - updateDejitter(); + case kDCSpeedChanged: + myDrivingSpeed->setValueLabel(myDrivingSpeed->getValue() * 10); break; case kTBSpeedChanged: - myTrackBallLabel->setValue(myTrackBallSpeed->getValue()); + myTrackBallSpeed->setValueLabel(myTrackBallSpeed->getValue() * 10); + break; + + case kAutoFireChanged: + updateAutoFireRate(); break; case kDBButtonPressed: @@ -623,39 +718,65 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, eraseEEPROM(); break; + case kMouseCtrlChanged: + handleMouseControlState(); + handleCursorState(); + break; + + case kCursorStateChanged: + handleCursorState(); + break; + + case kMPSpeedChanged: + myMPaddleSpeed->setValueLabel(myMPaddleSpeed->getValue() * 10); + break; + default: Dialog::handleCommand(sender, cmd, data, 0); } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputDialog::handleCursorState() +void InputDialog::updateDejitterAveraging() { - int state = myCursorState->getSelected(); - bool enableGrab = state != 1 && state != 3; + int strength = myDejitterBase->getValue(); - myGrabMouse->setEnabled(enableGrab); + myDejitterBase->setValueLabel(strength ? std::to_string(strength) : "Off"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputDialog::updateDejitter() +void InputDialog::updateDejitterReaction() { - int strength = myDejitterBase->getValue(); - stringstream label; + int strength = myDejitterDiff->getValue(); - if (strength) - label << myDejitterBase->getValue(); - else - label << "Off"; - - label << " "; - strength = myDejitterDiff->getValue(); - - if (strength) - label << myDejitterDiff->getValue(); - else - label << "Off"; - - myDejitterLabel->setLabel(label.str()); + myDejitterDiff->setValueLabel(strength ? std::to_string(strength) : "Off"); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::updateAutoFireRate() +{ + int rate = myAutoFireRate->getValue(); + + myAutoFireRate->setValueLabel(rate ? std::to_string(rate) : "Off"); + myAutoFireRate->setValueUnit(rate ? " Hz" : ""); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::handleMouseControlState() +{ + bool enable = myMouseControl->getSelected() != 2; + + myMouseSensitivity->setEnabled(enable); + myMPaddleSpeed->setEnabled(enable); + myTrackBallSpeed->setEnabled(enable); + myDrivingSpeed->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::handleCursorState() +{ + int state = myCursorState->getSelected(); + bool enableGrab = state != 1 && state != 3 && myMouseControl->getSelected() != 2; + + myGrabMouse->setEnabled(enableGrab); +} diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 45fb8ed35..6893d2c43 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -59,23 +59,32 @@ class InputDialog : public Dialog void saveConfig() override; void setDefaults() override; - void addDevicePortTab(const GUI::Font& font); + void addDevicePortTab(); + void addMouseTab(); + void handleMouseControlState(); void handleCursorState(); - void updateDejitter(); + void updateDejitterAveraging(); + void updateDejitterReaction(); + void updateAutoFireRate(); void eraseEEPROM(); private: enum { - kCursorStateChanged = 'CSch', kDeadzoneChanged = 'DZch', - kDejitterChanged = 'Pjch', + kPSpeedChanged = 'Ppch', + kDejitterAvChanged = 'JAch', + kDejitterReChanged = 'JRch', kDPSpeedChanged = 'PDch', - kMPSpeedChanged = 'PMch', + kAutoFireChanged = 'AFch', kTBSpeedChanged = 'TBch', + kDCSpeedChanged = 'DCch', kDBButtonPressed = 'DBbp', kEEButtonPressed = 'EEbp', - kConfirmEEEraseCmd = 'EEcf' + kConfirmEEEraseCmd = 'EEcf', + kMouseCtrlChanged = 'MCch', + kCursorStateChanged = 'CSch', + kMPSpeedChanged = 'PMch', }; TabWidget* myTab{nullptr}; @@ -83,30 +92,30 @@ class InputDialog : public Dialog EventMappingWidget* myEmulEventMapper{nullptr}; EventMappingWidget* myMenuEventMapper{nullptr}; - CheckboxWidget* mySAPort{nullptr}; - PopUpWidget* myMouseControl{nullptr}; - PopUpWidget* myCursorState{nullptr}; + CheckboxWidget* mySAPort{nullptr}; EditTextWidget* myAVoxPort{nullptr}; SliderWidget* myDeadzone{nullptr}; - StaticTextWidget* myDeadzoneLabel{nullptr}; + SliderWidget* myPaddleSpeed{nullptr}; SliderWidget* myDejitterBase{nullptr}; SliderWidget* myDejitterDiff{nullptr}; SliderWidget* myDPaddleSpeed{nullptr}; - SliderWidget* myMPaddleSpeed{nullptr}; - SliderWidget* myTrackBallSpeed{nullptr}; - StaticTextWidget* myDejitterLabel{nullptr}; - StaticTextWidget* myDPaddleLabel{nullptr}; - StaticTextWidget* myMPaddleLabel{nullptr}; - StaticTextWidget* myTrackBallLabel{nullptr}; + SliderWidget* myAutoFireRate{nullptr}; CheckboxWidget* myAllowAll4{nullptr}; - CheckboxWidget* myGrabMouse{nullptr}; CheckboxWidget* myModCombo{nullptr}; ButtonWidget* myJoyDlgButton{nullptr}; ButtonWidget* myEraseEEPROMButton{nullptr}; + PopUpWidget* myMouseControl{nullptr}; + StaticTextWidget* myMouseSensitivity{nullptr}; + SliderWidget* myMPaddleSpeed{nullptr}; + SliderWidget* myTrackBallSpeed{nullptr}; + SliderWidget* myDrivingSpeed{nullptr}; + PopUpWidget* myCursorState{nullptr}; + CheckboxWidget* myGrabMouse{nullptr}; + // Show the list of joysticks that the eventhandler knows about unique_ptr myJoyDialog; diff --git a/src/gui/InputTextDialog.cxx b/src/gui/InputTextDialog.cxx index b543d9729..12e7a66d4 100644 --- a/src/gui/InputTextDialog.cxx +++ b/src/gui/InputTextDialog.cxx @@ -50,15 +50,20 @@ InputTextDialog::InputTextDialog(GuiObject* boss, const GUI::Font& lfont, void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont, const StringList& labels) { - const int fontWidth = lfont.getMaxCharWidth(), - fontHeight = lfont.getFontHeight(), - lineHeight = lfont.getLineHeight(); + const int lineHeight = lfont.getLineHeight(), + fontWidth = lfont.getMaxCharWidth(), + fontHeight = lfont.getFontHeight(), + buttonHeight = lfont.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + uInt32 xpos, ypos, i, lwidth = 0, maxIdx = 0; WidgetArray wid; // Calculate real dimensions - _w = fontWidth * 41; - _h = lineHeight * 4 + int(labels.size()) * (lineHeight + 5) + _th; + _w = HBORDER * 2 + fontWidth * 39; + _h = buttonHeight + lineHeight + VGAP + int(labels.size()) * (lineHeight + VGAP) + _th + VBORDER * 2; // Determine longest label for(i = 0; i < labels.size(); ++i) @@ -72,25 +77,25 @@ void InputTextDialog::initialize(const GUI::Font& lfont, const GUI::Font& nfont, lwidth = lfont.getStringWidth(labels[maxIdx]); // Create editboxes for all labels - ypos = lineHeight + _th; + ypos = VBORDER + _th; for(i = 0; i < labels.size(); ++i) { - xpos = 10; + xpos = HBORDER; new StaticTextWidget(this, lfont, xpos, ypos + 2, lwidth, fontHeight, labels[i], TextAlign::Left); xpos += lwidth + fontWidth; EditTextWidget* w = new EditTextWidget(this, nfont, xpos, ypos, - _w - xpos - 10, lineHeight, ""); + _w - xpos - HBORDER, lineHeight, ""); wid.push_back(w); myInput.push_back(w); - ypos += lineHeight + 5; + ypos += lineHeight + VGAP; } - xpos = 10; - myMessage = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2*xpos, fontHeight, + xpos = HBORDER; ypos += VGAP; + myMessage = new StaticTextWidget(this, lfont, xpos, ypos, _w - 2 * xpos, fontHeight, "", TextAlign::Left); myMessage->setTextColor(kTextColorEm); diff --git a/src/gui/JoystickDialog.cxx b/src/gui/JoystickDialog.cxx index 16f8e84f0..218179e72 100644 --- a/src/gui/JoystickDialog.cxx +++ b/src/gui/JoystickDialog.cxx @@ -32,33 +32,38 @@ JoystickDialog::JoystickDialog(GuiObject* boss, const GUI::Font& font, int xpos, ypos; WidgetArray wid; - int buttonWidth = font.getStringWidth("Remove ") + 20, - buttonHeight = font.getLineHeight() + 4; + const int lineHeight = font.getLineHeight(), + fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonWidth = font.getStringWidth("Remove") + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; // Joystick list - xpos = 10; ypos = 10 + _th; + xpos = HBORDER; ypos = VBORDER + _th; int w = _w - 2 * xpos; - int h = _h - buttonHeight - ypos - 20; + int h = _h - buttonHeight - ypos - VBORDER * 2; myJoyList = new StringListWidget(this, font, xpos, ypos, w, h); myJoyList->setEditable(false); wid.push_back(myJoyList); // Joystick ID - ypos = _h - buttonHeight - 10; + ypos = _h - VBORDER - (buttonHeight + lineHeight) / 2; StaticTextWidget* t = new StaticTextWidget(this, font, xpos, ypos+2, "Joystick ID "); - xpos += t->getWidth() + 4; + xpos += t->getWidth(); myJoyText = new EditTextWidget(this, font, xpos, ypos, - font.getStringWidth("Unplugged")+8, font.getLineHeight(), ""); + font.getStringWidth("Unplugged "), font.getLineHeight(), ""); myJoyText->setEditable(false); // Add buttons at bottom - xpos = _w - buttonWidth - 10; + xpos = _w - buttonWidth - HBORDER; + ypos = _h - VBORDER - buttonHeight; myCloseBtn = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Close", GuiObject::kCloseCmd); addOKWidget(myCloseBtn); addCancelWidget(myCloseBtn); - buttonWidth = font.getStringWidth("Remove") + 20; - xpos -= buttonWidth + 8; + xpos -= buttonWidth + fontWidth; myRemoveBtn = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Remove", kRemoveCmd); myRemoveBtn->clearFlags(Widget::FLAG_ENABLED); diff --git a/src/gui/Launcher.cxx b/src/gui/Launcher.cxx index eb1324f9f..315a14f41 100644 --- a/src/gui/Launcher.cxx +++ b/src/gui/Launcher.cxx @@ -59,7 +59,8 @@ Launcher::~Launcher() FBInitStatus Launcher::initializeVideo() { string title = string("Stella ") + STELLA_VERSION; - return myOSystem.frameBuffer().createDisplay(title, myWidth, myHeight); + return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Launcher, + myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -75,9 +76,9 @@ const string& Launcher::selectedRomMD5() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const FilesystemNode& Launcher::currentNode() const +const FilesystemNode& Launcher::currentDir() const { - return (static_cast(myBaseDialog))->currentNode(); + return (static_cast(myBaseDialog))->currentDir(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/Launcher.hxx b/src/gui/Launcher.hxx index 7a1b57fa7..af0e91f8b 100644 --- a/src/gui/Launcher.hxx +++ b/src/gui/Launcher.hxx @@ -55,9 +55,9 @@ class Launcher : public DialogContainer const string& selectedRomMD5(); /** - Wrapper for LauncherDialog::currentNode() method. + Wrapper for LauncherDialog::currentDir() method. */ - const FilesystemNode& currentNode() const; + const FilesystemNode& currentDir() const; /** Wrapper for LauncherDialog::reload() method. diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 513718c8f..cc999c2bb 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -30,6 +30,7 @@ #include "HighScoresManager.hxx" #include "GlobalPropsDialog.hxx" #include "StellaSettingsDialog.hxx" +#include "WhatsNewDialog.hxx" #include "MessageBox.hxx" #include "OSystem.hxx" #include "FrameBuffer.hxx" @@ -39,9 +40,18 @@ #include "Props.hxx" #include "PropsSet.hxx" #include "RomInfoWidget.hxx" +#include "TIAConstants.hxx" #include "Settings.hxx" #include "Widget.hxx" #include "Font.hxx" +#include "StellaFont.hxx" +#include "ConsoleBFont.hxx" +#include "ConsoleMediumBFont.hxx" +#include "StellaMediumFont.hxx" +#include "StellaLargeFont.hxx" +#include "Stella12x24tFont.hxx" +#include "Stella14x28tFont.hxx" +#include "Stella16x32tFont.hxx" #include "Version.hxx" #include "LauncherDialog.hxx" @@ -53,25 +63,26 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, myUseMinimalUI = instance().settings().getBool("minimal_ui"); const GUI::Font& font = instance().frameBuffer().launcherFont(); - - const int HBORDER = 10; - const int BUTTON_GAP = 8; const int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), lineHeight = font.getLineHeight(), - bwidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)), - bheight = myUseMinimalUI ? lineHeight - 4 : lineHeight + 4, - LBL_GAP = fontWidth; - int xpos = 0, ypos = 0, lwidth = 0, lwidth2 = 0; - WidgetArray wid; + HBORDER = fontWidth * 1.25, + VBORDER = fontHeight / 2, + BUTTON_GAP = fontWidth, + LBL_GAP = fontWidth, + VGAP = fontHeight / 4, + buttonHeight = myUseMinimalUI ? lineHeight - VGAP * 2: lineHeight * 1.25, + buttonWidth = (_w - 2 * HBORDER - BUTTON_GAP * (4 - 1)); + int xpos = HBORDER, ypos = VBORDER, lwidth = 0, lwidth2 = 0; + WidgetArray wid; string lblRom = "Select a ROM from the list" + ELLIPSIS; const string& lblFilter = "Filter"; const string& lblAllFiles = "Show all files"; const string& lblFound = "XXXX items found"; lwidth = font.getStringWidth(lblRom); - lwidth2 = font.getStringWidth(lblAllFiles) + 20; + lwidth2 = font.getStringWidth(lblAllFiles) + CheckboxWidget::boxSize(font); int lwidth3 = font.getStringWidth(lblFilter); int lwidth4 = font.getStringWidth(lblFound); @@ -90,14 +101,12 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, #if defined(RETRON77) ver << " for RetroN 77"; #endif - ypos += 8; - new StaticTextWidget(this, font, xpos, ypos, _w - 20, fontHeight, + new StaticTextWidget(this, font, 0, ypos, _w, fontHeight, ver.str(), TextAlign::Center); - ypos += fontHeight - 4; + ypos += lineHeight; } // Show the header - xpos += HBORDER; ypos += 8; new StaticTextWidget(this, font, xpos, ypos, lblRom); // Shop the files counter xpos = _w - HBORDER - lwidth4; @@ -125,17 +134,13 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Add list with game titles // Before we add the list, we need to know the size of the RomInfoWidget - xpos = HBORDER; ypos += lineHeight + 4; - int romWidth = 0; - int romSize = instance().settings().getInt("romviewer"); - if(romSize > 1 && w >= 1000 && h >= 720) - romWidth = 660; - else if(romSize > 0 && w >= 640 && h >= 480) - romWidth = 365; - - int listWidth = _w - (romWidth > 0 ? romWidth+8 : 0) - 20; - myList = new FileListWidget(this, font, xpos, ypos, - listWidth, _h - 43 - bheight - fontHeight - lineHeight); + int listHeight = _h - VBORDER * 2 - buttonHeight - lineHeight * 2 - VGAP * 6; + float imgZoom = getRomInfoZoom(listHeight); + int romWidth = imgZoom * TIAConstants::viewableWidth; + if(romWidth > 0) romWidth += HBORDER; + int listWidth = _w - (romWidth > 0 ? romWidth + fontWidth : 0) - HBORDER * 2; + xpos = HBORDER; ypos += lineHeight + VGAP; + myList = new FileListWidget(this, font, xpos, ypos, listWidth, listHeight); myList->setEditable(false); myList->setListMode(FilesystemNode::ListMode::All); wid.push_back(myList); @@ -143,16 +148,23 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, // Add ROM info area (if enabled) if(romWidth > 0) { - xpos += myList->getWidth() + 8; - myRomInfoWidget = new RomInfoWidget(this, - romWidth < 660 ? instance().frameBuffer().smallFont() : - instance().frameBuffer().infoFont(), - xpos, ypos, romWidth, myList->getHeight()); + xpos += myList->getWidth() + fontWidth; + + // Initial surface size is the same as the viewable area + Common::Size imgSize(TIAConstants::viewableWidth*imgZoom, + TIAConstants::viewableHeight*imgZoom); + + // Calculate font area, and in the process the font that can be used + Common::Size fontArea(romWidth - fontWidth * 2, myList->getHeight() - imgSize.h - VGAP * 3); + + setRomInfoFont(fontArea); + myRomInfoWidget = new RomInfoWidget(this, *myROMInfoFont, + xpos, ypos, romWidth, myList->getHeight(), imgSize); } // Add textfield to show current directory xpos = HBORDER; - ypos += myList->getHeight() + 8; + ypos += myList->getHeight() + VGAP * 2; lwidth = font.getStringWidth("Path") + LBL_GAP; myDirLabel = new StaticTextWidget(this, font, xpos, ypos+2, lwidth, fontHeight, "Path", TextAlign::Left); @@ -164,42 +176,48 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, if(!myUseMinimalUI) { // Add four buttons at the bottom - xpos = HBORDER; ypos += myDir->getHeight() + 8; + xpos = HBORDER; ypos = _h - VBORDER - buttonHeight; #ifndef BSPF_MACOS - myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight, + myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, "Select", kLoadROMCmd); wid.push_back(myStartButton); - xpos += (bwidth + 0) / 4 + BUTTON_GAP; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight, + + xpos += (buttonWidth + 0) / 4 + BUTTON_GAP; + myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); - xpos += (bwidth + 1) / 4 + BUTTON_GAP; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 2) / 4, bheight, - "Options" + ELLIPSIS, kOptionsCmd); - wid.push_back(myOptionsButton); - xpos += (bwidth + 2) / 4 + BUTTON_GAP; - myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight, - "Quit", kQuitCmd); - wid.push_back(myQuitButton); - #else - myQuitButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 0) / 4, bheight, - "Quit", kQuitCmd); - wid.push_back(myQuitButton); - xpos += (bwidth + 0) / 4 + BUTTON_GAP; - myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 1) / 4, bheight, + + xpos += (buttonWidth + 1) / 4 + BUTTON_GAP; + myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, "Options" + ELLIPSIS, kOptionsCmd); wid.push_back(myOptionsButton); - xpos += (bwidth + 1) / 4 + BUTTON_GAP; - myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 2) / 4, bheight, + + xpos += (buttonWidth + 2) / 4 + BUTTON_GAP; + myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 4) / 4, buttonHeight, + "Quit", kQuitCmd); + wid.push_back(myQuitButton); + #else + myQuitButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 0) / 4, buttonHeight, + "Quit", kQuitCmd); + wid.push_back(myQuitButton); + + xpos += (buttonWidth + 0) / 4 + BUTTON_GAP; + myOptionsButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 1) / 4, buttonHeight, + "Options" + ELLIPSIS, kOptionsCmd); + wid.push_back(myOptionsButton); + + xpos += (buttonWidth + 1) / 4 + BUTTON_GAP; + myPrevDirButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 2) / 4, buttonHeight, "Go Up", kPrevDirCmd); wid.push_back(myPrevDirButton); - xpos += (bwidth + 2) / 4 + BUTTON_GAP; - myStartButton = new ButtonWidget(this, font, xpos, ypos, (bwidth + 3) / 4, bheight, + + xpos += (buttonWidth + 2) / 4 + BUTTON_GAP; + myStartButton = new ButtonWidget(this, font, xpos, ypos, (buttonWidth + 3) / 4, buttonHeight, "Select", kLoadROMCmd); wid.push_back(myStartButton); #endif } - if (myUseMinimalUI) // Highlight 'Rom Listing' + if(myUseMinimalUI) // Highlight 'Rom Listing' mySelectedItem = 0; else mySelectedItem = 2; @@ -207,9 +225,9 @@ LauncherDialog::LauncherDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(wid); // Create (empty) context menu for ROM list options - myMenu = make_unique(this, osystem.frameBuffer().font(), EmptyVarList); + myMenu = make_unique(this, osystem.frameBuffer().launcherFont(), EmptyVarList); - // Create global props dialog, which is used to temporarily overrride + // Create global props dialog, which is used to temporarily override // ROM properties myGlobalProps = make_unique(this, myUseMinimalUI ? osystem.frameBuffer().launcherFont() : osystem.frameBuffer().font()); @@ -251,6 +269,12 @@ const FilesystemNode& LauncherDialog::currentNode() const return myList->selected(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const FilesystemNode& LauncherDialog::currentDir() const +{ + return myList->currentDir(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherDialog::reload() { @@ -266,6 +290,14 @@ void LauncherDialog::loadConfig() const string& tmpromdir = instance().settings().getString("tmpromdir"); const string& romdir = tmpromdir != "" ? tmpromdir : instance().settings().getString("romdir"); + const string& version = instance().settings().getString("stella.version"); + + // Show "What's New" message when a new version of Stella is run for the first time + if(version != STELLA_VERSION) + { + openWhatsNew(); + instance().settings().setValue("stella.version", STELLA_VERSION); + } // Assume that if the list is empty, this is the first time that loadConfig() // has been called (and we should reload the list) @@ -286,6 +318,13 @@ void LauncherDialog::loadConfig() myList->clearFlags(Widget::FLAG_WANTS_RAWDATA); // always reset this } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::saveConfig() +{ + if(instance().settings().getBool("followlauncher")) + instance().settings().setValue("romdir", myList->currentDir().getShortPath()); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherDialog::updateUI() { @@ -326,6 +365,76 @@ void LauncherDialog::applyFiltering() ); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float LauncherDialog::getRomInfoZoom(int listHeight) const +{ + // The ROM info area is some multiple of the minimum TIA image size + float zoom = instance().settings().getFloat("romviewer"); + + if(zoom > 0.F) + { + const GUI::Font& font = instance().frameBuffer().launcherFont(); + const GUI::Font& smallFont = instance().frameBuffer().smallFont(); + const int fontWidth = font.getMaxCharWidth(), + HBORDER = fontWidth * 1.25; + + // upper zoom limit - at least 24 launchers chars/line and 7 + 4 ROM info lines + if((_w - (HBORDER * 2 + fontWidth + 30) - zoom * TIAConstants::viewableWidth) + / font.getMaxCharWidth() < MIN_LAUNCHER_CHARS) + { + zoom = float(_w - (HBORDER * 2 + fontWidth + 30) - MIN_LAUNCHER_CHARS * font.getMaxCharWidth()) + / TIAConstants::viewableWidth; + } + if((listHeight - 12 - zoom * TIAConstants::viewableHeight) < + MIN_ROMINFO_ROWS * smallFont.getLineHeight() + + MIN_ROMINFO_LINES * smallFont.getFontHeight()) + { + zoom = float(listHeight - 12 - + MIN_ROMINFO_ROWS * smallFont.getLineHeight() - + MIN_ROMINFO_LINES * smallFont.getFontHeight()) + / TIAConstants::viewableHeight; + } + + // lower zoom limit - at least 30 ROM info chars/line + if((zoom * TIAConstants::viewableWidth) + / smallFont.getMaxCharWidth() < MIN_ROMINFO_CHARS + 6) + { + zoom = float(MIN_ROMINFO_CHARS * smallFont.getMaxCharWidth() + 6) + / TIAConstants::viewableWidth; + } + } + return zoom; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::setRomInfoFont(const Common::Size& area) +{ + // TODO: Perhaps offer a setting to override the font used? + + FontDesc FONTS[7] = { + GUI::stella16x32tDesc, GUI::stella14x28tDesc, GUI::stella12x24tDesc, + GUI::stellaLargeDesc, GUI::stellaMediumDesc, + GUI::consoleMediumBDesc, GUI::consoleBDesc + }; + + // Try to pick a font that works best, based on the available area + for(size_t i = 0; i < sizeof(FONTS) / sizeof(FontDesc); ++i) + { + // only use fonts <= launcher fonts + if(instance().frameBuffer().launcherFont().getFontHeight() >= FONTS[i].height) + { + if(area.h >= uInt32(MIN_ROMINFO_ROWS * FONTS[i].height + 2 + + MIN_ROMINFO_LINES * FONTS[i].height) + && area.w >= uInt32(MIN_ROMINFO_CHARS * FONTS[i].maxwidth)) + { + myROMInfoFont = make_unique(FONTS[i]); + return; + } + } + } + myROMInfoFont = make_unique(GUI::stellaDesc); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherDialog::loadRomInfo() { @@ -334,13 +443,7 @@ void LauncherDialog::loadRomInfo() const string& md5 = selectedRomMD5(); if(md5 != EmptyString) - { - // Get the properties for this entry - Properties props; - instance().propSet().getMD5WithInsert(currentNode(), md5, props); - - myRomInfoWidget->setProperties(props, currentNode()); - } + myRomInfoWidget->setProperties(currentNode(), md5); else myRomInfoWidget->clearProperties(); } @@ -494,6 +597,7 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, case kLoadROMCmd: case FileListWidget::ItemActivated: + saveConfig(); loadRom(); break; @@ -521,17 +625,24 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, break; case kQuitCmd: + saveConfig(); close(); instance().eventHandler().quit(); break; case kRomDirChosenCmd: { - FilesystemNode node(instance().settings().getString("romdir")); - if(!(node.exists() && node.isDirectory())) - node = FilesystemNode("~"); + string romDir = instance().settings().getString("romdir"); - myList->setDirectory(node); + if(myList->currentDir().getPath() != romDir) + { + FilesystemNode node(romDir); + + if(!(node.exists() && node.isDirectory())) + node = FilesystemNode("~"); + + myList->setDirectory(node); + } break; } @@ -560,15 +671,23 @@ void LauncherDialog::loadRom() instance().frameBuffer().showMessage(result, MessagePosition::MiddleCenter, true); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::setDefaultDir() +{ + instance().settings().setValue("romdir", myList->currentDir().getShortPath()); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LauncherDialog::openSettings() { + saveConfig(); + // Create an options dialog, similar to the in-game one if (instance().settings().getBool("basic_settings")) { if (myStellaSettingsDialog == nullptr) myStellaSettingsDialog = make_unique(instance(), parent(), - instance().frameBuffer().launcherFont(), _w, _h, Menu::AppMode::launcher); + _w, _h, Menu::AppMode::launcher); myStellaSettingsDialog->open(); } else @@ -590,3 +709,12 @@ void LauncherDialog::openHighScores() myHighScoresDialog->open(); } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void LauncherDialog::openWhatsNew() +{ + if(myWhatsNewDialog == nullptr) + myWhatsNewDialog = make_unique(instance(), parent(), _font, _w, _h); + myWhatsNewDialog->open(); + +} diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx index 7aba78f22..7b1feb3c1 100644 --- a/src/gui/LauncherDialog.hxx +++ b/src/gui/LauncherDialog.hxx @@ -27,12 +27,16 @@ class OptionsDialog; class HighScoresDialog; class GlobalPropsDialog; class StellaSettingsDialog; +class WhatsNewDialog; class OSystem; class Properties; class EditTextWidget; class FileListWidget; class RomInfoWidget; class StaticTextWidget; +namespace Common { + struct Size; +} namespace GUI { class MessageBox; } @@ -42,7 +46,6 @@ namespace GUI { #include "bspf.hxx" #include "Dialog.hxx" #include "FSNode.hxx" -#include "Stack.hxx" class LauncherDialog : public Dialog { @@ -75,18 +78,30 @@ class LauncherDialog : public Dialog const string& selectedRomMD5(); /** - Get node for the currently selected directory. + Get node for the currently selected entry. - @return FilesystemNode currently active + @return FilesystemNode currently selected */ const FilesystemNode& currentNode() const; + /** + Get node for the current directory. + + @return FilesystemNode (directory) currently active + */ + const FilesystemNode& currentDir() const; + /** Reload the current listing */ void reload(); private: + static constexpr int MIN_LAUNCHER_CHARS = 24; + static constexpr int MIN_ROMINFO_CHARS = 30; + static constexpr int MIN_ROMINFO_ROWS = 7; // full lines + static constexpr int MIN_ROMINFO_LINES = 4; // extra lines + void center() override { positionAt(0); } void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; @@ -96,15 +111,21 @@ class LauncherDialog : public Dialog Event::Type getJoyAxisEvent(int stick, JoyAxis axis, JoyDir adir, int button) override; void loadConfig() override; + void saveConfig() override; void updateUI(); void applyFiltering(); + float getRomInfoZoom(int listHeight) const; + void setRomInfoFont(const Common::Size& area); + void loadRom(); void loadRomInfo(); void handleContextMenu(); void showOnlyROMs(bool state); + void setDefaultDir(); void openSettings(); void openHighScores(); + void openWhatsNew(); private: unique_ptr myOptionsDialog; @@ -113,6 +134,10 @@ class LauncherDialog : public Dialog unique_ptr myMenu; unique_ptr myGlobalProps; unique_ptr myRomDir; + unique_ptr myWhatsNewDialog; + + // automatically sized font for ROM info viewer + unique_ptr myROMInfoFont; ButtonWidget* myStartButton{nullptr}; ButtonWidget* myPrevDirButton{nullptr}; @@ -136,10 +161,10 @@ class LauncherDialog : public Dialog bool myEventHandled{false}; enum { - kAllfilesCmd = 'lalf', // show all files (or ROMs only) - kPrevDirCmd = 'PRVD', - kOptionsCmd = 'OPTI', - kQuitCmd = 'QUIT' + kAllfilesCmd = 'lalf', // show all files (or ROMs only) + kPrevDirCmd = 'PRVD', + kOptionsCmd = 'OPTI', + kQuitCmd = 'QUIT' }; private: diff --git a/src/gui/ListWidget.cxx b/src/gui/ListWidget.cxx index 850b7710b..aa8ed9455 100644 --- a/src/gui/ListWidget.cxx +++ b/src/gui/ListWidget.cxx @@ -39,11 +39,12 @@ ListWidget::ListWidget(GuiObject* boss, const GUI::Font& font, _rows = h / _fontHeight; // Set real dimensions - _w = w - kScrollBarWidth; + _w = w - ScrollBarWidget::scrollBarWidth(_font); _h = h + 2; // Create scrollbar and attach to the list - _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, kScrollBarWidth, _h); + _scrollBar = new ScrollBarWidget(boss, font, _x + _w, _y, + ScrollBarWidget::scrollBarWidth(_font), _h); _scrollBar->setTarget(this); } @@ -144,7 +145,7 @@ void ListWidget::scrollTo(int item) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int ListWidget::getWidth() const { - return _w + kScrollBarWidth; + return _w + ScrollBarWidget::scrollBarWidth(_font); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 779cd1868..bf53d80a0 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -37,8 +37,14 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, : Dialog(osystem, parent, font, "System logs") { const int lineHeight = font.getLineHeight(), - buttonWidth = font.getStringWidth("Save log to disk") + 20, - buttonHeight = font.getLineHeight() + 4; + fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(), + buttonWidth = font.getStringWidth("Save log to disk") + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int VGAP = fontHeight / 4; + int xpos, ypos; WidgetArray wid; @@ -47,13 +53,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, setSize(4000, 4000, max_w, max_h); // Test listing of the log output - xpos = 10; ypos = 10 + _th; + xpos = HBORDER; ypos = VBORDER + _th; myLogInfo = new StringListWidget(this, uselargefont ? font : instance().frameBuffer().infoFont(), xpos, ypos, _w - 2 * xpos, - _h - buttonHeight - ypos - 20 - 2 * lineHeight, false); + _h - buttonHeight - ypos - VBORDER - lineHeight - VGAP * 4, false); myLogInfo->setEditable(false); wid.push_back(myLogInfo); - ypos += myLogInfo->getHeight() + 8; + ypos += myLogInfo->getHeight() + VGAP * 2; // Level of logging (how much info to print) VariantList items; @@ -67,13 +73,13 @@ LoggerDialog::LoggerDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myLogLevel); // Should log output also be shown on the console? - xpos += myLogLevel->getWidth() + 32; + xpos += myLogLevel->getWidth() + fontWidth * 4; myLogToConsole = new CheckboxWidget(this, font, xpos, ypos + 1, "Print to console"); wid.push_back(myLogToConsole); // Add Save, OK and Cancel buttons ButtonWidget* b; - b = new ButtonWidget(this, font, 10, _h - buttonHeight - 10, + b = new ButtonWidget(this, font, HBORDER, _h - buttonHeight - VBORDER, buttonWidth, buttonHeight, "Save log to disk", GuiObject::kDefaultsCmd); wid.push_back(b); @@ -110,15 +116,19 @@ void LoggerDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void LoggerDialog::saveLogFile() { - ostringstream path; - path << instance().defaultSaveDir() << "stella.log"; - FilesystemNode node(path.str()); + FilesystemNode node = instance().defaultSaveDir(); + node /= "stella.log"; - ofstream out(node.getPath()); - if(out.is_open()) + try { + stringstream out; out << Logger::instance().logMessages(); - instance().frameBuffer().showMessage("Saving log file to " + path.str()); + instance().frameBuffer().showMessage("Saving log file to " + node.getShortPath()); + node.write(out); + } + catch(...) + { + instance().frameBuffer().showMessage("Error saving log file to " + node.getShortPath()); } } diff --git a/src/gui/Menu.cxx b/src/gui/Menu.cxx index c47525da9..547f8e2ac 100644 --- a/src/gui/Menu.cxx +++ b/src/gui/Menu.cxx @@ -19,6 +19,7 @@ #include "FrameBufferConstants.hxx" #include "OptionsDialog.hxx" #include "StellaSettingsDialog.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "bspf.hxx" #include "Menu.hxx" @@ -42,8 +43,8 @@ Dialog* Menu::baseDialog() if (myOSystem.settings().getBool("basic_settings")) { if (stellaSettingDialog == nullptr) - stellaSettingDialog = new StellaSettingsDialog(myOSystem, *this, myOSystem.frameBuffer().font(), - FBMinimum::Width, FBMinimum::Height, AppMode::emulator); + stellaSettingDialog = new StellaSettingsDialog(myOSystem, *this, + 1280, 720, AppMode::emulator); return stellaSettingDialog; } else diff --git a/src/gui/MessageBox.cxx b/src/gui/MessageBox.cxx index 30bdc88d0..d5b5cf11b 100644 --- a/src/gui/MessageBox.cxx +++ b/src/gui/MessageBox.cxx @@ -79,21 +79,24 @@ MessageBox::MessageBox(GuiObject* boss, const GUI::Font& font, // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MessageBox::addText(const GUI::Font& font, const StringList& text) { - const int fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(); - int xpos, ypos; + const int fontWidth = font.getMaxCharWidth(), + fontHeight = font.getFontHeight(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos; // Set real dimensions int str_w = 0; + for(const auto& s: text) str_w = std::max(int(s.length()), str_w); - _w = std::min(str_w * fontWidth + 20, _w); - _h = std::min(uInt32((text.size() + 2) * fontHeight + 20 + _th), uInt32(_h)); + _w = std::min(str_w * fontWidth + HBORDER * 2, _w); + _h = std::min(uInt32((text.size() + 2) * fontHeight + VBORDER * 2 + _th), uInt32(_h)); - xpos = 10; ypos = 10 + _th; + xpos = HBORDER; ypos = VBORDER + _th; for(const auto& s: text) { - new StaticTextWidget(this, font, xpos, ypos, _w - 20, + new StaticTextWidget(this, font, xpos, ypos, _w - HBORDER * 2, fontHeight, s, TextAlign::Left); ypos += fontHeight; } diff --git a/src/gui/MessageDialog.cxx b/src/gui/MessageDialog.cxx index d00acc5a5..ca52c99e6 100644 --- a/src/gui/MessageDialog.cxx +++ b/src/gui/MessageDialog.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Console.hxx" #include "EventHandler.hxx" #include "Font.hxx" diff --git a/src/gui/MessageMenu.cxx b/src/gui/MessageMenu.cxx index f7c7f0faa..19b700ae7 100644 --- a/src/gui/MessageMenu.cxx +++ b/src/gui/MessageMenu.cxx @@ -16,6 +16,7 @@ //============================================================================ #include "Dialog.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "MessageDialog.hxx" #include "MessageMenu.hxx" diff --git a/src/gui/MinUICommandDialog.cxx b/src/gui/MinUICommandDialog.cxx index e6cab4fba..080316005 100644 --- a/src/gui/MinUICommandDialog.cxx +++ b/src/gui/MinUICommandDialog.cxx @@ -67,7 +67,7 @@ MinUICommandDialog::MinUICommandDialog(OSystem& osystem, DialogContainer& parent wid.push_back(myColorButton); myLeftDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); wid.push_back(myLeftDiffButton); - myRightDiffButton = ADD_CD_BUTTON("", kLeftDiffCmd); + myRightDiffButton = ADD_CD_BUTTON("", kRightDiffCmd); wid.push_back(myRightDiffButton); // Column 2 @@ -217,7 +217,7 @@ void MinUICommandDialog::handleCommand(CommandSender* sender, int cmd, // Column 3 case kFormatCmd: - instance().console().toggleFormat(); + instance().console().selectFormat(); updateTVFormat(); break; @@ -307,7 +307,7 @@ void MinUICommandDialog::openSettings() { if (myStellaSettingsDialog == nullptr) myStellaSettingsDialog = make_unique(instance(), parent(), - instance().frameBuffer().launcherFont(), FBMinimum::Width, FBMinimum::Height, Menu::AppMode::launcher); + 1280, 720, Menu::AppMode::launcher); myStellaSettingsDialog->open(); } else diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index 1b03b8cfc..865103822 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -23,8 +23,8 @@ #include "Widget.hxx" #include "Font.hxx" #include "Control.hxx" -#include "VideoDialog.hxx" -#include "AudioDialog.hxx" +#include "EmulationDialog.hxx" +#include "VideoAudioDialog.hxx" #include "InputDialog.hxx" #include "UIDialog.hxx" #include "SnapshotDialog.hxx" @@ -49,19 +49,24 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, GuiObject* boss, int max_w, int max_h, Menu::AppMode mode) : Dialog(osystem, parent, osystem.frameBuffer().font(), "Options"), + myBoss(boss), myMode(mode) { // do not show basic settings options in debugger bool minSettings = osystem.settings().getBool("minimal_ui") && mode != Menu::AppMode::debugger; - const int buttonHeight = _font.getLineHeight() + 6, - GAP = buttonHeight > 26 ? 5 : 4, - rowHeight = buttonHeight + GAP; - const int VBORDER = GAP * 2 + 2; - const int HBORDER = GAP * 2 + 2; - int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + GAP * 5; + const int + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(), + buttonHeight = _font.getLineHeight() * 1.25, + VGAP = fontHeight / 4, + HGAP = fontWidth, + rowHeight = buttonHeight + VGAP; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int buttonWidth = _font.getStringWidth("Game Properties" + ELLIPSIS) + fontWidth * 2.5; - _w = 2 * buttonWidth + HBORDER * 3; - _h = 7 * rowHeight + VBORDER * 2 - GAP + _th; + _w = 2 * buttonWidth + HBORDER * 2 + HGAP; + _h = 7 * rowHeight + VBORDER * 2 - VGAP + _th; int xoffset = HBORDER, yoffset = VBORDER + _th; WidgetArray wid; @@ -72,8 +77,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, ButtonWidget* bw = new ButtonWidget(this, _font, xoffset, yoffset, _w - HBORDER * 2, buttonHeight, "Use Basic Settings", kBasSetCmd); wid.push_back(bw); - yoffset += rowHeight + GAP * 2; - _h += rowHeight + GAP * 2; + yoffset += rowHeight + VGAP * 2; + _h += rowHeight + VGAP * 2; } auto ADD_OD_BUTTON = [&](const string& label, int cmd) @@ -84,13 +89,10 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, return bw; }; - b = ADD_OD_BUTTON("Video" + ELLIPSIS, kVidCmd); + b = ADD_OD_BUTTON("Video & Audio" + ELLIPSIS, kVidCmd); wid.push_back(b); - b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd); -#ifndef SOUND_SUPPORT - b->clearFlags(Widget::FLAG_ENABLED); -#endif + b = ADD_OD_BUTTON("Emulation" + ELLIPSIS, kEmuCmd); wid.push_back(b); b = ADD_OD_BUTTON("Input" + ELLIPSIS, kInptCmd); @@ -107,8 +109,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(b); // Move to second column - xoffset += buttonWidth + HBORDER; - yoffset = minSettings ? VBORDER + _th + rowHeight + GAP * 2 : VBORDER + _th; + xoffset += buttonWidth + HGAP; + yoffset = minSettings ? VBORDER + _th + rowHeight + VGAP * 2 : VBORDER + _th; myGameInfoButton = ADD_OD_BUTTON("Game Properties" + ELLIPSIS, kInfoCmd); wid.push_back(myGameInfoButton); @@ -131,15 +133,15 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent, b = ADD_OD_BUTTON("About" + ELLIPSIS, kAboutCmd); wid.push_back(b); - buttonWidth = _font.getStringWidth(" Close ") + GAP * 5; - xoffset -= (buttonWidth + HBORDER) / 2; + buttonWidth = _font.getStringWidth(" Close ") + fontWidth * 2.5; + xoffset -= (buttonWidth + HGAP) / 2; b = ADD_OD_BUTTON("Close", kExitCmd); wid.push_back(b); addCancelWidget(b); // Now create all the dialogs attached to each menu button - myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); - myAudioDialog = make_unique(osystem, parent, _font); + myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h); + myEmulationDialog= make_unique(osystem, parent, _font, max_w, max_h); myInputDialog = make_unique(osystem, parent, _font, max_w, max_h); myUIDialog = make_unique(osystem, parent, _font, boss, max_w, max_h); mySnapshotDialog = make_unique(osystem, parent, _font, max_w, max_h); @@ -207,6 +209,10 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, instance().eventHandler().leaveMenuMode(); break; + case kEmuCmd: + myEmulationDialog->open(); + break; + case kVidCmd: { // This dialog is resizable under certain conditions, so we need @@ -215,17 +221,12 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, if(myVideoDialog == nullptr || myVideoDialog->shouldResize(w, h)) { - myVideoDialog = make_unique(instance(), parent(), + myVideoDialog = make_unique(instance(), parent(), instance().frameBuffer().font(), w, h); } myVideoDialog->open(); break; } - - case kAudCmd: - myAudioDialog->open(); - break; - case kInptCmd: { // This dialog is resizable under certain conditions, so we need @@ -243,8 +244,20 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd, } case kUsrIfaceCmd: + { + // This dialog is resizable under certain conditions, so we need + // to re-create it as necessary + uInt32 w = 0, h = 0; + + if(myUIDialog == nullptr || myUIDialog->shouldResize(w, h)) + { + myUIDialog = make_unique(instance(), parent(), + instance().frameBuffer().font(), myBoss, w, h); + } + myUIDialog->open(); break; + } case kSnapCmd: { diff --git a/src/gui/OptionsDialog.hxx b/src/gui/OptionsDialog.hxx index 5842bc482..001fad73b 100644 --- a/src/gui/OptionsDialog.hxx +++ b/src/gui/OptionsDialog.hxx @@ -22,8 +22,8 @@ class CommandSender; class DialogContainer; class GuiObject; class OSystem; -class VideoDialog; -class AudioDialog; +class EmulationDialog; +class VideoAudioDialog; class InputDialog; class UIDialog; class SnapshotDialog; @@ -52,8 +52,8 @@ class OptionsDialog : public Dialog void handleCommand(CommandSender* sender, int cmd, int data, int id) override; private: - unique_ptr myVideoDialog; - unique_ptr myAudioDialog; + unique_ptr myVideoDialog; + unique_ptr myEmulationDialog; unique_ptr myInputDialog; unique_ptr myUIDialog; unique_ptr mySnapshotDialog; @@ -71,13 +71,14 @@ class OptionsDialog : public Dialog ButtonWidget* myGameInfoButton{nullptr}; ButtonWidget* myCheatCodeButton{nullptr}; + GuiObject* myBoss; // Indicates if this dialog is used for global (vs. in-game) settings Menu::AppMode myMode{Menu::AppMode::emulator}; enum { kBasSetCmd = 'BAST', kVidCmd = 'VIDO', - kAudCmd = 'AUDO', + kEmuCmd = 'EMUO', kInptCmd = 'INPT', kUsrIfaceCmd = 'URIF', kSnapCmd = 'SNAP', diff --git a/src/gui/PopUpWidget.cxx b/src/gui/PopUpWidget.cxx index 0c1124066..3f4474fea 100644 --- a/src/gui/PopUpWidget.cxx +++ b/src/gui/PopUpWidget.cxx @@ -41,15 +41,25 @@ PopUpWidget::PopUpWidget(GuiObject* boss, const GUI::Font& font, if(!_label.empty() && _labelWidth == 0) _labelWidth = _font.getStringWidth(_label); - _w = w + _labelWidth + 23; + setArrow(); + + _w = w + _labelWidth + dropDownWidth(font); // 23 // vertically center the arrows and text myTextY = (_h - _font.getFontHeight()) / 2; - myArrowsY = (_h - 8) / 2; + myArrowsY = (_h - _arrowHeight) / 2; myMenu = make_unique(this, font, list, cmd, w); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PopUpWidget::setID(uInt32 id) +{ + myMenu->setID(id); + + Widget::setID(id); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void PopUpWidget::addItems(const VariantList& items) { @@ -177,10 +187,10 @@ void PopUpWidget::handleCommand(CommandSender* sender, int cmd, int data, int id } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PopUpWidget::drawWidget(bool hilite) +void PopUpWidget::setArrow() { - // Little down arrow - static constexpr std::array down_arrow = { + // Small down arrow + static constexpr std::array down_arrow = { 0b100000001, 0b110000011, 0b111000111, @@ -188,9 +198,40 @@ void PopUpWidget::drawWidget(bool hilite) 0b001111100, 0b000111000, 0b000010000, - 0b000000000 + }; + // Large down arrow + static constexpr std::array down_arrow_large = { + 0b1000000000001, + 0b1100000000011, + 0b1110000000111, + 0b1111000001111, + 0b0111100011110, + 0b0011110111100, + 0b0001111111000, + 0b0000111110000, + 0b0000011100000, + 0b0000001000000 }; + if(_font.getFontHeight() < 24) + { + _textOfs = 3; + _arrowWidth = 9; + _arrowHeight = 7; + _arrowImg = down_arrow.data(); + } + else + { + _textOfs = 5; + _arrowWidth = 13; + _arrowHeight = 10; + _arrowImg = down_arrow_large.data(); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void PopUpWidget::drawWidget(bool hilite) +{ //cerr << "PopUpWidget::drawWidget\n"; FBSurface& s = dialog().surface(); bool onTop = _boss->dialog().isOnTop(); @@ -205,19 +246,23 @@ void PopUpWidget::drawWidget(bool hilite) // Draw a thin frame around us. s.frameRect(x, _y, w, _h, isEnabled() && hilite ? kWidColorHi : kColor); - s.frameRect(x + w - 16, _y + 1, 15, _h - 2, isEnabled() && hilite ? kWidColorHi : kBGColorLo); + s.frameRect(x + w - (_arrowWidth * 2 - 2), _y + 1, (_arrowWidth * 2 - 3), _h - 2, + isEnabled() && hilite ? kWidColorHi : kBGColorLo); // Fill the background - s.fillRect(x + 1, _y + 1, w - 17, _h - 2, onTop ? _changed ? kDbgChangedColor : isEnabled() ? kWidColor : kDlgColor : kBGColorLo); - s.fillRect(x + w - 15, _y + 2, 13, _h - 4, onTop ? isEnabled() && hilite ? kWidColor : kDlgColor : kBGColorLo); + s.fillRect(x + 1, _y + 1, w - (_arrowWidth * 2 - 1), _h - 2, + onTop ? _changed ? kDbgChangedColor : kWidColor : kDlgColor); + s.fillRect(x + w - (_arrowWidth * 2 - 3), _y + 2, (_arrowWidth * 2 - 5), _h - 4, + onTop ? isEnabled() && hilite ? kWidColor : kBGColorHi : kBGColorLo); // Draw an arrow pointing down at the right end to signal this is a dropdown/popup - s.drawBitmap(down_arrow.data(), x + w - 13, _y + myArrowsY + 1, - !(isEnabled() && onTop) ? kColor : kTextColor, 9U, 8U); + s.drawBitmap(_arrowImg, x + w - (_arrowWidth * 1.5 - 1), _y + myArrowsY + 1, + !(isEnabled() && onTop) ? kColor : kTextColor, _arrowWidth, _arrowHeight); // Draw the selected entry, if any const string& name = myMenu->getSelectedName(); - TextAlign align = (_font.getStringWidth(name) > w-6) ? + w -= dropDownWidth(_font); + TextAlign align = (_font.getStringWidth(name) > w) ? TextAlign::Right : TextAlign::Left; - s.drawString(_font, name, x+2, _y+myTextY, w-6, - !(isEnabled() && onTop) ? kColor : kTextColor, align); + s.drawString(_font, name, x + _textOfs, _y + myTextY, w, + !(isEnabled() && onTop) ? kColor : _changed ? kDbgChangedTextColor : kTextColor, align); } diff --git a/src/gui/PopUpWidget.hxx b/src/gui/PopUpWidget.hxx index f79e575f8..c9817e6dd 100644 --- a/src/gui/PopUpWidget.hxx +++ b/src/gui/PopUpWidget.hxx @@ -41,6 +41,8 @@ class PopUpWidget : public Widget, public CommandSender const string& label, int labelWidth = 0, int cmd = 0); virtual ~PopUpWidget() = default; + void setID(uInt32 id); + int getTop() const override { return _y + 1; } int getBottom() const override { return _y + 1 + getHeight(); } @@ -60,6 +62,10 @@ class PopUpWidget : public Widget, public CommandSender const Variant& getSelectedTag() const; bool wantsFocus() const override { return true; } + static int dropDownWidth(const GUI::Font& font) + { + return font.getFontHeight() < 24 ? (9 * 2 + 3) : (13 * 2 + 7); + } protected: void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; @@ -68,6 +74,8 @@ class PopUpWidget : public Widget, public CommandSender void handleMouseLeft() override; bool handleEvent(Event::Type e) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + + void setArrow(); void drawWidget(bool hilite) override; private: @@ -79,6 +87,11 @@ class PopUpWidget : public Widget, public CommandSender int _labelWidth{0}; bool _changed{false}; + int _textOfs{0}; + int _arrowWidth{0}; + int _arrowHeight{0}; + const uInt32* _arrowImg{nullptr}; + private: // Following constructors and assignment operators not supported PopUpWidget() = delete; diff --git a/src/gui/ProgressDialog.cxx b/src/gui/ProgressDialog.cxx index 5ff6f7698..04bc2adae 100644 --- a/src/gui/ProgressDialog.cxx +++ b/src/gui/ProgressDialog.cxx @@ -31,20 +31,23 @@ ProgressDialog::ProgressDialog(GuiObject* boss, const GUI::Font& font, { const int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - lineHeight = font.getLineHeight(); + lineHeight = font.getLineHeight(), + VBORDER = fontHeight / 2, + HBORDER = fontWidth * 1.25, + VGAP = fontHeight / 4; int xpos, ypos, lwidth; // Calculate real dimensions lwidth = font.getStringWidth(message); - _w = lwidth + 2 * fontWidth; - _h = lineHeight * 5; + _w = HBORDER * 2 + lwidth; + _h = VBORDER * 2 + lineHeight * 2 + VGAP * 2; - xpos = fontWidth; ypos = lineHeight; + xpos = HBORDER; ypos = VBORDER; myMessage = new StaticTextWidget(this, font, xpos, ypos, lwidth, fontHeight, message, TextAlign::Center); myMessage->setTextColor(kTextColorEm); - xpos = fontWidth; ypos += 2 * lineHeight; + xpos = HBORDER; ypos += lineHeight + VGAP * 2; mySlider = new SliderWidget(this, font, xpos, ypos, lwidth, lineHeight, "", 0, 0); mySlider->setMinValue(1); mySlider->setMaxValue(100); diff --git a/src/gui/R77HelpDialog.cxx b/src/gui/R77HelpDialog.cxx index 617f783be..1e4601ced 100644 --- a/src/gui/R77HelpDialog.cxx +++ b/src/gui/R77HelpDialog.cxx @@ -38,7 +38,7 @@ R77HelpDialog::R77HelpDialog(OSystem& osystem, DialogContainer& parent, // Set real dimensions _w = 47 * fontWidth + HBORDER * 2; - _h = (LINES_PER_PAGE + 2) * lineHeight + 20 + _th; + _h = (LINES_PER_PAGE + 2) * lineHeight + 12 + _th; // Add Previous, Next and Close buttons xpos = HBORDER; ypos = _h - buttonHeight - 10; @@ -130,6 +130,7 @@ void R77HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) ADD_BIND("Right", "MODE", "Page down"); ADD_BIND("Button 1", "SKILL P1", "Start selected game"); ADD_BIND("\\c2Button 2", "SKILL P2", "Open power-on options"); + ADD_BIND(" or hold Bu", "tton 1", ""); ADD_BIND("\\c2Button 4", "Color,B/W", "Open settings"); break; @@ -144,7 +145,9 @@ void R77HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title) ADD_BIND("Button 1", "SKILL P1", "Select element"); ADD_BIND("\\c2Button 2", "SKILL P2", "OK"); ADD_BIND("\\c2Button 3", "4:3,16:9", "Previous tab"); + ADD_BIND(" or Button ", "1+Left", ""); ADD_BIND("\\c2Button 4", "FRY", "Next tab"); + ADD_BIND(" or Button ", "1+Right", ""); ADD_BIND("\\c2Button 6", "\\c2-", "Cancel"); break; diff --git a/src/gui/R77HelpDialog.hxx b/src/gui/R77HelpDialog.hxx index a7b8e7fa2..731de5e65 100644 --- a/src/gui/R77HelpDialog.hxx +++ b/src/gui/R77HelpDialog.hxx @@ -41,7 +41,7 @@ class R77HelpDialog : public Dialog void loadConfig() override; private: - static constexpr uInt32 LINES_PER_PAGE = 11; + static constexpr uInt32 LINES_PER_PAGE = 13; ButtonWidget* myNextButton{nullptr}; ButtonWidget* myPrevButton{nullptr}; diff --git a/src/gui/RadioButtonWidget.cxx b/src/gui/RadioButtonWidget.cxx index 7480122a2..e2b5e34df 100644 --- a/src/gui/RadioButtonWidget.cxx +++ b/src/gui/RadioButtonWidget.cxx @@ -21,6 +21,7 @@ #include "RadioButtonWidget.hxx" /* Radiobutton bitmaps */ +// small versions static constexpr std::array radio_img_outercircle = { 0b00001111110000, 0b00110000001100, 0b01000000000010, 0b01000000000010, 0b10000000000001, 0b10000000000001, @@ -33,16 +34,188 @@ static constexpr std::array radio_img_innercircle = { 0b111111111111, 0b111111111111, 0b111111111111, 0b111111111111, 0b111111111111, 0b011111111110, 0b011111111110, 0b000111111000 }; -static constexpr uInt32 RADIO_IMG_FILL_SIZE = 10; -static constexpr std::array radio_img_active = { +static constexpr std::array radio_img_active = { 0b0011111100, 0b0111111110, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b0111111110, 0b0011111100, }; -static constexpr std::array radio_img_inactive = { +static constexpr std::array radio_img_inactive = { 0b0011111100, 0b0111111110, 0b1111001111, 0b1110000111, 0b1100000011, 0b1100000011, 0b1110000111, 0b1111001111, 0b0111111110, 0b0011111100 }; +// large versions +static constexpr std::array radio_img_outercircle_large = { + // thinner version + //0b0000000011111100000000, + //0b0000001100000011000000, + //0b0000110000000000110000, + //0b0001000000000000001000, + //0b0010000000000000000100, + //0b0010000000000000000100, + //0b0100000000000000000010, + //0b0100000000000000000010, + //0b1000000000000000000001, + //0b1000000000000000000001, + //0b1000000000000000000001, + //0b1000000000000000000001, + //0b1000000000000000000001, + //0b1000000000000000000001, + //0b0100000000000000000010, + //0b0100000000000000000010, + //0b0010000000000000000100, + //0b0010000000000000000100, + //0b0001000000000000001000, + //0b0000110000000000110000, + //0b0000001100000011000000, + //0b0000000011111100000000 + + 0b0000000011111100000000, + 0b0000001110000111000000, + 0b0000111000000001110000, + 0b0001100000000000011000, + 0b0011000000000000001100, + 0b0010000000000000000100, + 0b0110000000000000000110, + 0b0100000000000000000010, + 0b1100000000000000000011, + 0b1000000000000000000001, + 0b1000000000000000000001, + 0b1000000000000000000001, + 0b1000000000000000000001, + 0b1100000000000000000011, + 0b0100000000000000000010, + 0b0110000000000000000110, + 0b0010000000000000000100, + 0b0011000000000000001100, + 0b0001100000000000011000, + 0b0000111000000001110000, + 0b0000001110000111000000, + 0b0000000011111100000000 + +}; +static constexpr std::array radio_img_innercircle_large = { + //0b00000001111110000000, + //0b00000111111111100000, + //0b00011111111111111000, + //0b00111111111111111100, + //0b00111111111111111100, + //0b01111111111111111110, + //0b01111111111111111110, + //0b11111111111111111111, + //0b11111111111111111111, + //0b11111111111111111111, + //0b11111111111111111111, + //0b11111111111111111111, + //0b11111111111111111111, + //0b01111111111111111110, + //0b01111111111111111110, + //0b00111111111111111100, + //0b00111111111111111100, + //0b00011111111111111000, + //0b00000111111111100000, + //0b00000001111110000000 + + 0b00000000111100000000, + 0b00000011111111000000, + 0b00001111111111110000, + 0b00011111111111111000, + 0b00111111111111111100, + 0b00111111111111111100, + 0b01111111111111111110, + 0b01111111111111111110, + 0b11111111111111111111, + 0b11111111111111111111, + 0b11111111111111111111, + 0b11111111111111111111, + 0b01111111111111111110, + 0b01111111111111111110, + 0b00111111111111111100, + 0b00111111111111111100, + 0b00011111111111111000, + 0b00001111111111110000, + 0b00000011111111000000, + 0b00000000111100000000 + +}; +static constexpr std::array radio_img_active_large = { + //0b000000111111000000, + //0b000011111111110000, + //0b000111111111111000, + //0b001111111111111100, + //0b011111111111111110, + //0b011111111111111110, + //0b111111111111111111, + //0b111111111111111111, + //0b111111111111111111, + //0b111111111111111111, + //0b111111111111111111, + //0b111111111111111111, + //0b011111111111111110, + //0b011111111111111110, + //0b001111111111111100, + //0b000111111111111000, + //0b000011111111110000, + //0b000000111111000000 + + 0b000000000000000000, + 0b000000111111000000, + 0b000011111111110000, + 0b000111111111111000, + 0b001111111111111100, + 0b001111111111111100, + 0b011111111111111110, + 0b011111111111111110, + 0b011111111111111110, + 0b011111111111111110, + 0b011111111111111110, + 0b011111111111111110, + 0b001111111111111100, + 0b001111111111111100, + 0b000111111111111000, + 0b000011111111110000, + 0b000000111111000000, + 0b000000000000000000 +}; +static constexpr std::array radio_img_inactive_large = { + //0b000001111111100000, + //0b000111111111111000, + //0b001111111111111100, + //0b011111100001111110, + //0b011110000000011110, + //0b111100000000001111, + //0b111100000000001111, + //0b111000000000000111, + //0b111000000000000111, + //0b111000000000000111, + //0b111000000000000111, + //0b111100000000001111, + //0b111100000000001111, + //0b011110000000011110, + //0b011111100001111110, + //0b001111111111111100, + //0b010111111111111000, + //0b000001111111100000 + + 0b000000000000000000, + 0b000000111111000000, + 0b000011111111110000, + 0b000111111111111000, + 0b001111100001111100, + 0b001111000000111100, + 0b011110000000011110, + 0b011100000000001110, + 0b011100000000001110, + 0b011100000000001110, + 0b011100000000001110, + 0b011110000000011110, + 0b001111000000111100, + 0b001111100001111100, + 0b000111111111111000, + 0b000011111111110000, + 0b000000111111000000, + 0b000000000000000000 +}; + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font, int x, int y, const string& label, @@ -54,19 +227,31 @@ RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font, _bgcolor = _bgcolorhi = kWidColor; _editable = true; + _buttonSize = buttonSize(font); // 14 | 22 + + if(_buttonSize == 14) + { + _outerCircle = radio_img_outercircle.data(); + _innerCircle = radio_img_innercircle.data(); + } + else + { + _outerCircle = radio_img_outercircle_large.data(); + _innerCircle = radio_img_innercircle_large.data(); + } if(label == "") - _w = 14; + _w = _buttonSize; else - _w = font.getStringWidth(label) + 20; - _h = font.getFontHeight() < 14 ? 14 : font.getFontHeight(); + _w = font.getStringWidth(label) + _buttonSize + font.getMaxCharWidth() * 0.75; + _h = font.getFontHeight() < int(_buttonSize) ? _buttonSize : font.getFontHeight(); // Depending on font size, either the font or box will need to be // centered vertically - if(_h > 14) // center box - _boxY = (_h - 14) / 2; + if(_h > int(_buttonSize)) // center box + _boxY = (_h - _buttonSize) / 2; else // center text - _textY = (14 - _font.getFontHeight()) / 2; + _textY = (_buttonSize - _font.getFontHeight()) / 2; setFill(CheckboxWidget::FillType::Normal); myGroup->addWidget(this); @@ -102,10 +287,10 @@ void RadioButtonWidget::setFill(FillType type) switch(type) { case CheckboxWidget::FillType::Normal: - _img = radio_img_active.data(); + _img = _buttonSize == 14 ? radio_img_active.data() : radio_img_active_large.data(); break; case CheckboxWidget::FillType::Inactive: - _img = radio_img_inactive.data(); + _img = _buttonSize == 14 ? radio_img_inactive.data(): radio_img_inactive_large.data(); break; default: break; @@ -118,25 +303,23 @@ void RadioButtonWidget::drawWidget(bool hilite) FBSurface& s = _boss->dialog().surface(); // Draw the outer bounding circle - s.drawBitmap(radio_img_outercircle.data(), _x, _y + _boxY, + s.drawBitmap(_outerCircle, _x, _y + _boxY, hilite ? kWidColorHi : kColor, - static_cast(radio_img_outercircle.size()), - static_cast(radio_img_outercircle.size())); + _buttonSize); // Draw the inner bounding circle with enabled color - s.drawBitmap(radio_img_innercircle.data(), _x + 1, _y + _boxY + 1, + s.drawBitmap(_innerCircle, _x + 1, _y + _boxY + 1, isEnabled() ? _bgcolor : kColor, - static_cast(radio_img_innercircle.size()), - static_cast(radio_img_innercircle.size())); + _buttonSize - 2); // draw state if(_state) s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled() ? hilite ? kWidColorHi : kCheckColor - : kColor, RADIO_IMG_FILL_SIZE); + : kColor, _buttonSize - 4); // Finally draw the label - s.drawString(_font, _label, _x + 20, _y + _textY, _w, + s.drawString(_font, _label, _x + _buttonSize + _font.getMaxCharWidth() * 0.75, _y + _textY, _w, isEnabled() ? kTextColor : kColor); } diff --git a/src/gui/RadioButtonWidget.hxx b/src/gui/RadioButtonWidget.hxx index 840cc2dd2..8003a8627 100644 --- a/src/gui/RadioButtonWidget.hxx +++ b/src/gui/RadioButtonWidget.hxx @@ -40,9 +40,14 @@ class RadioButtonWidget : public CheckboxWidget protected: void setFill(FillType type); void drawWidget(bool hilite) override; + static int buttonSize(const GUI::Font& font) + { + return font.getFontHeight() < 24 ? 14 : 22; // box is square + } private: RadioButtonGroup* myGroup{nullptr}; + uInt32 _buttonSize{14}; private: // Following constructors and assignment operators not supported diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index 25cf78220..58b9acaba 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -25,6 +25,7 @@ #include "FSNode.hxx" #include "Font.hxx" #include "MessageBox.hxx" +#include "OSystem.hxx" #include "FrameBuffer.hxx" #include "MD5.hxx" #include "Props.hxx" @@ -40,15 +41,15 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, myMaxWidth(max_w), myMaxHeight(max_h) { - const int VBORDER = 10 + _th; - const int HBORDER = 10; - const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + 20, - buttonHeight = font.getLineHeight() + 4, + buttonWidth = font.getStringWidth("Audit path" + ELLIPSIS) + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25, lwidth = font.getStringWidth("ROMs without properties (skipped) "); + const int VBORDER = _th + fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos = VBORDER; WidgetArray wid; @@ -62,28 +63,24 @@ RomAuditDialog::RomAuditDialog(OSystem& osystem, DialogContainer& parent, "Audit path" + ELLIPSIS, kChooseAuditDirCmd); wid.push_back(romButton); xpos = HBORDER + buttonWidth + 8; - myRomPath = new EditTextWidget(this, font, xpos, ypos + 1, + myRomPath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1, _w - xpos - HBORDER, lineHeight, ""); wid.push_back(myRomPath); // Show results of ROM audit ypos += buttonHeight + 16; - new StaticTextWidget(this, font, HBORDER, ypos, lwidth, fontHeight, - "ROMs with properties (renamed) ", TextAlign::Left); + new StaticTextWidget(this, font, HBORDER, ypos, "ROMs with properties (renamed) "); myResults1 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2, fontWidth * 6, lineHeight, ""); myResults1->setEditable(false, true); ypos += buttonHeight; - new StaticTextWidget(this, font, HBORDER, ypos, lwidth, fontHeight, - "ROMs without properties (skipped) ", TextAlign::Left); + new StaticTextWidget(this, font, HBORDER, ypos, "ROMs without properties (skipped) "); myResults2 = new EditTextWidget(this, font, HBORDER + lwidth, ypos - 2, fontWidth * 6, lineHeight, ""); myResults2->setEditable(false, true); ypos += buttonHeight + 8; - new StaticTextWidget(this, font, HBORDER, ypos, _w - 20, fontHeight, - "(*) WARNING: Operation cannot be undone!", - TextAlign::Left); + new StaticTextWidget(this, font, HBORDER, ypos, "(*) WARNING: Operation cannot be undone!"); // Add OK and Cancel buttons addOKCancelBGroup(wid, font, "Audit", "Close"); @@ -99,7 +96,7 @@ RomAuditDialog::~RomAuditDialog() void RomAuditDialog::loadConfig() { const string& currentdir = - instance().launcher().currentNode().getShortPath(); + instance().launcher().currentDir().getShortPath(); const string& path = currentdir == "" ? instance().settings().getString("romdir") : currentdir; diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index a5278876f..7e29d19e4 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -27,18 +27,17 @@ #include "Logger.hxx" #include "Props.hxx" #include "PNGLibrary.hxx" +#include "PropsSet.hxx" #include "Rect.hxx" #include "Widget.hxx" -#include "TIAConstants.hxx" #include "RomInfoWidget.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, - int x, int y, int w, int h) + int x, int y, int w, int h, + const Common::Size& imgSize) : Widget(boss, font, x, y, w, h), - myAvail(w > 400 ? - Common::Size(TIAConstants::viewableWidth*2, TIAConstants::viewableHeight*2) : - Common::Size(TIAConstants::viewableWidth, TIAConstants::viewableHeight)) + myAvail(imgSize) { _flags = Widget::FLAG_ENABLED; _bgcolor = kDlgColor; @@ -46,20 +45,15 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font, } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomInfoWidget::reloadProperties(const FilesystemNode& node) -{ - // The ROM may have changed since we were last in the browser, either - // by saving a different image or through a change in video renderer, - // so we reload the properties - if(myHaveProperties) - parseProperties(node); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void RomInfoWidget::setProperties(const Properties& props, const FilesystemNode& node) +void RomInfoWidget::setProperties(const FilesystemNode& node, const string& md5) { myHaveProperties = true; - myProperties = props; + + // Make sure to load a per-ROM properties entry, if one exists + instance().propSet().loadPerROM(node, md5); + + // And now get the properties for this ROM + instance().propSet().getMD5(md5, myProperties); // Decide whether the information should be shown immediately if(instance().eventHandler().state() == EventHandlerState::LAUNCHER) @@ -78,6 +72,16 @@ void RomInfoWidget::clearProperties() setDirty(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void RomInfoWidget::reloadProperties(const FilesystemNode& node) +{ + // The ROM may have changed since we were last in the browser, either + // by saving a different image or through a change in video renderer, + // so we reload the properties + if(myHaveProperties) + parseProperties(node); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void RomInfoWidget::parseProperties(const FilesystemNode& node) { @@ -87,7 +91,7 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node) if(mySurface == nullptr) { mySurface = instance().frameBuffer().allocateSurface( - TIAConstants::viewableWidth*2, TIAConstants::viewableHeight*2, FrameBuffer::ScalingInterpolation::blur); + myAvail.w, myAvail.h, FrameBuffer::ScalingInterpolation::blur); mySurface->applyAttributes(); dialog().addSurface(mySurface); @@ -100,7 +104,7 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node) #ifdef PNG_SUPPORT // Get a valid filename representing a snapshot file for this rom - const string& filename = instance().snapshotLoadDir() + + const string& filename = instance().snapshotLoadDir().getPath() + myProperties.get(PropType::Cart_Name) + ".png"; // Read the PNG file @@ -142,17 +146,16 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node) try { ByteBuffer image; - string md5 = myProperties.get(PropType::Cart_MD5); - size_t size = 0; + string md5 = ""; size_t size = 0; if(node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr) { Logger::debug(myProperties.get(PropType::Cart_Name) + ":"); - left = ControllerDetector::detectName(image.get(), size, leftType, + left = ControllerDetector::detectName(image, size, leftType, !swappedPorts ? Controller::Jack::Left : Controller::Jack::Right, instance().settings()); - right = ControllerDetector::detectName(image.get(), size, rightType, + right = ControllerDetector::detectName(image, size, rightType, !swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, instance().settings()); if (bsDetected == "AUTO") @@ -199,15 +202,27 @@ void RomInfoWidget::drawWidget(bool hilite) } else if(mySurfaceErrorMsg != "") { - const GUI::Font& font = instance().frameBuffer().font(); - uInt32 x = _x + ((_w - font.getStringWidth(mySurfaceErrorMsg)) >> 1); - uInt32 y = _y + ((yoff - font.getLineHeight()) >> 1); - s.drawString(font, mySurfaceErrorMsg, x, y, _w - 10, onTop ? _textcolor : _shadowcolor); + uInt32 x = _x + ((_w - _font.getStringWidth(mySurfaceErrorMsg)) >> 1); + uInt32 y = _y + ((yoff - _font.getLineHeight()) >> 1); + s.drawString(_font, mySurfaceErrorMsg, x, y, _w - 10, onTop ? _textcolor : _shadowcolor); } - int xpos = _x + 8, ypos = _y + yoff + 10; - for(const auto& info: myRomInfo) + int xpos = _x + 8, ypos = _y + yoff + 5; + for(const auto& info : myRomInfo) { + if(info.length() * _font.getMaxCharWidth() <= uInt64(_w - 16)) + + { + // 1 line for next entry + if(ypos + _font.getFontHeight() > _h + _y) + break; + } + else + { + // assume 2 lines for next entry + if(ypos + _font.getLineHeight() + _font.getFontHeight() > _h + _y ) + break; + } int lines = s.drawString(_font, info, xpos, ypos, _w - 16, _font.getFontHeight() * 3, onTop ? _textcolor : _shadowcolor); ypos += _font.getLineHeight() + (lines - 1) * _font.getFontHeight(); diff --git a/src/gui/RomInfoWidget.hxx b/src/gui/RomInfoWidget.hxx index 9ae045ac6..e2ea566ca 100644 --- a/src/gui/RomInfoWidget.hxx +++ b/src/gui/RomInfoWidget.hxx @@ -31,10 +31,11 @@ class RomInfoWidget : public Widget { public: RomInfoWidget(GuiObject *boss, const GUI::Font& font, - int x, int y, int w, int h); + int x, int y, int w, int h, + const Common::Size& imgSize); virtual ~RomInfoWidget() = default; - void setProperties(const Properties& props, const FilesystemNode& node); + void setProperties(const FilesystemNode& node, const string& md5); void clearProperties(); void reloadProperties(const FilesystemNode& node); diff --git a/src/gui/ScrollBarWidget.cxx b/src/gui/ScrollBarWidget.cxx index 4d055a027..335b716de 100644 --- a/src/gui/ScrollBarWidget.cxx +++ b/src/gui/ScrollBarWidget.cxx @@ -28,8 +28,6 @@ * and we thus should not highlight the arrows/slider. */ -#define UP_DOWN_BOX_HEIGHT 18 - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h) @@ -38,6 +36,76 @@ ScrollBarWidget::ScrollBarWidget(GuiObject* boss, const GUI::Font& font, _flags = Widget::FLAG_ENABLED | Widget::FLAG_TRACK_MOUSE | Widget::FLAG_CLEARBG; _bgcolor = kWidColor; _bgcolorhi = kWidColor; + + _scrollBarWidth = scrollBarWidth(font); + + setArrows(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void ScrollBarWidget::setArrows() +{ + // Small up arrow + static constexpr std::array up_arrow = { + 0b0001000, + 0b0011100, + 0b0111110, + 0b1110111, + 0b1100011, + 0b1000001, + }; + // Small down arrow + static constexpr std::array down_arrow = { + 0b1000001, + 0b1100011, + 0b1110111, + 0b0111110, + 0b0011100, + 0b0001000 + }; + + // Large up arrow + static constexpr std::array up_arrow_large = { + 0b00000100000, + 0b00001110000, + 0b00011111000, + 0b00111111100, + 0b01111011110, + 0b11110001111, + 0b11100000111, + 0b11000000011, + 0b10000000001, + }; + // Large down arrow + static constexpr std::array down_arrow_large = { + 0b10000000001, + 0b11000000011, + 0b11100000111, + 0b11110001111, + 0b01111011110, + 0b00111111100, + 0b00011111000, + 0b00001110000, + 0b00000100000 + }; + + + if(_font.getFontHeight() < 24) + { + _upDownWidth = 7; + _upDownHeight = 6; + _upDownBoxHeight = 18; + _upImg = up_arrow.data(); + _downImg = down_arrow.data(); + } + else + { + _upDownWidth = 11; + _upDownHeight = 9; + _upDownBoxHeight = 27; + _upImg = up_arrow_large.data(); + _downImg = down_arrow_large.data(); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -54,13 +122,13 @@ void ScrollBarWidget::handleMouseDown(int x, int y, MouseButton b, if(_numEntries <= _entriesPerPage) return; - if (y <= UP_DOWN_BOX_HEIGHT) + if (y <= _upDownBoxHeight) { // Up arrow _currentPos--; _draggingPart = Part::UpArrow; } - else if(y >= _h - UP_DOWN_BOX_HEIGHT) + else if(y >= _h - _upDownBoxHeight) { // Down arrow _currentPos++; @@ -120,23 +188,23 @@ void ScrollBarWidget::handleMouseMoved(int x, int y) int old_pos = _currentPos; _sliderPos = y - _sliderDeltaMouseDownPos; - if(_sliderPos < UP_DOWN_BOX_HEIGHT) - _sliderPos = UP_DOWN_BOX_HEIGHT; + if(_sliderPos < _upDownBoxHeight) + _sliderPos = _upDownBoxHeight; - if(_sliderPos > _h - UP_DOWN_BOX_HEIGHT - _sliderHeight) - _sliderPos = _h - UP_DOWN_BOX_HEIGHT - _sliderHeight; + if(_sliderPos > _h - _upDownBoxHeight - _sliderHeight) + _sliderPos = _h - _upDownBoxHeight - _sliderHeight; - _currentPos = (_sliderPos - UP_DOWN_BOX_HEIGHT) * (_numEntries - _entriesPerPage) / - (_h - 2 * UP_DOWN_BOX_HEIGHT - _sliderHeight); + _currentPos = (_sliderPos - _upDownBoxHeight) * (_numEntries - _entriesPerPage) / + (_h - 2 * _upDownBoxHeight - _sliderHeight); checkBounds(old_pos); } else { Part old_part = _part; - if(y <= UP_DOWN_BOX_HEIGHT) // Up arrow + if(y <= _upDownBoxHeight) // Up arrow _part = Part::UpArrow; - else if(y >= _h - UP_DOWN_BOX_HEIGHT) // Down arrow + else if(y >= _h - _upDownBoxHeight) // Down arrow _part = Part::DownArrow; else if(y < _sliderPos) _part = Part::PageUp; @@ -193,19 +261,19 @@ void ScrollBarWidget::recalc() //cerr << "ScrollBarWidget::recalc()\n"; if(_numEntries > _entriesPerPage) { - _sliderHeight = (_h - 2 * UP_DOWN_BOX_HEIGHT) * _entriesPerPage / _numEntries; - if(_sliderHeight < UP_DOWN_BOX_HEIGHT) - _sliderHeight = UP_DOWN_BOX_HEIGHT; + _sliderHeight = (_h - 2 * _upDownBoxHeight) * _entriesPerPage / _numEntries; + if(_sliderHeight < _upDownBoxHeight) + _sliderHeight = _upDownBoxHeight; - _sliderPos = UP_DOWN_BOX_HEIGHT + (_h - 2 * UP_DOWN_BOX_HEIGHT - _sliderHeight) * + _sliderPos = _upDownBoxHeight + (_h - 2 * _upDownBoxHeight - _sliderHeight) * _currentPos / (_numEntries - _entriesPerPage); if(_sliderPos < 0) _sliderPos = 0; } else { - _sliderHeight = _h - 2 * UP_DOWN_BOX_HEIGHT; - _sliderPos = UP_DOWN_BOX_HEIGHT; + _sliderHeight = _h - 2 * _upDownBoxHeight; + _sliderPos = _upDownBoxHeight; } setDirty(); @@ -214,30 +282,6 @@ void ScrollBarWidget::recalc() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void ScrollBarWidget::drawWidget(bool hilite) { - // Up arrow - static constexpr std::array up_arrow = { - 0b00000000, - 0b00010000, - 0b00111000, - 0b01111100, - 0b11101110, - 0b11000110, - 0b10000010, - 0b00000000 - }; - - // Down arrow - static constexpr std::array down_arrow = { - 0b00000000, - 0b10000010, - 0b11000110, - 0b11101110, - 0b01111100, - 0b00111000, - 0b00010000, - 0b00000000 - }; - //cerr << "ScrollBarWidget::drawWidget\n"; FBSurface& s = _boss->dialog().surface(); bool onTop = _boss->dialog().isOnTop(); @@ -251,17 +295,19 @@ void ScrollBarWidget::drawWidget(bool hilite) // Up arrow if(hilite && _part == Part::UpArrow) - s.fillRect(_x + 1, _y + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor); - s.drawBitmap(up_arrow.data(), _x+4, _y+5, + s.fillRect(_x + 1, _y + 1, _w - 2, _upDownBoxHeight - 2, kScrollColor); + s.drawBitmap(_upImg, _x + (_scrollBarWidth - _upDownWidth) / 2, + _y + (_upDownBoxHeight - _upDownHeight) / 2, onTop ? isSinglePage ? kColor : (hilite && _part == Part::UpArrow) ? kWidColor - : kTextColor : kColor, 8); + : kTextColor : kColor, _upDownWidth, _upDownHeight); // Down arrow if(hilite && _part == Part::DownArrow) - s.fillRect(_x + 1, bottomY - UP_DOWN_BOX_HEIGHT + 1, _w - 2, UP_DOWN_BOX_HEIGHT - 2, kScrollColor); - s.drawBitmap(down_arrow.data(), _x+4, bottomY - UP_DOWN_BOX_HEIGHT + 5, + s.fillRect(_x + 1, bottomY - _upDownBoxHeight + 1, _w - 2, _upDownBoxHeight - 2, kScrollColor); + s.drawBitmap(_downImg, _x + (_scrollBarWidth - _upDownWidth) / 2, + bottomY - _upDownBoxHeight + (_upDownBoxHeight - _upDownHeight) / 2, onTop ? isSinglePage ? kColor : (hilite && _part == Part::DownArrow) ? - kWidColor : kTextColor : kColor, 8); + kWidColor : kTextColor : kColor, _upDownWidth, _upDownHeight); // Slider if(!isSinglePage) @@ -273,3 +319,4 @@ void ScrollBarWidget::drawWidget(bool hilite) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int ScrollBarWidget::_WHEEL_LINES = 4; + diff --git a/src/gui/ScrollBarWidget.hxx b/src/gui/ScrollBarWidget.hxx index bbe227559..7752e8ab7 100644 --- a/src/gui/ScrollBarWidget.hxx +++ b/src/gui/ScrollBarWidget.hxx @@ -24,10 +24,6 @@ class GuiObject; #include "Command.hxx" #include "bspf.hxx" -enum { - kScrollBarWidth = 15 -}; - class ScrollBarWidget : public Widget, public CommandSender { public: @@ -40,6 +36,10 @@ class ScrollBarWidget : public Widget, public CommandSender static void setWheelLines(int lines) { _WHEEL_LINES = lines; } static int getWheelLines() { return _WHEEL_LINES; } + static int scrollBarWidth(const GUI::Font& font) + { + return font.getFontHeight() < 24 ? 15 : 23; + } private: void drawWidget(bool hilite) override; @@ -51,6 +51,7 @@ class ScrollBarWidget : public Widget, public CommandSender bool handleMouseClicks(int x, int y, MouseButton b) override; void handleMouseEntered() override; void handleMouseLeft() override; + void setArrows(); public: int _numEntries{0}; @@ -66,6 +67,12 @@ class ScrollBarWidget : public Widget, public CommandSender int _sliderHeight{0}; int _sliderPos{0}; int _sliderDeltaMouseDownPos{0}; + int _upDownWidth{0}; + int _upDownHeight{0}; + int _upDownBoxHeight{0}; + int _scrollBarWidth{0}; + const uInt32* _upImg{nullptr}; + const uInt32* _downImg{nullptr}; static int _WHEEL_LINES; diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx index c1f94d52f..792d7af7f 100644 --- a/src/gui/SnapshotDialog.cxx +++ b/src/gui/SnapshotDialog.cxx @@ -21,6 +21,7 @@ #include "FSNode.hxx" #include "Font.hxx" #include "LauncherDialog.hxx" +#include "OSystem.hxx" #include "Settings.hxx" #include "SnapshotDialog.hxx" @@ -30,20 +31,22 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, : Dialog(osystem, parent, font, "Snapshot settings"), myFont(font) { - const int VBORDER = 10; - const int HBORDER = 10; - const int INDENT = 16; - const int V_GAP = 4; const int lineHeight = font.getLineHeight(), + fontHeight = _font.getFontHeight(), fontWidth = font.getMaxCharWidth(), - buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + 20, - buttonHeight = font.getLineHeight() + 4; + buttonWidth = font.getStringWidth("Save path" + ELLIPSIS) + fontWidth * 2.5, + buttonHeight = font.getLineHeight() * 1.25; + const int HBORDER = fontWidth * 1.25; + const int VBORDER = fontHeight / 4; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + int xpos, ypos, fwidth; WidgetArray wid; ButtonWidget* b; // Set real dimensions - setSize(64 * fontWidth + HBORDER * 2, 9 * (lineHeight + 4) + VBORDER + _th, max_w, max_h); + setSize(64 * fontWidth + HBORDER * 2, 9 * (lineHeight + VGAP) + VBORDER + _th, max_w, max_h); xpos = HBORDER; ypos = VBORDER + _th; @@ -51,13 +54,13 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, b = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, "Save path" + ELLIPSIS, kChooseSnapSaveDirCmd); wid.push_back(b); - xpos += buttonWidth + 8; - mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + 1, + xpos += buttonWidth + fontWidth; + mySnapSavePath = new EditTextWidget(this, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1, _w - xpos - HBORDER, lineHeight, ""); wid.push_back(mySnapSavePath); // Snapshot naming - xpos = HBORDER; ypos += buttonHeight + V_GAP * 4; + xpos = HBORDER; ypos += buttonHeight + VGAP * 4; // Snapshot interval (continuous mode) mySnapInterval = new SliderWidget(this, font, xpos, ypos, @@ -70,23 +73,23 @@ SnapshotDialog::SnapshotDialog(OSystem& osystem, DialogContainer& parent, // Booleans for saving snapshots fwidth = font.getStringWidth("When saving snapshots:"); - xpos = HBORDER; ypos += lineHeight + V_GAP * 3; + xpos = HBORDER; ypos += lineHeight + VGAP * 3; new StaticTextWidget(this, font, xpos, ypos, fwidth, lineHeight, "When saving snapshots:", TextAlign::Left); // Snapshot single or multiple saves - xpos += INDENT; ypos += lineHeight + V_GAP; + xpos += INDENT; ypos += lineHeight + VGAP; mySnapName = new CheckboxWidget(this, font, xpos, ypos, "Use actual ROM name"); wid.push_back(mySnapName); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; mySnapSingle = new CheckboxWidget(this, font, xpos, ypos, "Overwrite existing files"); wid.push_back(mySnapSingle); // Snapshot in 1x mode (ignore scaling) - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; mySnap1x = new CheckboxWidget(this, font, xpos, ypos, - "Ignore scaling (1x mode)"); + "Create pixel-exact image (no zoom/post-processing)"); wid.push_back(mySnap1x); // Add Defaults, OK and Cancel buttons @@ -128,7 +131,7 @@ void SnapshotDialog::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void SnapshotDialog::setDefaults() { - mySnapSavePath->setText(instance().defaultSaveDir()); + mySnapSavePath->setText(instance().defaultSaveDir().getShortPath()); mySnapInterval->setValue(2); mySnapName->setState(false); mySnapSingle->setState(false); diff --git a/src/gui/Stella12x24tFont.hxx b/src/gui/Stella12x24tFont.hxx new file mode 100644 index 000000000..4ed48528c --- /dev/null +++ b/src/gui/Stella12x24tFont.hxx @@ -0,0 +1,5609 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// Generated by src/tools/convbdf on Sun Mar 15 08:31:37 2020. +//============================================================================ + +#ifndef STELLA12X24T_FONT_DATA_HXX +#define STELLA12X24T_FONT_DATA_HXX + +#include "Font.hxx" + +/* Font information: + name: ter-u24b + facename: -xos4-Terminus-Bold-R-Normal--24-240-72-72-C-120-ISO10646-1 + w x h: 12x24 + bbx: 12 24 0 -5 + size: 95 + ascent: 19 + descent: 5 + first char: 32 (0x20) + last char: 126 (0x7e) + default char: 32 (0x20) + proportional: no + Copyright (C) 2014 Dimitar Toshkov Zhekov +*/ + +namespace GUI { + +// Font character bitmap data. +static const uInt16 stella12x24t_font_bits[] = { // NOLINT : too complicated to convert + +/* Character 28 (0x1c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0b0000111000000000, +0b0001101100000000, +0b0011000110000000, +0b0011000110000000, +0b0011000110000000, +0b0001101100000000, +0b0000111000000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 29 (0x1d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0110011001100000, +0b0110011001100000, +0b0110011001100000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 30 (0x1e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 31 (0x1f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | **** | + | ******** | + | ******** | + | ********** | + | ********** | + | ********** | + | ********** | + | ******** | + | ******** | + | **** | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0000111100000000, +0b0011111110000000, +0b0011111110000000, +0b0111111111000000, +0b0111111111000000, +0b0111111111000000, +0b0111111111000000, +0b0011111110000000, +0b0011111110000000, +0b0000111100000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 32 (0x20): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 33 (0x21): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 34 (0x22): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x1980, +0x1980, +0x1980, +0x1980, +0x1980, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 35 (0x23): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1980, +0x1980, +0x1980, +0x1980, +0x7fe0, +0x1980, +0x1980, +0x1980, +0x1980, +0x1980, +0x7fe0, +0x1980, +0x1980, +0x1980, +0x1980, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 36 (0x24): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | ** | + | ** | + | ****** | + | ** ** ** | + | ** ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** ** ** | + | ****** | + | ** | + | ** | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x1f80, +0x36c0, +0x6660, +0x6600, +0x6600, +0x3600, +0x1f80, +0x06c0, +0x0660, +0x0660, +0x6660, +0x36c0, +0x1f80, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 37 (0x25): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | *** ** | + | ** ** ** | + | ** ** ** | + | *** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | ** ** ** | + | ** ** ** | + | ** *** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x38c0, +0x6cc0, +0x6d80, +0x3980, +0x0300, +0x0300, +0x0600, +0x0600, +0x0c00, +0x0c00, +0x19c0, +0x1b60, +0x3360, +0x31c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 38 (0x26): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | **** ** | + | ** ** ** | + | ** *** | + | ** ** | + | ** ** | + | ** *** | + | ** ** ** | + | **** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0e00, +0x1b00, +0x3180, +0x3180, +0x3180, +0x1b00, +0x0e00, +0x1e60, +0x3360, +0x61c0, +0x60c0, +0x60c0, +0x61c0, +0x3360, +0x1e60, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 39 (0x27): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 40 (0x28): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0600, +0x0c00, +0x0c00, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x0c00, +0x0c00, +0x0600, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 41 (0x29): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1800, +0x0c00, +0x0600, +0x0600, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0600, +0x0600, +0x0c00, +0x1800, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 42 (0x2a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | *** | + |*********** | + | *** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x60c0, +0x3180, +0x1b00, +0x0e00, +0xffe0, +0x0e00, +0x1b00, +0x3180, +0x60c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 43 (0x2b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ********** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x7fe0, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 44 (0x2c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0c00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 45 (0x2d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 46 (0x2e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 47 (0x2f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x00c0, +0x00c0, +0x0180, +0x0180, +0x0300, +0x0300, +0x0600, +0x0600, +0x0c00, +0x0c00, +0x1800, +0x1800, +0x3000, +0x3000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 48 (0x30): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ** **** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | **** ** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x60e0, +0x61e0, +0x6360, +0x6660, +0x6c60, +0x7860, +0x7060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 49 (0x31): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | *** | + | **** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0e00, +0x1e00, +0x3600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x3fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 50 (0x32): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x0060, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0c00, +0x1800, +0x3000, +0x6000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 51 (0x33): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x0060, +0x0060, +0x0060, +0x00c0, +0x0f80, +0x00c0, +0x0060, +0x0060, +0x0060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 52 (0x34): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | *** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0060, +0x00e0, +0x01e0, +0x0360, +0x0660, +0x0c60, +0x1860, +0x3060, +0x6060, +0x6060, +0x6060, +0x7fe0, +0x0060, +0x0060, +0x0060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 53 (0x35): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x00c0, +0x0060, +0x0060, +0x0060, +0x0060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 54 (0x36): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******* | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 55 (0x37): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x6060, +0x6060, +0x0060, +0x00c0, +0x00c0, +0x0180, +0x0180, +0x0300, +0x0300, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 56 (0x38): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 57 (0x39): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******* | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x3060, +0x1fe0, +0x0060, +0x0060, +0x0060, +0x0060, +0x00c0, +0x3f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 58 (0x3a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 59 (0x3b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0c00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 60 (0x3c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0c00, +0x1800, +0x3000, +0x6000, +0x3000, +0x1800, +0x0c00, +0x0600, +0x0300, +0x0180, +0x00c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 61 (0x3d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | | + | | + | | + | | + | ********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 62 (0x3e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x3000, +0x1800, +0x0c00, +0x0600, +0x0300, +0x0180, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0c00, +0x1800, +0x3000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 63 (0x3f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0600, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 64 (0x40): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******* | + | ** ** | + |** ** | + |** ***** | + |** ** ** | + |** ** ** | + |** ** ** | + |** ** ** | + |** ** ** | + |** ** ** | + |** ** ** | + |** ***** | + |** | + | ** | + | ********* | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3f80, +0x60c0, +0xc060, +0xc3e0, +0xc660, +0xcc60, +0xcc60, +0xcc60, +0xcc60, +0xcc60, +0xc660, +0xc3e0, +0xc000, +0x6000, +0x3fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 65 (0x41): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x7fe0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 66 (0x42): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 67 (0x43): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 68 (0x44): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 69 (0x45): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 70 (0x46): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 71 (0x47): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** ***** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6000, +0x6000, +0x6000, +0x63e0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 72 (0x48): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x7fe0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 73 (0x49): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 74 (0x4a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******| + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ***** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x03f0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x60c0, +0x60c0, +0x60c0, +0x3180, +0x1f00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 75 (0x4b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | *** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x60c0, +0x6180, +0x6300, +0x6600, +0x6c00, +0x7800, +0x7000, +0x7800, +0x6c00, +0x6600, +0x6300, +0x6180, +0x60c0, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 76 (0x4c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 77 (0x4d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + |* * | + |** ** | + |*** *** | + |**** **** | + |** ** ** ** | + |** *** ** | + |** * ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x8020, +0xc060, +0xe0e0, +0xf1e0, +0xdb60, +0xce60, +0xc460, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 78 (0x4e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | **** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** **** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x7060, +0x7860, +0x6c60, +0x6660, +0x6360, +0x61e0, +0x60e0, +0x6060, +0x6060, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 79 (0x4f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 80 (0x50): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 81 (0x51): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** **** | + | ****** | + | ** | + | ** | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6660, +0x33c0, +0x1f80, +0x00c0, +0x0060, +0x0000, +0x0000, +0x0000, + +/* Character 82 (0x52): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x7800, +0x6c00, +0x6600, +0x6300, +0x6180, +0x60c0, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 83 (0x53): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6000, +0x6000, +0x6000, +0x3000, +0x1f80, +0x00c0, +0x0060, +0x0060, +0x0060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 84 (0x54): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 85 (0x55): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 86 (0x56): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x30c0, +0x30c0, +0x30c0, +0x1980, +0x1980, +0x1980, +0x0f00, +0x0f00, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 87 (0x57): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** ** | + |** * ** | + |** *** ** | + |** ** ** ** | + |**** **** | + |*** *** | + |** ** | + |* * | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc060, +0xc460, +0xce60, +0xdb60, +0xf1e0, +0xe0e0, +0xc060, +0x8020, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 88 (0x58): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x30c0, +0x30c0, +0x1980, +0x1980, +0x0f00, +0x0600, +0x0f00, +0x1980, +0x1980, +0x30c0, +0x30c0, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 89 (0x59): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x30c0, +0x30c0, +0x1980, +0x1980, +0x0f00, +0x0f00, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 90 (0x5a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0060, +0x0060, +0x0060, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0c00, +0x1800, +0x3000, +0x6000, +0x6000, +0x6000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 91 (0x5b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ***** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f00, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1800, +0x1f00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 92 (0x5c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3000, +0x3000, +0x1800, +0x1800, +0x0c00, +0x0c00, +0x0600, +0x0600, +0x0300, +0x0300, +0x0180, +0x0180, +0x00c0, +0x00c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 93 (0x5d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ***** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1f00, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x1f00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 94 (0x5e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0600, +0x0f00, +0x1980, +0x30c0, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 95 (0x5f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0000, +0x0000, +0x0000, + +/* Character 96 (0x60): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x1800, +0x0c00, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 97 (0x61): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ** | + | ** | + | ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3f80, +0x00c0, +0x0060, +0x0060, +0x1fe0, +0x3060, +0x6060, +0x6060, +0x6060, +0x3060, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 98 (0x62): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 99 (0x63): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 100 (0x64): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0060, +0x0060, +0x0060, +0x0060, +0x1fe0, +0x3060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x3060, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 101 (0x65): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********** | + | ** | + | ** | + | ** | + | ** ** | + | ******* | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x7fe0, +0x6000, +0x6000, +0x6000, +0x3060, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 102 (0x66): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ***** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x03e0, +0x0600, +0x0600, +0x0600, +0x3fc0, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 103 (0x67): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ******** | + | ** | + | ** | + | ** | + | ******* | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fe0, +0x3060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30e0, +0x1fe0, +0x0060, +0x0060, +0x00c0, +0x3f80, +0x0000, + +/* Character 104 (0x68): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 105 (0x69): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0000, +0x1e00, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 106 (0x6a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x00c0, +0x00c0, +0x00c0, +0x0000, +0x03c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x30c0, +0x30c0, +0x1980, +0x0f00, +0x0000, + +/* Character 107 (0x6b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3000, +0x3000, +0x3000, +0x3000, +0x3060, +0x30c0, +0x3180, +0x3300, +0x3600, +0x3c00, +0x3600, +0x3300, +0x3180, +0x30c0, +0x3060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 108 (0x6c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1e00, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 109 (0x6d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x66c0, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 110 (0x6e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 111 (0x6f): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ****** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1f80, +0x30c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30c0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 112 (0x70): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7f80, +0x60c0, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x60c0, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, + +/* Character 113 (0x71): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fe0, +0x3060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x3060, +0x1fe0, +0x0060, +0x0060, +0x0060, +0x0060, +0x0000, + +/* Character 114 (0x72): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ****** | + | ** ** | + | **** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x67e0, +0x6c00, +0x7800, +0x7000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 115 (0x73): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ******** | + | ** ** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3fc0, +0x6060, +0x6000, +0x6000, +0x6000, +0x3fc0, +0x0060, +0x0060, +0x0060, +0x6060, +0x3fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 116 (0x74): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ***** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x7f80, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x07c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 117 (0x75): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x3060, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 118 (0x76): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x30c0, +0x30c0, +0x1980, +0x1980, +0x0f00, +0x0f00, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 119 (0x77): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ******** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x6660, +0x3fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 120 (0x78): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | ** | + | **** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x30c0, +0x1980, +0x0f00, +0x0600, +0x0f00, +0x1980, +0x30c0, +0x6060, +0x6060, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 121 (0x79): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ******** | + | ** | + | ** | + | ** | + | ******* | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x6060, +0x30e0, +0x1fe0, +0x0060, +0x0060, +0x00c0, +0x3f80, +0x0000, + +/* Character 122 (0x7a): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x0060, +0x00c0, +0x0180, +0x0300, +0x0600, +0x0c00, +0x1800, +0x3000, +0x6000, +0x7fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 123 (0x7b): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0600, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x3800, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0600, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 124 (0x7c): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 125 (0x7d): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | | + | | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3800, +0x0c00, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0380, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0c00, +0x3800, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 126 (0x7e): + width 12 + bbx ( 12, 24, 0, -5 ) + + +------------+ + | | + | | + | **** ** | + | ** ** ** | + | ** ** ** | + | ** **** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +------------+ +*/ +0x0000, +0x0000, +0x3c60, +0x6660, +0x6660, +0x63c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +}; + +/* Exported structure definition. */ +static const FontDesc stella12x24tDesc = { + "ter-u24b", + 12, + 24, + 12, 24, 0, -5, + 19, + 28, + 99, + stella12x24t_font_bits, + nullptr, /* no encode table*/ + nullptr, /* fixed width*/ + nullptr, /* fixed bbox*/ + 32, + sizeof(stella12x24t_font_bits)/sizeof(uInt16) +}; + +} // End of namespace GUI + +#endif diff --git a/src/gui/Stella14x28tFont.hxx b/src/gui/Stella14x28tFont.hxx new file mode 100644 index 000000000..52ad7dda6 --- /dev/null +++ b/src/gui/Stella14x28tFont.hxx @@ -0,0 +1,6402 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// Generated by src/tools/convbdf on Sun Mar 15 08:40:37 2020. +//============================================================================ + +#ifndef STELLA14X28T_FONT_DATA_HXX +#define STELLA14X28T_FONT_DATA_HXX + +#include "Font.hxx" + +/* Font information: + name: ter-u28b + facename: -xos4-Terminus-Bold-R-Normal--28-280-72-72-C-140-ISO10646-1 + w x h: 14x28 + bbx: 14 28 0 -6 + size: 95 + ascent: 22 + descent: 6 + first char: 32 (0x20) + last char: 126 (0x7e) + default char: 32 (0x20) + proportional: no + Copyright (C) 2014 Dimitar Toshkov Zhekov +*/ + +namespace GUI { + +// Font character bitmap data. +static const uInt16 stella14x28t_font_bits[] = { // NOLINT : too complicated to convert + +/* Character 28 (0x1c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0b0000011110000000, +0b0000111111000000, +0b0001110011100000, +0b0001100001100000, +0b0001100001100000, +0b0001110011100000, +0b0000111111000000, +0b0000011110000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + + +/* Character 29 (0x1d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0011001100110000, +0b0011001100110000, +0b0011001100110000, +0b0011001100110000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 30 (0x1e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 31 (0x1f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | **** | + | ******** | + | ********** | + | ********** | + | ************ | + | ************ | + | ************ | + | ************ | + | ************ | + | ************ | + | ********** | + | ********** | + | ******** | + | **** | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0000011110000000, +0b0001111111100000, +0b0011111111110000, +0b0011111111110000, +0b0111111111111000, +0b0111111111111000, +0b0111111111111000, +0b0111111111111000, +0b0111111111111000, +0b0111111111111000, +0b0011111111110000, +0b0011111111110000, +0b0001111111100000, +0b0000011110000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 32 (0x20): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 33 (0x21): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 34 (0x22): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 35 (0x23): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x7ff0, +0x7ff0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x7ff0, +0x7ff0, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 36 (0x24): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | ** | + | ** | + | ** | + | ******** | + | ********** | + | *** ** *** | + | ** ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********* | + | ********* | + | ** *** | + | ** ** | + | ** ** | + | ** ** ** | + | *** ** *** | + | ********** | + | ******** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x1fe0, +0x3ff0, +0x7338, +0x6318, +0x6300, +0x6300, +0x7300, +0x3fe0, +0x1ff0, +0x0338, +0x0318, +0x0318, +0x6318, +0x7338, +0x3ff0, +0x1fe0, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 37 (0x25): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | **** ** | + | ****** ** | + | ** ** ** | + | ****** ** | + | **** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** **** | + | ** ****** | + | ** ** ** | + | ** ****** | + | ** **** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3c30, +0x7e30, +0x6660, +0x7e60, +0x3cc0, +0x00c0, +0x0180, +0x0180, +0x0300, +0x0300, +0x0600, +0x0600, +0x0c00, +0x0cf0, +0x19f8, +0x1998, +0x31f8, +0x30f0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 38 (0x26): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | **** | + | ****** | + | *** *** | + | ** ** | + | ** ** | + | *** *** | + | ****** | + | **** | + | *** | + | ***** ** | + | *** *** *** | + | *** ***** | + | ** *** | + | ** *** | + | ** *** | + | *** ***** | + | ******* *** | + | ***** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0f00, +0x1f80, +0x39c0, +0x30c0, +0x30c0, +0x39c0, +0x1f80, +0x0f00, +0x0e00, +0x1f18, +0x3bb8, +0x71f0, +0x60e0, +0x60e0, +0x60e0, +0x71f0, +0x3fb8, +0x1f18, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 39 (0x27): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 40 (0x28): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0180, +0x0300, +0x0600, +0x0600, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0600, +0x0600, +0x0300, +0x0180, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 41 (0x29): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0c00, +0x0600, +0x0300, +0x0300, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0180, +0x0300, +0x0300, +0x0600, +0x0c00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 42 (0x2a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | ***** | + | *** | + | *********** | + | *********** | + | *** | + | ***** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x38e0, +0x1dc0, +0x0f80, +0x0700, +0x7ff0, +0x7ff0, +0x0700, +0x0f80, +0x1dc0, +0x38e0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 43 (0x2b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ************ | + | ************ | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x7ff8, +0x7ff8, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 44 (0x2c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0600, +0x0c00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 45 (0x2d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 46 (0x2e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 47 (0x2f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0030, +0x0030, +0x0060, +0x0060, +0x00c0, +0x00c0, +0x0180, +0x0180, +0x0300, +0x0300, +0x0600, +0x0600, +0x0c00, +0x0c00, +0x1800, +0x1800, +0x3000, +0x3000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 48 (0x30): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** *** | + | ** **** | + | ** ***** | + | ** *** ** | + | ** *** ** | + | ** *** ** | + | ***** ** | + | **** ** | + | *** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6070, +0x60f0, +0x61f0, +0x63b0, +0x6730, +0x6e30, +0x7c30, +0x7830, +0x7030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 49 (0x31): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | *** | + | **** | + | ***** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ******** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0700, +0x0f00, +0x1f00, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x1fe0, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 50 (0x32): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x0030, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 51 (0x33): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** | + | ** | + | ** | + | *** | + | ******* | + | ******* | + | *** | + | ** | + | ** | + | ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x0030, +0x0030, +0x0030, +0x0070, +0x0fe0, +0x0fe0, +0x0070, +0x0030, +0x0030, +0x0030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 52 (0x34): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | *** | + | **** | + | ***** | + | *** ** | + | *** ** | + | *** ** | + | *** ** | + | *** ** | + | *** ** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0030, +0x0070, +0x00f0, +0x01f0, +0x03b0, +0x0730, +0x0e30, +0x1c30, +0x3830, +0x7030, +0x6030, +0x6030, +0x7ff0, +0x7ff0, +0x0030, +0x0030, +0x0030, +0x0030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 53 (0x35): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *********** | + | *********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********* | + | ********** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fc0, +0x7fe0, +0x0070, +0x0030, +0x0030, +0x0030, +0x0030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 54 (0x36): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******** | + | ********* | + | *** | + | ** | + | ** | + | ** | + | ** | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fe0, +0x3fe0, +0x7000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 55 (0x37): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *********** | + | *********** | + | ** ** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x6030, +0x6030, +0x6030, +0x0060, +0x0060, +0x00c0, +0x00c0, +0x0180, +0x0180, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 56 (0x38): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 57 (0x39): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | ** | + | ** | + | ** | + | ** | + | *** | + | ********* | + | ******** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0030, +0x0030, +0x0030, +0x0030, +0x0070, +0x3fe0, +0x3fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 58 (0x3a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 59 (0x3b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0600, +0x0c00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 60 (0x3c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x3800, +0x1c00, +0x0e00, +0x0700, +0x0380, +0x01c0, +0x00e0, +0x0070, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 61 (0x3d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | *********** | + | | + | | + | | + | | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 62 (0x3e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7000, +0x3800, +0x1c00, +0x0e00, +0x0700, +0x0380, +0x01c0, +0x00e0, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 63 (0x3f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | *** | + | *** | + | *** | + | ** | + | ** | + | | + | | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0300, +0x0300, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 64 (0x40): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******** | + | ********** | + | *** *** | + | ** ** | + | ** ****** | + | ** ******* | + | ** *** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** *** ** | + | ** ******* | + | ** **** * | + | ** | + | *** | + | *********** | + | ********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fe0, +0x3ff0, +0x7038, +0x6018, +0x61f8, +0x63f8, +0x6718, +0x6618, +0x6618, +0x6618, +0x6618, +0x6718, +0x63f8, +0x61e8, +0x6000, +0x7000, +0x3ff8, +0x1ff8, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 65 (0x41): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7ff0, +0x7ff0, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 66 (0x42): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ********* | + | ********* | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********** | + | ********* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6060, +0x7fc0, +0x7fc0, +0x6060, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6070, +0x7fe0, +0x7fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 67 (0x43): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 68 (0x44): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7f00, +0x7fc0, +0x60e0, +0x6060, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6060, +0x60e0, +0x7fc0, +0x7f00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 69 (0x45): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *********** | + | *********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 70 (0x46): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *********** | + | *********** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7f80, +0x7f80, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 71 (0x47): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** | + | ** | + | ** | + | ** ****** | + | ** ****** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6000, +0x6000, +0x6000, +0x63f0, +0x63f0, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 72 (0x48): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7ff0, +0x7ff0, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 73 (0x49): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ****** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0fc0, +0x0fc0, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0fc0, +0x0fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 74 (0x4a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ****** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ******** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x01f8, +0x01f8, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x6060, +0x6060, +0x6060, +0x70e0, +0x3fc0, +0x1f80, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 75 (0x4b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ***** | + | **** | + | **** | + | ***** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6070, +0x60e0, +0x61c0, +0x6380, +0x6700, +0x6e00, +0x7c00, +0x7800, +0x7800, +0x7c00, +0x6e00, +0x6700, +0x6380, +0x61c0, +0x60e0, +0x6070, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 76 (0x4c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 77 (0x4d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | *** *** | + | **** **** | + | ***** ***** | + | ** ****** ** | + | ** **** ** | + | ** ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6018, +0x6018, +0x7038, +0x7878, +0x7cf8, +0x6fd8, +0x6798, +0x6318, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 78 (0x4e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | **** ** | + | ***** ** | + | ** *** ** | + | ** *** ** | + | ** *** ** | + | ** ***** | + | ** **** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x7830, +0x7c30, +0x6e30, +0x6730, +0x63b0, +0x61f0, +0x60f0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 79 (0x4f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 80 (0x50): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********** | + | ********* | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6070, +0x7fe0, +0x7fc0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 81 (0x51): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** ** | + | *** ***** | + | ********* | + | ******** | + | *** | + | *** | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x63b0, +0x71f0, +0x3fe0, +0x1fe0, +0x0070, +0x0038, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 82 (0x52): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********** | + | ********* | + | ***** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6070, +0x7fe0, +0x7fc0, +0x7c00, +0x6e00, +0x6700, +0x6380, +0x61c0, +0x60e0, +0x6070, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 83 (0x53): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** | + | ** | + | ** | + | *** | + | ******** | + | ******** | + | *** | + | ** | + | ** | + | ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6000, +0x6000, +0x6000, +0x7000, +0x3fc0, +0x1fe0, +0x0070, +0x0030, +0x0030, +0x0030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 84 (0x54): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ************ | + | ************ | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff8, +0x7ff8, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 85 (0x55): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 86 (0x56): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x3060, +0x3060, +0x3060, +0x3060, +0x18c0, +0x18c0, +0x18c0, +0x18c0, +0x0d80, +0x0d80, +0x0d80, +0x0700, +0x0700, +0x0700, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 87 (0x57): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** **** ** | + | ** ****** ** | + | ***** ***** | + | **** **** | + | *** *** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6018, +0x6318, +0x6798, +0x6fd8, +0x7cf8, +0x7878, +0x7038, +0x6018, +0x6018, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 88 (0x58): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x3060, +0x3060, +0x18c0, +0x18c0, +0x0d80, +0x0d80, +0x0700, +0x0700, +0x0d80, +0x0d80, +0x18c0, +0x18c0, +0x3060, +0x3060, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 89 (0x59): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6018, +0x6018, +0x3030, +0x3030, +0x1860, +0x1860, +0x0cc0, +0x0cc0, +0x0780, +0x0780, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 90 (0x5a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *********** | + | *********** | + | ** | + | ** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ** | + | ** | + | ** | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0030, +0x0030, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x6000, +0x6000, +0x6000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 91 (0x5b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ****** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0fc0, +0x0fc0, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0c00, +0x0fc0, +0x0fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 92 (0x5c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3000, +0x3000, +0x1800, +0x1800, +0x0c00, +0x0c00, +0x0600, +0x0600, +0x0300, +0x0300, +0x0180, +0x0180, +0x00c0, +0x00c0, +0x0060, +0x0060, +0x0030, +0x0030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 93 (0x5d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ****** | + | ****** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0fc0, +0x0fc0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x00c0, +0x0fc0, +0x0fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 94 (0x5e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | * | + | *** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0200, +0x0700, +0x0f80, +0x1dc0, +0x38e0, +0x7070, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 95 (0x5f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | *********** | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, + +/* Character 96 (0x60): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x1c00, +0x0e00, +0x0700, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 97 (0x61): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ******** | + | *** | + | ** | + | ********* | + | ********** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x1fe0, +0x0070, +0x0030, +0x1ff0, +0x3ff0, +0x7030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 98 (0x62): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********** | + | ********* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6070, +0x7fe0, +0x7fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 99 (0x63): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 100 (0x64): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********* | + | ********** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0030, +0x0030, +0x0030, +0x0030, +0x0030, +0x1ff0, +0x3ff0, +0x7030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 101 (0x65): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | *********** | + | *********** | + | ** | + | ** | + | ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x7ff0, +0x7ff0, +0x6000, +0x6000, +0x6000, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 102 (0x66): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ****** | + | ******* | + | ** | + | ** | + | ** | + | ******** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x03f0, +0x07f0, +0x0600, +0x0600, +0x0600, +0x3fc0, +0x3fc0, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 103 (0x67): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | ********** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | ** | + | ** | + | *** | + | ********* | + | ******** | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff0, +0x7030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0030, +0x0030, +0x0070, +0x3fe0, +0x3fc0, +0x0000, + +/* Character 104 (0x68): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 105 (0x69): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0f00, +0x0f00, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0fc0, +0x0fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 106 (0x6a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | | + | | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** ** | + | ** ** | + | *** *** | + | ******* | + | ***** | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0060, +0x0060, +0x0060, +0x0000, +0x0000, +0x01e0, +0x01e0, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x0060, +0x3060, +0x3060, +0x38e0, +0x1fc0, +0x0f80, +0x0000, + +/* Character 107 (0x6b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ***** | + | **** | + | ***** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | ** *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x3000, +0x3000, +0x3000, +0x3000, +0x3000, +0x3070, +0x30e0, +0x31c0, +0x3380, +0x3700, +0x3e00, +0x3c00, +0x3e00, +0x3700, +0x3380, +0x31c0, +0x30e0, +0x3070, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 108 (0x6c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | **** | + | **** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ****** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0f00, +0x0f00, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0fc0, +0x0fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 109 (0x6d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | *********** | + | ** ** *** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fe0, +0x7ff0, +0x6338, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 110 (0x6e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 111 (0x6f): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 112 (0x70): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | ********** | + | ** *** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** *** | + | ********** | + | ********* | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7fe0, +0x6070, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6070, +0x7fe0, +0x7fc0, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, + +/* Character 113 (0x71): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | ********** | + | *** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff0, +0x7030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0030, +0x0030, +0x0030, +0x0030, +0x0030, +0x0000, + +/* Character 114 (0x72): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ******* | + | ** ******** | + | ***** | + | **** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x67f0, +0x6ff0, +0x7c00, +0x7800, +0x7000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x6000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 115 (0x73): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ******* | + | ********* | + | *** *** | + | ** | + | *** | + | ******** | + | ******** | + | *** | + | ** | + | ** | + | *** *** | + | ********* | + | ******* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1fc0, +0x3fe0, +0x7070, +0x6000, +0x7000, +0x3fc0, +0x1fe0, +0x0070, +0x0030, +0x0030, +0x7070, +0x3fe0, +0x1fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 116 (0x74): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ******** | + | ******** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ****** | + | ***** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x3fc0, +0x3fc0, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x07e0, +0x03e0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 117 (0x75): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 118 (0x76): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x3060, +0x3060, +0x3060, +0x18c0, +0x18c0, +0x18c0, +0x0d80, +0x0d80, +0x0700, +0x0700, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 119 (0x77): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | ** ** ** | + | *** ** *** | + | ********** | + | ******** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6018, +0x6018, +0x6018, +0x6018, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x6318, +0x7338, +0x3ff0, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 120 (0x78): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | *** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | ** ** | + | ** ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x7070, +0x38e0, +0x1dc0, +0x0f80, +0x0700, +0x0f80, +0x1dc0, +0x38e0, +0x7070, +0x6030, +0x6030, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 121 (0x79): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | ** ** | + | *** ** | + | ********** | + | ********* | + | ** | + | ** | + | *** | + | ********* | + | ******** | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x6030, +0x7030, +0x3ff0, +0x1ff0, +0x0030, +0x0030, +0x0070, +0x3fe0, +0x3fc0, +0x0000, + +/* Character 122 (0x7a): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | *********** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff0, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x7ff0, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 123 (0x7b): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *** | + | **** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | **** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x01c0, +0x03c0, +0x0700, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x1c00, +0x1c00, +0x0600, +0x0600, +0x0600, +0x0600, +0x0600, +0x0700, +0x03c0, +0x01c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 124 (0x7c): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | ** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 125 (0x7d): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | | + | | + | *** | + | **** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | *** | + | ** | + | ** | + | ** | + | ** | + | ** | + | *** | + | **** | + | *** | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1c00, +0x1e00, +0x0700, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x01c0, +0x01c0, +0x0300, +0x0300, +0x0300, +0x0300, +0x0300, +0x0700, +0x1e00, +0x1c00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 126 (0x7e): + width 14 + bbx ( 14, 28, 0, -6 ) + + +--------------+ + | | + | | + | **** ** | + | ****** ** | + | ** *** ** | + | ** ****** | + | ** **** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +--------------+ +*/ +0x0000, +0x0000, +0x3c30, +0x7e30, +0x6730, +0x63f0, +0x61e0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +}; + +/* Exported structure definition. */ +static const FontDesc stella14x28tDesc = { + "ter-u28b", + 14, + 28, + 14, 28, 0, -6, + 22, + 28, + 99, + stella14x28t_font_bits, + nullptr, /* no encode table*/ + nullptr, /* fixed width*/ + nullptr, /* fixed bbox*/ + 32, + sizeof(stella14x28t_font_bits)/sizeof(uInt16) +}; + +} // End of namespace GUI + +#endif diff --git a/src/gui/Stella16x32tFont.hxx b/src/gui/Stella16x32tFont.hxx new file mode 100644 index 000000000..6f15c3293 --- /dev/null +++ b/src/gui/Stella16x32tFont.hxx @@ -0,0 +1,7193 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// Generated by src/tools/convbdf on Sun Mar 15 08:41:32 2020. +//============================================================================ + +#ifndef STELLA16X32T_FONT_DATA_HXX +#define STELLA16X32T_FONT_DATA_HXX + +#include "Font.hxx" + +/* Font information: + name: ter-u32b + facename: -xos4-Terminus-Bold-R-Normal--32-320-72-72-C-160-ISO10646-1 + w x h: 16x32 + bbx: 16 32 0 -6 + size: 95 + ascent: 26 + descent: 6 + first char: 32 (0x20) + last char: 126 (0x7e) + default char: 32 (0x20) + proportional: no + Copyright (C) 2014 Dimitar Toshkov Zhekov +*/ + +namespace GUI { + +// Font character bitmap data. +static const uInt16 stella16x32t_font_bits[] = { // NOLINT : too complicated to convert + +/* Character 28 (0x1c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0000111110000000, +0b0001111111000000, +0b0011110111100000, +0b0011100011100000, +0b0011100011100000, +0b0011110111100000, +0b0001111111000000, +0b0000111110000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 29 (0x1d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0011100111001110, +0b0011100111001110, +0b0011100111001110, +0b0011100111001110, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 30 (0x1e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 31 (0x1f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ***** | + | ********* | + | *********** | + | *********** | + | ************* | + | ************* | + | ************* | + | ************* | + | ************* | + | ************* | + | *********** | + | *********** | + | ********* | + | ***** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0b0000011111000000, +0b0001111111110000, +0b0011111111111000, +0b0011111111111000, +0b0111111111111100, +0b0111111111111100, +0b0111111111111100, +0b0111111111111100, +0b0111111111111100, +0b0111111111111100, +0b0011111111111000, +0b0011111111111000, +0b0001111111110000, +0b0000011111000000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 32 (0x20): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 33 (0x21): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 34 (0x22): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 35 (0x23): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x7ffc, +0x7ffc, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x7ffc, +0x7ffc, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 36 (0x24): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | *** | + | *** | + | *** | + | ********* | + | *********** | + | **** *** **** | + | *** *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ********** | + | ********** | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** *** | + | **** *** **** | + | *********** | + | ********* | + | *** | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x1ff0, +0x3ff8, +0x7bbc, +0x739c, +0x7380, +0x7380, +0x7380, +0x7b80, +0x3ff0, +0x1ff8, +0x03bc, +0x039c, +0x039c, +0x039c, +0x739c, +0x7bbc, +0x3ff8, +0x1ff0, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 37 (0x25): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ***** *** | + | ******* *** | + | *** *** *** | + | *** *** *** | + | ********** | + | ***** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** ***** | + | ********** | + | *** *** *** | + | *** *** *** | + | *** ******* | + | *** ***** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1f1c, +0x3f9c, +0x3bb8, +0x3bb8, +0x3ff0, +0x1f70, +0x00e0, +0x00e0, +0x01c0, +0x01c0, +0x0380, +0x0380, +0x0700, +0x0700, +0x0ef8, +0x0ffc, +0x1ddc, +0x1ddc, +0x39fc, +0x38f8, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 38 (0x26): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ****** | + | ******** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ****** | + | ***** | + | ******* *** | + | *** *** *** | + | *** ***** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** ***** | + | ********* *** | + | ******* *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0fc0, +0x1fe0, +0x3870, +0x3870, +0x3870, +0x3870, +0x3870, +0x1ce0, +0x0fc0, +0x0f80, +0x1fce, +0x38ee, +0x707c, +0x7038, +0x7038, +0x7038, +0x7038, +0x787c, +0x3fee, +0x1fce, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 39 (0x27): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 40 (0x28): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0700, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0700, +0x0700, +0x0380, +0x01c0, +0x00e0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 41 (0x29): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0e00, +0x0700, +0x0380, +0x01c0, +0x01c0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x00e0, +0x01c0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 42 (0x2a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | *** | + | ************* | + | ************* | + | *** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3838, +0x1c70, +0x0ee0, +0x07c0, +0x0380, +0x7ffc, +0x7ffc, +0x0380, +0x07c0, +0x0ee0, +0x1c70, +0x3838, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 43 (0x2b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x7ffc, +0x7ffc, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 44 (0x2c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0700, +0x0e00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 45 (0x2d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 46 (0x2e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 47 (0x2f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x001c, +0x001c, +0x0038, +0x0038, +0x0070, +0x0070, +0x00e0, +0x00e0, +0x01c0, +0x01c0, +0x0380, +0x0380, +0x0700, +0x0700, +0x0e00, +0x0e00, +0x1c00, +0x1c00, +0x3800, +0x3800, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 48 (0x30): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** **** | + | *** ***** | + | *** ****** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | ****** *** | + | ***** *** | + | **** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x703c, +0x707c, +0x70fc, +0x71dc, +0x739c, +0x771c, +0x7e1c, +0x7c1c, +0x781c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 49 (0x31): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | **** | + | ***** | + | ****** | + | ****** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ********* | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0780, +0x0f80, +0x1f80, +0x1f80, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x1ff0, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 50 (0x32): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x001c, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 51 (0x33): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | **** | + | ********* | + | ********* | + | **** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x001c, +0x001c, +0x001c, +0x003c, +0x0ff8, +0x0ff8, +0x003c, +0x001c, +0x001c, +0x001c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 52 (0x34): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | **** | + | ***** | + | ****** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x001c, +0x003c, +0x007c, +0x00fc, +0x01dc, +0x039c, +0x071c, +0x0e1c, +0x1c1c, +0x381c, +0x701c, +0x701c, +0x701c, +0x7ffc, +0x7ffc, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 53 (0x35): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | ************ | + | **** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | **** *** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ff0, +0x7ff8, +0x003c, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x701c, +0x781c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 54 (0x36): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********** | + | *********** | + | **** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff8, +0x3ff8, +0x7800, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 55 (0x37): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x701c, +0x701c, +0x701c, +0x7038, +0x0038, +0x0070, +0x0070, +0x00e0, +0x00e0, +0x01c0, +0x01c0, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 56 (0x38): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 57 (0x39): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | **** | + | *********** | + | ********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x003c, +0x3ff8, +0x3ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 58 (0x3a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 59 (0x3b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0700, +0x0e00, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 60 (0x3c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x001c, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x3800, +0x1c00, +0x0e00, +0x0700, +0x0380, +0x01c0, +0x00e0, +0x0070, +0x0038, +0x001c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 61 (0x3d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | | + | | + | | + | | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 62 (0x3e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3800, +0x1c00, +0x0e00, +0x0700, +0x0380, +0x01c0, +0x00e0, +0x0070, +0x0038, +0x001c, +0x001c, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 63 (0x3f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 64 (0x40): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********** | + | ************ | + | **** *** | + | *** ** | + | *** ******** | + | *** ********* | + | *** **** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** **** **** | + | *** ********* | + | *** ***** ** | + | *** | + | **** | + | ************* | + | ************ | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff8, +0x3ffc, +0x780e, +0x7006, +0x71fe, +0x73fe, +0x778e, +0x770e, +0x770e, +0x770e, +0x770e, +0x770e, +0x770e, +0x779e, +0x73fe, +0x71f6, +0x7000, +0x7800, +0x3ffe, +0x1ffe, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 65 (0x41): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x7ffc, +0x7ffc, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 66 (0x42): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *********** | + | *********** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | ************ | + | *********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x7038, +0x7ff0, +0x7ff0, +0x7038, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x703c, +0x7ff8, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 67 (0x43): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 68 (0x44): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7fc0, +0x7ff0, +0x7078, +0x7038, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x7038, +0x7078, +0x7ff0, +0x7fc0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 69 (0x45): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ********** | + | ********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7fe0, +0x7fe0, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 70 (0x46): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ********** | + | ********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7fe0, +0x7fe0, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 71 (0x47): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** ******* | + | *** ******* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x7000, +0x7000, +0x7000, +0x7000, +0x71fc, +0x71fc, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 72 (0x48): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x7ffc, +0x7ffc, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 73 (0x49): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ******* | + | ******* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ******* | + | ******* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0fe0, +0x0fe0, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0fe0, +0x0fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 74 (0x4a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ******* | + | ******* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | ********** | + | ******** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x00fe, +0x00fe, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x7038, +0x7038, +0x7038, +0x7878, +0x3ff0, +0x1fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 75 (0x4b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** ** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ****** | + | ***** | + | ***** | + | ****** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** ** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x700c, +0x701c, +0x7038, +0x7070, +0x70e0, +0x71c0, +0x7380, +0x7700, +0x7e00, +0x7c00, +0x7c00, +0x7e00, +0x7700, +0x7380, +0x71c0, +0x70e0, +0x7070, +0x7038, +0x701c, +0x700c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 76 (0x4c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 77 (0x4d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | **** **** | + | ***** ***** | + | ****** ****** | + | ****** ****** | + | *** ****** *** | + | *** **** *** | + | *** **** *** | + | *** ** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x700e, +0x700e, +0x781e, +0x7c3e, +0x7e7e, +0x7e7e, +0x77ee, +0x73ce, +0x73ce, +0x718e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 78 (0x4e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ***** *** | + | ****** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** ****** | + | *** ***** | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x7c1c, +0x7e1c, +0x771c, +0x739c, +0x71dc, +0x70fc, +0x707c, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 79 (0x4f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 80 (0x50): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | ************ | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x703c, +0x7ff8, +0x7ff0, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 81 (0x51): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** *** | + | **** ******* | + | *********** | + | ********* | + | *** | + | *** | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x739c, +0x79fc, +0x3ff8, +0x1ff0, +0x0038, +0x001c, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 82 (0x52): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | ************ | + | *********** | + | ****** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x703c, +0x7ff8, +0x7ff0, +0x7e00, +0x7700, +0x7380, +0x71c0, +0x70e0, +0x7070, +0x7038, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 83 (0x53): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** | + | *** | + | *** | + | **** | + | ********** | + | ********** | + | **** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x7000, +0x7000, +0x7000, +0x7800, +0x3ff0, +0x1ff8, +0x003c, +0x001c, +0x001c, +0x001c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 84 (0x54): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 85 (0x55): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 86 (0x56): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | ***** | + | ***** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x3838, +0x3838, +0x3838, +0x3838, +0x3838, +0x1c70, +0x1c70, +0x1c70, +0x1c70, +0x0ee0, +0x0ee0, +0x0ee0, +0x07c0, +0x07c0, +0x07c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 87 (0x57): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** ** *** | + | *** **** *** | + | *** **** *** | + | *** ****** *** | + | ****** ****** | + | ****** ****** | + | ***** ***** | + | **** **** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x700e, +0x718e, +0x73ce, +0x73ce, +0x77ee, +0x7e7e, +0x7e7e, +0x7c3e, +0x781e, +0x700e, +0x700e, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 88 (0x58): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | ***** | + | ***** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x3838, +0x3838, +0x1c70, +0x1c70, +0x0ee0, +0x0ee0, +0x07c0, +0x07c0, +0x07c0, +0x07c0, +0x0ee0, +0x0ee0, +0x1c70, +0x1c70, +0x3838, +0x3838, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 89 (0x59): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x3838, +0x3838, +0x1c70, +0x1c70, +0x0ee0, +0x0ee0, +0x07c0, +0x07c0, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 90 (0x5a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x001c, +0x001c, +0x001c, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 91 (0x5b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ******** | + | ******** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ******** | + | ******** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0ff0, +0x0ff0, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0e00, +0x0ff0, +0x0ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 92 (0x5c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3800, +0x3800, +0x1c00, +0x1c00, +0x0e00, +0x0e00, +0x0700, +0x0700, +0x0380, +0x0380, +0x01c0, +0x01c0, +0x00e0, +0x00e0, +0x0070, +0x0070, +0x0038, +0x0038, +0x001c, +0x001c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 93 (0x5d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ******** | + | ******** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ******** | + | ******** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0ff0, +0x0ff0, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0070, +0x0ff0, +0x0ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 94 (0x5e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | *** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x07c0, +0x0ee0, +0x1c70, +0x3838, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 95 (0x5f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, + +/* Character 96 (0x60): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x1c00, +0x0e00, +0x0700, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 97 (0x61): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********** | + | *********** | + | **** | + | *** | + | *** | + | *********** | + | ************ | + | **** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3ff0, +0x3ff8, +0x003c, +0x001c, +0x001c, +0x1ffc, +0x3ffc, +0x781c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 98 (0x62): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | ************ | + | *********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x703c, +0x7ff8, +0x7ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 99 (0x63): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 100 (0x64): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | ************ | + | **** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x1ffc, +0x3ffc, +0x781c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 101 (0x65): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | **** *** | + | ************ | + | ********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x7ffc, +0x7ffc, +0x7000, +0x7000, +0x7000, +0x781c, +0x3ffc, +0x1ff8, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 102 (0x66): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ******* | + | ******** | + | **** | + | *** | + | *** | + | *** | + | *********** | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x00fe, +0x01fe, +0x03c0, +0x0380, +0x0380, +0x0380, +0x3ff8, +0x3ff8, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 103 (0x67): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | **** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | *** | + | *** | + | *** | + | *********** | + | ********** | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ffc, +0x3ffc, +0x781c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x001c, +0x001c, +0x001c, +0x3ff8, +0x3ff0, +0x0000, + +/* Character 104 (0x68): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 105 (0x69): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ******* | + | ******* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0f80, +0x0f80, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0fe0, +0x0fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 106 (0x6a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | | + | | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | **** **** | + | ********* | + | ******* | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0038, +0x0038, +0x0038, +0x0038, +0x0000, +0x0000, +0x00f8, +0x00f8, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x0038, +0x3838, +0x3838, +0x3c78, +0x1ff0, +0x0fe0, +0x0000, + +/* Character 107 (0x6b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ****** | + | ****** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3800, +0x3800, +0x3800, +0x3800, +0x3800, +0x3800, +0x381c, +0x3838, +0x3870, +0x38e0, +0x39c0, +0x3b80, +0x3f00, +0x3f00, +0x3b80, +0x39c0, +0x38e0, +0x3870, +0x3838, +0x381c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 108 (0x6c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ******* | + | ******* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0f80, +0x0f80, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0fe0, +0x0fe0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 109 (0x6d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** *** **** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x73bc, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 110 (0x6e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 111 (0x6f): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 112 (0x70): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | *** **** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** **** | + | ************ | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ff0, +0x7ff8, +0x703c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x703c, +0x7ff8, +0x7ff0, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x0000, + +/* Character 113 (0x71): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *********** | + | ************ | + | **** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ffc, +0x3ffc, +0x781c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x001c, +0x001c, +0x001c, +0x001c, +0x001c, +0x0000, + +/* Character 114 (0x72): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** ******** | + | *** ********* | + | ****** | + | ***** | + | **** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x73fc, +0x77fc, +0x7e00, +0x7c00, +0x7800, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x7000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 115 (0x73): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ********* | + | *********** | + | **** **** | + | *** | + | *** | + | **** | + | ********** | + | ********** | + | **** | + | *** | + | *** | + | **** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x1ff0, +0x3ff8, +0x783c, +0x7000, +0x7000, +0x7800, +0x3ff0, +0x1ff8, +0x003c, +0x001c, +0x001c, +0x783c, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 116 (0x74): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *********** | + | *********** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | **** | + | ******** | + | ******* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x7ff0, +0x7ff0, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0780, +0x03fc, +0x01fc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 117 (0x75): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 118 (0x76): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | ***** | + | ***** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x3838, +0x3838, +0x3838, +0x1c70, +0x1c70, +0x1c70, +0x0ee0, +0x0ee0, +0x07c0, +0x07c0, +0x07c0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 119 (0x77): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | *** *** *** | + | **** *** **** | + | *********** | + | ********* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x739c, +0x7bbc, +0x3ff8, +0x1ff0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 120 (0x78): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | ***** | + | ***** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x3838, +0x1c70, +0x0ee0, +0x07c0, +0x07c0, +0x0ee0, +0x1c70, +0x3838, +0x701c, +0x701c, +0x701c, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 121 (0x79): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | *** *** | + | **** *** | + | ************ | + | *********** | + | *** | + | *** | + | **** | + | *********** | + | ********** | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x701c, +0x781c, +0x3ffc, +0x1ffc, +0x001c, +0x001c, +0x003c, +0x3ff8, +0x3ff0, +0x0000, + +/* Character 122 (0x7a): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ************* | + | ************* | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ************* | + | ************* | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x7ffc, +0x7ffc, +0x0038, +0x0070, +0x00e0, +0x01c0, +0x0380, +0x0700, +0x0e00, +0x1c00, +0x3800, +0x7000, +0x7ffc, +0x7ffc, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 123 (0x7b): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ***** | + | ****** | + | **** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | **** | + | ****** | + | ***** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x01f0, +0x03f0, +0x0780, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x3e00, +0x3e00, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0700, +0x0780, +0x03f0, +0x01f0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 124 (0x7c): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 125 (0x7d): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | | + | | + | ***** | + | ****** | + | **** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | ***** | + | ***** | + | *** | + | *** | + | *** | + | *** | + | *** | + | *** | + | **** | + | ****** | + | ***** | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x3e00, +0x3f00, +0x0780, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x01f0, +0x01f0, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0380, +0x0780, +0x3f00, +0x3e00, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, + +/* Character 126 (0x7e): + width 16 + bbx ( 16, 32, 0, -6 ) + + +----------------+ + | | + | | + | | + | | + | **** *** | + | ****** *** | + | *** **** *** | + | *** **** *** | + | *** ****** | + | *** **** | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------------+ +*/ +0x0000, +0x0000, +0x0000, +0x0000, +0x1e1c, +0x3f1c, +0x779c, +0x73dc, +0x71f8, +0x70f0, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +0x0000, +}; + +/* Exported structure definition. */ +static const FontDesc stella16x32tDesc = { + "ter-u32b", + 16, + 32, + 16, 32, 0, -6, + 26, + 28, + 99, + stella16x32t_font_bits, + nullptr, /* no encode table*/ + nullptr, /* fixed width*/ + nullptr, /* fixed bbox*/ + 32, + sizeof(stella16x32t_font_bits)/sizeof(uInt16) +}; + +} // End of namespace GUI + +#endif diff --git a/src/gui/StellaLargeFont.hxx b/src/gui/StellaLargeFont.hxx index 39b181b8f..f8a2f5a42 100644 --- a/src/gui/StellaLargeFont.hxx +++ b/src/gui/StellaLargeFont.hxx @@ -42,6 +42,55 @@ namespace GUI { // Font character bitmap data. static const uInt16 stellaLarge_font_bits[] = { // NOLINT : too complicated to convert + /* MODIFIED + Character 28 (0x1c): + width 10 + bbx ( 10, 20, 0, -4 ) + + +----------+ + | | + | | + | | + | XXXX | + | XX XX | + | XX XX | + | XX XX | + | XX XX | + | XXXX | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + | | + +----------+ + */ + 0x0000, + 0x0000, + 0x0000, + 0b0001111000000000, + 0b0011001100000000, + 0b0011001100000000, + 0b0011001100000000, + 0b0011001100000000, + 0b0001111000000000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + /* MODIFIED Character 29 (0x1d): width 10 @@ -153,14 +202,14 @@ static const uInt16 stellaLarge_font_bits[] = { // NOLINT : too complicated to | | | | | | - | | - | | - | | - | | - | | - | | - | | - | | + | **** | + | ****** | + | ******** | + | ******** | + | ******** | + | ******** | + | ****** | + | **** | | | | | | | @@ -175,14 +224,14 @@ static const uInt16 stellaLarge_font_bits[] = { // NOLINT : too complicated to 0x0000, 0x0000, 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, - 0x0000, + 0b0001111000000000, + 0b0011111100000000, + 0b0111111110000000, + 0b0111111110000000, + 0b0111111110000000, + 0b0111111110000000, + 0b0011111100000000, + 0b0001111000000000, 0x0000, 0x0000, 0x0000, @@ -4759,8 +4808,8 @@ static const FontDesc stellaLargeDesc = { 20, 10, 20, 0, -4, 16, - 29, - 98, + 28, + 99, stellaLarge_font_bits, nullptr, /* no encode table*/ nullptr, /* fixed width*/ diff --git a/src/gui/StellaMediumFont.hxx b/src/gui/StellaMediumFont.hxx index e0fd43629..e81422454 100644 --- a/src/gui/StellaMediumFont.hxx +++ b/src/gui/StellaMediumFont.hxx @@ -43,6 +43,52 @@ namespace GUI { static const uInt16 stellaMedium_font_bits[] = { // NOLINT : too complicated to convert + /* MODIFIED + Character 28 (0x1c): degree + width 9 + bbx ( 9, 15, 0, -3 ) + + +---------+ + | | + | | + | | + | | + | | + | XXXXXX | + | X X| + | X X| + | XXXXXX | + | | + | | + | | + | XX XX XX| + | XX XX XX| + | | + | | + | | + | | + +---------+ + */ + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0b0001111000000000, + 0b0011001100000000, + 0b0011001100000000, + 0b0011001100000000, + 0b0001111000000000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + 0x0000, + + /* MODIFIED Character 29 (0x1d): ellipsis width 9 @@ -4367,8 +4413,8 @@ static const FontDesc stellaMediumDesc = { 18, 9, 18, 0, -4, 14, - 29, - 98, + 28, + 99, stellaMedium_font_bits, nullptr, /* no encode table*/ nullptr, /* fixed width*/ diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx index df3b5e0fc..74e8ca35f 100644 --- a/src/gui/StellaSettingsDialog.cxx +++ b/src/gui/StellaSettingsDialog.cxx @@ -15,6 +15,7 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "OSystem.hxx" #include "Console.hxx" #include "EventHandler.hxx" #include "Launcher.hxx" @@ -23,23 +24,26 @@ #include "NTSCFilter.hxx" #include "PopUpWidget.hxx" #include "MessageBox.hxx" +#include "TIASurface.hxx" #include "StellaSettingsDialog.hxx" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h, Menu::AppMode mode) - : Dialog(osystem, parent, font, "Basic settings"), + int max_w, int max_h, Menu::AppMode mode) + : Dialog(osystem, parent, osystem.frameBuffer().font(), "Basic settings"), myMode(mode) { - const int VBORDER = 8; - const int HBORDER = 10; - const int INDENT = 20; - const int buttonHeight = font.getLineHeight() + 6, - lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonWidth = _font.getStringWidth("Help" + ELLIPSIS) + 32; - const int VGAP = 5; + const int buttonHeight = _font.getLineHeight() + _font.getLineHeight() / 5, + lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonWidth = _font.getStringWidth(" Help " + ELLIPSIS), + iLineHeight = instance().frameBuffer().infoFont().getLineHeight(); + + const int VBORDER = _font.getFontHeight() / 2; + const int HBORDER = fontWidth; + const int INDENT = fontWidth * 2; + const int VGAP = _font.getFontHeight() / 4; int xpos, ypos; ButtonWidget* bw = nullptr; @@ -47,55 +51,62 @@ StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& pa VariantList items; // Set real dimensions - setSize(35 * fontWidth + HBORDER * 2 + 3, 14 * (lineHeight + VGAP) + VGAP * 9 + 10 + _th, max_w, max_h); + setSize(35 * fontWidth + HBORDER * 2 + 5, + VBORDER * 2 +_th + 10 * (lineHeight + VGAP) + 3 * (iLineHeight + VGAP) + + VGAP * 12 + buttonHeight * 2, max_w, max_h); xpos = HBORDER; ypos = VBORDER + _th; - bw = new ButtonWidget(this, font, xpos, ypos, _w - HBORDER * 2 - buttonWidth - 8, buttonHeight, + bw = new ButtonWidget(this, _font, xpos, ypos, _w - HBORDER * 2 - buttonWidth - 8, buttonHeight, "Use Advanced Settings" + ELLIPSIS, kAdvancedSettings); wid.push_back(bw); - bw = new ButtonWidget(this, font, bw->getRight() + 8, ypos, buttonWidth, buttonHeight, + bw = new ButtonWidget(this, _font, bw->getRight() + 8, ypos, buttonWidth, buttonHeight, "Help" + ELLIPSIS, kHelp); wid.push_back(bw); - ypos += lineHeight + VGAP*4; + ypos += buttonHeight + VGAP * 2; - new StaticTextWidget(this, font, xpos, ypos + 1, "Global settings:"); + new StaticTextWidget(this, _font, xpos, ypos + 1, "Global settings:"); xpos += INDENT; ypos += lineHeight + VGAP; - addUIOptions(wid, xpos, ypos, font); + addUIOptions(wid, xpos, ypos); ypos += VGAP * 4; - addVideoOptions(wid, xpos, ypos, font); + addVideoOptions(wid, xpos, ypos); ypos += VGAP * 4; xpos -= INDENT; - myGameSettings = new StaticTextWidget(this, font, xpos, ypos + 1, "Game settings:"); + myGameSettings = new StaticTextWidget(this, _font, xpos, ypos + 1, "Game settings:"); xpos += INDENT; ypos += lineHeight + VGAP; - addGameOptions(wid, xpos, ypos, font); + addGameOptions(wid, xpos, ypos); // Add Defaults, OK and Cancel buttons - addDefaultsOKCancelBGroup(wid, font); + addDefaultsOKCancelBGroup(wid, _font); addToFocusList(wid); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos, const GUI::Font& font) +StellaSettingsDialog::~StellaSettingsDialog() { - const int VGAP = 4; - const int lineHeight = font.getLineHeight(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos) +{ + const int VGAP = _font.getFontHeight() / 4; + const int lineHeight = _font.getLineHeight(); VariantList items; - int pwidth = font.getStringWidth("Right bottom"); // align width with other popup + int pwidth = _font.getStringWidth("Right bottom"); // align width with other popup ypos += 1; VarList::push_back(items, "Standard", "standard"); VarList::push_back(items, "Classic", "classic"); VarList::push_back(items, "Light", "light"); - myThemePopup = new PopUpWidget(this, font, xpos, ypos, pwidth, lineHeight, items, "UI theme "); + myThemePopup = new PopUpWidget(this, _font, xpos, ypos, pwidth, lineHeight, items, "UI theme "); wid.push_back(myThemePopup); ypos += lineHeight + VGAP; @@ -106,41 +117,40 @@ void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos, VarList::push_back(items, "Right top", 2); VarList::push_back(items, "Right bottom", 3); VarList::push_back(items, "Left bottom", 4); - myPositionPopup = new PopUpWidget(this, font, xpos, ypos, pwidth, lineHeight, + myPositionPopup = new PopUpWidget(this, _font, xpos, ypos, pwidth, lineHeight, items, "Dialogs position "); wid.push_back(myPositionPopup); ypos += lineHeight + VGAP; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypos, - const GUI::Font& font) +void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypos) { - const int VGAP = 4; - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(); + const int VGAP = _font.getFontHeight() / 4; + const GUI::Font& ifont = instance().frameBuffer().infoFont(); + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(); VariantList items; // TV effects options - int swidth = font.getMaxCharWidth() * 11; + int swidth = _font.getMaxCharWidth() * 11; // TV Mode - items.clear(); VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); - int pwidth = font.getStringWidth("Right bottom"); - int lwidth = font.getStringWidth("Scanline intensity "); + int pwidth = _font.getStringWidth("Right bottom"); + int lwidth = _font.getStringWidth("Scanline intensity "); - myTVMode = new PopUpWidget(this, font, xpos, ypos, pwidth, lineHeight, + myTVMode = new PopUpWidget(this, _font, xpos, ypos, pwidth, lineHeight, items, "TV mode "); wid.push_back(myTVMode); ypos += lineHeight + VGAP; // Scanline intensity - myTVScanIntense = new SliderWidget(this, font, xpos, ypos-1, swidth, lineHeight, + myTVScanIntense = new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight, "Scanline intensity", lwidth, kScanlinesChanged, fontWidth * 3); myTVScanIntense->setMinValue(0); myTVScanIntense->setMaxValue(10); myTVScanIntense->setTickmarkIntervals(2); @@ -148,7 +158,7 @@ void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypo ypos += lineHeight + VGAP; // TV Phosphor blend level - myTVPhosLevel = new SliderWidget(this, font, xpos, ypos-1, swidth, lineHeight, + myTVPhosLevel = new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight, "Phosphor blend ", lwidth, kPhosphorChanged, fontWidth * 3); myTVPhosLevel->setMinValue(0); myTVPhosLevel->setMaxValue(10); myTVPhosLevel->setTickmarkIntervals(2); @@ -156,23 +166,25 @@ void StellaSettingsDialog::addVideoOptions(WidgetArray& wid, int& xpos, int& ypo ypos += lineHeight + VGAP; // FS overscan - myTVOverscan = new SliderWidget(this, font, xpos, ypos - 1, swidth, lineHeight, - "Overscan ", lwidth, kOverscanChanged, fontWidth * 3); + myTVOverscan = new SliderWidget(this, _font, xpos, ypos - 1, swidth, lineHeight, + "Overscan (*) ", lwidth, kOverscanChanged, fontWidth * 3); myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); myTVOverscan->setTickmarkIntervals(2); wid.push_back(myTVOverscan); ypos += lineHeight + VGAP; + + new StaticTextWidget(this, ifont, xpos, ypos + 1, "(*) Change requires launcher reboot"); + ypos += ifont.getLineHeight() + VGAP; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos, const GUI::Font& font) +void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos) { - const int VGAP = 4; - const int lineHeight = font.getLineHeight(); + const int VGAP = _font.getFontHeight() / 4; + const int lineHeight = _font.getLineHeight(); const GUI::Font& ifont = instance().frameBuffer().infoFont(); VariantList ctrls; - ctrls.clear(); VarList::push_back(ctrls, "Auto-detect", "AUTO"); VarList::push_back(ctrls, "Joystick", "JOYSTICK"); VarList::push_back(ctrls, "Paddles", "PADDLES"); @@ -184,9 +196,9 @@ void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos VarList::push_back(ctrls, "Trakball", "TRAKBALL"); VarList::push_back(ctrls, "Sega Genesis", "GENESIS"); - int pwidth = font.getStringWidth("Sega Genesis"); - myLeftPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Left port "); - myLeftPort = new PopUpWidget(this, font, myLeftPortLabel->getRight(), + int pwidth = _font.getStringWidth("Sega Genesis"); + myLeftPortLabel = new StaticTextWidget(this, _font, xpos, ypos + 1, "Left port "); + myLeftPort = new PopUpWidget(this, _font, myLeftPortLabel->getRight(), myLeftPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, "", 0, kLeftCChanged); wid.push_back(myLeftPort); ypos += lineHeight + VGAP; @@ -195,8 +207,8 @@ void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos "Sega Genesis detected"); ypos += ifont.getLineHeight() + VGAP; - myRightPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Right port "); - myRightPort = new PopUpWidget(this, font, myRightPortLabel->getRight(), + myRightPortLabel = new StaticTextWidget(this, _font, xpos, ypos + 1, "Right port "); + myRightPort = new PopUpWidget(this, _font, myRightPortLabel->getRight(), myRightPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, "", 0, kRightCChanged); wid.push_back(myRightPort); ypos += lineHeight + VGAP; @@ -291,8 +303,11 @@ void StellaSettingsDialog::saveConfig() instance().console().setProperties(myGameProperties); } - // Finally, issue a complete framebuffer re-initialization + // Finally, issue a complete framebuffer re-initialization... instance().createFrameBuffer(); + + // ... and apply potential setting changes to the TIA surface + instance().frameBuffer().tiaSurface().updateSurfaceSettings(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -409,7 +424,7 @@ void StellaSettingsDialog::switchSettingsMode() msg.push_back("proceed with the switch, click"); msg.push_back("'OK', otherwise click 'Cancel'."); - myConfirmMsg = make_unique(this, instance().frameBuffer().font(), msg, + myConfirmMsg = make_unique(this, _font, msg, _w-16, _h, kConfirmSwitchCmd, "OK", "Cancel", "Switch settings mode", false); myConfirmMsg->show(); } @@ -525,7 +540,7 @@ void StellaSettingsDialog::updateControllerStates() if(instance().hasConsole()) label = (instance().console().leftController().name()) + " detected"; else if(autoDetect) - label = ControllerDetector::detectName(image.get(), size, type, + label = ControllerDetector::detectName(image, size, type, Controller::Jack::Left, instance().settings()) + " detected"; } @@ -539,7 +554,7 @@ void StellaSettingsDialog::updateControllerStates() if(instance().hasConsole()) label = (instance().console().rightController().name()) + " detected"; else if(autoDetect) - label = ControllerDetector::detectName(image.get(), size, type, + label = ControllerDetector::detectName(image, size, type, Controller::Jack::Right, instance().settings()) + " detected"; } diff --git a/src/gui/StellaSettingsDialog.hxx b/src/gui/StellaSettingsDialog.hxx index cad6c9fbc..6f7cfe8a8 100644 --- a/src/gui/StellaSettingsDialog.hxx +++ b/src/gui/StellaSettingsDialog.hxx @@ -23,7 +23,6 @@ class PopUpWidget; #include "Props.hxx" #include "Menu.hxx" #include "Dialog.hxx" -#include "MessageBox.hxx" #if defined(RETRON77) #include "R77HelpDialog.hxx" @@ -33,23 +32,24 @@ class PopUpWidget; namespace GUI { class Font; + class MessageBox; } class StellaSettingsDialog : public Dialog { public: StellaSettingsDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h, Menu::AppMode mode); - virtual ~StellaSettingsDialog() = default; + int max_w, int max_h, Menu::AppMode mode); + virtual ~StellaSettingsDialog(); private: void loadConfig() override; void saveConfig() override; void setDefaults() override; - void addVideoOptions(WidgetArray& wid, int& xpos, int& ypos, const GUI::Font& font); - void addUIOptions(WidgetArray& wid, int& xpos, int& ypos, const GUI::Font& font); - void addGameOptions(WidgetArray& wid, int& xpos, int& ypos, const GUI::Font& font); + void addVideoOptions(WidgetArray& wid, int& xpos, int& ypos); + void addUIOptions(WidgetArray& wid, int& xpos, int& ypos); + void addGameOptions(WidgetArray& wid, int& xpos, int& ypos); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleOverscanChange(); diff --git a/src/gui/StringListWidget.cxx b/src/gui/StringListWidget.cxx index 8af0fcb80..46aed13ba 100644 --- a/src/gui/StringListWidget.cxx +++ b/src/gui/StringListWidget.cxx @@ -29,6 +29,16 @@ StringListWidget::StringListWidget(GuiObject* boss, const GUI::Font& font, _hilite(hilite) { _bgcolorlo = kDlgColor; + + + if(_font.getFontHeight() < 24) + { + _textOfs = 3; + } + else + { + _textOfs = 5; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -106,5 +116,5 @@ void StringListWidget::drawWidget(bool hilite) Common::Rect StringListWidget::getEditRect() const { const int offset = std::max(0, (_selectedItem - _currentPos) * _fontHeight); - return Common::Rect(2, 1 + offset, _w - 2, _fontHeight + offset); + return Common::Rect(_textOfs, 1 + offset, _w - _textOfs, _fontHeight + offset); } diff --git a/src/gui/StringListWidget.hxx b/src/gui/StringListWidget.hxx index 18080a7c7..10c197509 100644 --- a/src/gui/StringListWidget.hxx +++ b/src/gui/StringListWidget.hxx @@ -39,6 +39,7 @@ class StringListWidget : public ListWidget protected: bool _hilite{false}; + int _textOfs{0}; private: // Following constructors and assignment operators not supported diff --git a/src/gui/TimeMachineDialog.cxx b/src/gui/TimeMachineDialog.cxx index e5881ef01..3b591a62d 100644 --- a/src/gui/TimeMachineDialog.cxx +++ b/src/gui/TimeMachineDialog.cxx @@ -25,6 +25,7 @@ #include "StateManager.hxx" #include "RewindManager.hxx" #include "TimeLineWidget.hxx" +#include "TIASurface.hxx" #include "Console.hxx" #include "TIA.hxx" @@ -68,22 +69,23 @@ static constexpr std::array STOP = { 0b11111111111111, 0b11111111111111 }; -static constexpr std::array PLAY = { - 0b11000000000000, - 0b11110000000000, - 0b11111100000000, - 0b11111111000000, - 0b11111111110000, - 0b11111111111100, - 0b11111111111111, - 0b11111111111111, - 0b11111111111100, - 0b11111111110000, - 0b11111111000000, - 0b11111100000000, - 0b11110000000000, - 0b11000000000000 +static constexpr std::array EXIT = { + 0b01100000000110, + 0b11110000001111, + 0b11111000011111, + 0b01111100111110, + 0b00111111111100, + 0b00011111111000, + 0b00001111110000, + 0b00001111110000, + 0b00011111111000, + 0b00111111111100, + 0b01111100111110, + 0b11111000011111, + 0b11110000001111, + 0b01100000000110 }; + static constexpr std::array REWIND_ALL = { 0, 0b11000011000011, @@ -116,6 +118,22 @@ static constexpr std::array REWIND_1 = { 0b00000110001110, 0 }; +static constexpr std::array PLAYBACK = { + 0b11000000000000, + 0b11110000000000, + 0b11111100000000, + 0b11111111000000, + 0b11111111110000, + 0b11111111111100, + 0b11111111111111, + 0b11111111111111, + 0b11111111111100, + 0b11111111110000, + 0b11111111000000, + 0b11111100000000, + 0b11110000000000, + 0b11000000000000 +}; static constexpr std::array UNWIND_1 = { 0, 0b01110001100000, @@ -196,7 +214,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, // Set real dimensions _w = width; // Parent determines our width (based on window size) - _h = V_BORDER * 2 + rowHeight + buttonHeight + 2; + _h = V_BORDER * 2 + rowHeight + std::max(buttonHeight + 2, rowHeight); this->clearFlags(Widget::FLAG_CLEARBG); // does only work combined with blending (0..100)! this->clearFlags(Widget::FLAG_BORDER); @@ -221,9 +239,10 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, ypos += rowHeight; // Add time info - myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos + 3, "00:00.00", TextAlign::Left, kBGColor); + int ypos_s = ypos + (buttonHeight - font.getFontHeight() + 1) / 2; // align to button vertical center + myCurrentTimeWidget = new StaticTextWidget(this, font, xpos, ypos_s, "00:00.00", TextAlign::Left, kBGColor); myCurrentTimeWidget->setTextColor(kColorInfo); - myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("00:00.00"), ypos + 3, + myLastTimeWidget = new StaticTextWidget(this, font, _w - H_BORDER - font.getStringWidth("00:00.00"), ypos_s, "00:00.00", TextAlign::Right, kBGColor); myLastTimeWidget->setTextColor(kColorInfo); xpos = myCurrentTimeWidget->getRight() + BUTTON_GAP * 4; @@ -233,8 +252,8 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, STOP.data(), BUTTON_W, BUTTON_H, kToggle); xpos += buttonWidth + BUTTON_GAP; - myPlayWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, - PLAY.data(), BUTTON_W, BUTTON_H, kPlay); + myExitWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, + EXIT.data(), BUTTON_W, BUTTON_H, kExit); xpos += buttonWidth + BUTTON_GAP * 4; myRewindAllWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, @@ -245,6 +264,10 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, REWIND_1.data(), BUTTON_W, BUTTON_H, kRewind1, true); xpos += buttonWidth + BUTTON_GAP; + myPlayBackWidget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, + PLAYBACK.data(), BUTTON_W, BUTTON_H, kPlayBack); + xpos += buttonWidth + BUTTON_GAP; + myUnwind1Widget = new ButtonWidget(this, font, xpos, ypos, buttonWidth, buttonHeight, UNWIND_1.data(), BUTTON_W, BUTTON_H, kUnwind1, true); xpos += buttonWidth + BUTTON_GAP; @@ -262,7 +285,7 @@ TimeMachineDialog::TimeMachineDialog(OSystem& osystem, DialogContainer& parent, xpos = myLoadAllWidget->getRight() + BUTTON_GAP * 4; // Add message - myMessageWidget = new StaticTextWidget(this, font, xpos, ypos + 3, + myMessageWidget = new StaticTextWidget(this, font, xpos, ypos_s, " ", TextAlign::Left, kBGColor); myMessageWidget->setTextColor(kColorInfo); } @@ -293,37 +316,70 @@ void TimeMachineDialog::loadConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TimeMachineDialog::handleKeyDown(StellaKey key, StellaMod mod, bool repeated) { - // The following 'Alt' shortcuts duplicate the shortcuts in EventHandler - // It is best to keep them the same, so changes in EventHandler mean we - // need to update the logic here too - if(StellaModTest::isAlt(mod)) + // The following shortcuts duplicate the shortcuts in EventHandler + + Event::Type event = instance().eventHandler().eventForKey(EventMode::kEmulationMode, key, mod); + + switch (event) { - switch(key) - { - case KBDK_LEFT: // Alt-left(-shift) rewinds 1(10) states - handleCommand(nullptr, StellaModTest::isShift(mod) ? kRewind10 : kRewind1, 0, 0); - break; + case Event::Rewind1Menu: + handleCommand(nullptr, kRewind1, 0, 0); + break; - case KBDK_RIGHT: // Alt-right(-shift) unwinds 1(10) states - handleCommand(nullptr, StellaModTest::isShift(mod) ? kUnwind10 : kUnwind1, 0, 0); - break; + case Event::Rewind10Menu: + handleCommand(nullptr, kRewind10, 0, 0); + break; - case KBDK_DOWN: // Alt-down rewinds to start of list - handleCommand(nullptr, kRewindAll, 0, 0); - break; + case Event::RewindAllMenu: + handleCommand(nullptr, kRewindAll, 0, 0); + break; - case KBDK_UP: // Alt-up rewinds to end of list - handleCommand(nullptr, kUnwindAll, 0, 0); - break; + case Event::Unwind1Menu: + handleCommand(nullptr, kUnwind1, 0, 0); + break; - default: - Dialog::handleKeyDown(key, mod); - } + case Event::Unwind10Menu: + handleCommand(nullptr, kUnwind10, 0, 0); + break; + + case Event::UnwindAllMenu: + handleCommand(nullptr, kUnwindAll, 0, 0); + break; + + case Event::TakeSnapshot: + if (!repeated) + handleCommand(nullptr, kSnapShot, 0, 0); + break; + + case Event::ExitMode: + handleCommand(nullptr, kExit, 0, 0); + break; + + default: + Dialog::handleKeyDown(key, mod, repeated); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TimeMachineDialog::handleKeyUp(StellaKey key, StellaMod mod) +{ + // The following shortcuts duplicate the shortcuts in EventHandler + // Note: mode switches must happen in key UP + + Event::Type event = instance().eventHandler().eventForKey(EventMode::kEmulationMode, key, mod); + + switch (event) + { + case Event::TogglePlayBackMode: + handleCommand(nullptr, kPlayBack, 0, 0); + break; + + default: + if (key == KBDK_SPACE) + handleCommand(nullptr, kPlayBack, 0, 0); + else + Dialog::handleKeyUp(key, mod); } - else if(key == KBDK_SPACE || key == KBDK_ESCAPE) - handleCommand(nullptr, kPlay, 0, 0); - else - Dialog::handleKeyDown(key, mod); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -345,7 +401,7 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd, handleToggle(); break; - case kPlay: + case kExit: instance().eventHandler().leaveMenuMode(); break; @@ -361,6 +417,10 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd, handleWinds(-1000); break; + case kPlayBack: + instance().eventHandler().enterPlayBackMode(); + break; + case kUnwind1: handleWinds(1); break; @@ -382,6 +442,10 @@ void TimeMachineDialog::handleCommand(CommandSender* sender, int cmd, initBar(); break; + case kSnapShot: + instance().frameBuffer().tiaSurface().saveSnapShot(); + break; + default: Dialog::handleCommand(sender, cmd, data, 0); } @@ -459,6 +523,7 @@ void TimeMachineDialog::handleWinds(Int32 numWinds) // Enable/disable buttons myRewindAllWidget->setEnabled(!r.atFirst()); myRewind1Widget->setEnabled(!r.atFirst()); + myPlayBackWidget->setEnabled(!r.atLast()); myUnwindAllWidget->setEnabled(!r.atLast()); myUnwind1Widget->setEnabled(!r.atLast()); mySaveAllWidget->setEnabled(r.getLastIdx() != 0); diff --git a/src/gui/TimeMachineDialog.hxx b/src/gui/TimeMachineDialog.hxx index 4d94f006f..283249514 100644 --- a/src/gui/TimeMachineDialog.hxx +++ b/src/gui/TimeMachineDialog.hxx @@ -38,6 +38,7 @@ class TimeMachineDialog : public Dialog private: void loadConfig() override; void handleKeyDown(StellaKey key, StellaMod mod, bool repeated) override; + void handleKeyUp(StellaKey key, StellaMod mod) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; /** initialize timeline bar */ @@ -58,21 +59,24 @@ class TimeMachineDialog : public Dialog { kTimeline = 'TMtl', kToggle = 'TMtg', - kPlay = 'TMpl', + kExit = 'TMex', + kPlayBack = 'TMpb', kRewindAll = 'TMra', kRewind10 = 'TMr1', kRewind1 = 'TMre', kUnwindAll = 'TMua', kUnwind10 = 'TMu1', kUnwind1 = 'TMun', - kSaveAll = 'TMsv', - kLoadAll = 'TMld', + kSaveAll = 'TMsv', + kLoadAll = 'TMld', + kSnapShot = 'TMsn', }; TimeLineWidget* myTimeline{nullptr}; ButtonWidget* myToggleWidget{nullptr}; - ButtonWidget* myPlayWidget{nullptr}; + ButtonWidget* myExitWidget{ nullptr }; + ButtonWidget* myPlayBackWidget{nullptr}; ButtonWidget* myRewindAllWidget{nullptr}; ButtonWidget* myRewind1Widget{nullptr}; ButtonWidget* myUnwind1Widget{nullptr}; diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 0d601f168..1b64d73f2 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -30,6 +30,7 @@ #include "TabWidget.hxx" #include "Widget.hxx" #include "Font.hxx" +#include "StellaMediumFont.hxx" #include "LauncherDialog.hxx" #ifdef DEBUGGER_SUPPORT #include "DebuggerDialog.hxx" @@ -48,12 +49,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), - buttonHeight = font.getLineHeight() + 4; - - const int VBORDER = 8; - const int HBORDER = 10; - const int INDENT = 16; - const int V_GAP = 4; + buttonHeight = font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; int xpos, ypos, tabID; int lwidth, pwidth, bwidth; WidgetArray wid; @@ -61,11 +61,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, const Common::Size& ds = instance().frameBuffer().desktopSize(); // Set real dimensions - setSize(64 * fontWidth + HBORDER * 2, 11 * (lineHeight + V_GAP) + V_GAP * 9 + VBORDER + _th, + setSize(64 * fontWidth + HBORDER * 2, + _th + VGAP * 3 + lineHeight + 10 * (lineHeight + VGAP) + VGAP * 2 + buttonHeight + VBORDER * 3, max_w, max_h); // The tab widget - myTab = new TabWidget(this, font, 2, 4 + _th, _w - 2*2, _h - _th - buttonHeight - 20); + myTab = new TabWidget(this, font, 2, VGAP + _th, + _w - 2*2, + _h - _th - VGAP - buttonHeight - VBORDER * 2); addTabWidget(myTab); ////////////////////////////////////////////////////////// @@ -82,17 +85,34 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, VarList::push_back(items, "Standard", "standard"); VarList::push_back(items, "Classic", "classic"); VarList::push_back(items, "Light", "light"); + VarList::push_back(items, "Dark", "dark"); myPalettePopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Theme ", lwidth); wid.push_back(myPalettePopup); + ypos += lineHeight + VGAP; + + + // Dialog font + items.clear(); + VarList::push_back(items, "Small", "small"); // 8x13 + VarList::push_back(items, "Low Medium", "low_medium"); // 9x15 + VarList::push_back(items, "Medium", "medium"); // 9x18 + VarList::push_back(items, "Large (10pt)", "large"); // 10x20 + VarList::push_back(items, "Large (12pt)", "large12"); // 12x24 + VarList::push_back(items, "Large (14pt)", "large14"); // 14x28 + VarList::push_back(items, "Large (16pt)", "large16"); // 16x32 + myDialogFontPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, + items, "Dialogs font (*)", lwidth, kDialogFont); + wid.push_back(myDialogFontPopup); // Enable HiDPI mode - myHidpiWidget = new CheckboxWidget(myTab, font, myPalettePopup->getRight() + 40, - ypos, "HiDPI mode (*)"); + xpos = myDialogFontPopup->getRight() + fontWidth * 5; + myHidpiWidget = new CheckboxWidget(myTab, font, xpos, + ypos + 1, "HiDPI mode (*)"); wid.push_back(myHidpiWidget); - ypos += lineHeight + V_GAP; // Dialog position + xpos = HBORDER; ypos += lineHeight + VGAP; items.clear(); VarList::push_back(items, "Centered", 0); VarList::push_back(items, "Left top", 1); @@ -100,16 +120,16 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, VarList::push_back(items, "Right bottom", 3); VarList::push_back(items, "Left bottom", 4); myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "Dialogs position ", lwidth); + items, "Dialogs position", lwidth); wid.push_back(myPositionPopup); - ypos += lineHeight + V_GAP * 2; - // Confirm dialog when exiting emulation - myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation"); - wid.push_back(myConfirmExitWidget); - ypos += lineHeight + V_GAP * 3; + // Center window (in windowed mode) + xpos = myHidpiWidget->getLeft(); + myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows"); + wid.push_back(myCenter); // Delay between quick-selecting characters in ListWidget + xpos = HBORDER; ypos += lineHeight + VGAP * 4; int swidth = myPalettePopup->getWidth() - lwidth; myListDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, "List input delay ", 0, kListDelay, @@ -119,7 +139,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myListDelaySlider->setStepValue(50); myListDelaySlider->setTickmarkIntervals(5); wid.push_back(myListDelaySlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; // Number of lines a mouse wheel will scroll myWheelLinesSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, @@ -129,7 +149,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myWheelLinesSlider->setMaxValue(10); myWheelLinesSlider->setTickmarkIntervals(3); wid.push_back(myWheelLinesSlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; // Mouse double click speed myDoubleClickSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, @@ -140,7 +160,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myDoubleClickSlider->setStepValue(50); myDoubleClickSlider->setTickmarkIntervals(8); wid.push_back(myDoubleClickSlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; // Initial delay before controller input will start repeating myControllerDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, @@ -151,7 +171,7 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, myControllerDelaySlider->setStepValue(100); myControllerDelaySlider->setTickmarkIntervals(4); wid.push_back(myControllerDelaySlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; // Controller repeat rate myControllerRateSlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight, @@ -164,10 +184,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.push_back(myControllerRateSlider); // Add message concerning usage - ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10; - lwidth = ifont.getStringWidth("(*) Change requires application restart"); - new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight, - "(*) Change requires application restart"); + ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER; + lwidth = ifont.getStringWidth("(*) Change requires an application restart"); + new StaticTextWidget(myTab, ifont, xpos, ypos, + std::min(lwidth, _w - HBORDER * 2), ifont.getFontHeight(), + "(*) Change requires an application restart"); // Add items for tab 0 addToFocusList(wid, myTab, tabID); @@ -185,68 +206,74 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight, "ROM path" + ELLIPSIS, kChooseRomDirCmd); wid.push_back(romButton); - xpos = romButton->getRight() + 8; - myRomPath = new EditTextWidget(myTab, font, xpos, ypos + 1, + xpos = romButton->getRight() + fontWidth; + myRomPath = new EditTextWidget(myTab, font, xpos, ypos + (buttonHeight - lineHeight) / 2 - 1, _w - xpos - HBORDER - 2, lineHeight, ""); wid.push_back(myRomPath); + + xpos = _w - HBORDER - font.getStringWidth("Follow Launcher path") - CheckboxWidget::prefixSize(font) - 1; + ypos += lineHeight + VGAP * 2; + myFollowLauncherWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Follow Launcher path"); + wid.push_back(myFollowLauncherWidget); + xpos = HBORDER; - ypos += lineHeight + V_GAP * 4; + ypos += VGAP * 2; // Launcher width and height myLauncherWidthSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher width ", - lwidth, kLauncherSize, 6 * fontWidth, "px"); - myLauncherWidthSlider->setMinValue(FBMinimum::Width); + lwidth, 0, 6 * fontWidth, "px"); myLauncherWidthSlider->setMaxValue(ds.w); myLauncherWidthSlider->setStepValue(10); - // one tickmark every ~100 pixel - myLauncherWidthSlider->setTickmarkIntervals((ds.w - FBMinimum::Width + 50) / 100); wid.push_back(myLauncherWidthSlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; myLauncherHeightSlider = new SliderWidget(myTab, font, xpos, ypos, "Launcher height ", - lwidth, kLauncherSize, 6 * fontWidth, "px"); - myLauncherHeightSlider->setMinValue(FBMinimum::Height); + lwidth, 0, 6 * fontWidth, "px"); myLauncherHeightSlider->setMaxValue(ds.h); myLauncherHeightSlider->setStepValue(10); - // one tickmark every ~100 pixel - myLauncherHeightSlider->setTickmarkIntervals((ds.h - FBMinimum::Height + 50) / 100); wid.push_back(myLauncherHeightSlider); - ypos += lineHeight + V_GAP; + ypos += lineHeight + VGAP; // Launcher font pwidth = font.getStringWidth("2x (1000x760)"); items.clear(); - VarList::push_back(items, "Small", "small"); - VarList::push_back(items, "Medium", "medium"); - VarList::push_back(items, "Large", "large"); + VarList::push_back(items, "Small", "small"); // 8x13 + VarList::push_back(items, "Low Medium", "low_medium"); // 9x15 + VarList::push_back(items, "Medium", "medium"); // 9x18 + VarList::push_back(items, "Large (10pt)", "large"); // 10x20 + VarList::push_back(items, "Large (12pt)", "large12"); // 12x24 + VarList::push_back(items, "Large (14pt)", "large14"); // 14x28 + VarList::push_back(items, "Large (16pt)", "large16"); // 16x32 myLauncherFontPopup = new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items, "Launcher font ", lwidth); wid.push_back(myLauncherFontPopup); - ypos += lineHeight + V_GAP * 4; + ypos += lineHeight + VGAP * 4; // ROM launcher info/snapshot viewer - items.clear(); - VarList::push_back(items, "Off", "0"); - VarList::push_back(items, "1x (640x480) ", "1"); - VarList::push_back(items, "2x (1000x760)", "2"); - myRomViewerPopup = - new PopUpWidget(myTab, font, xpos, ypos + 1, pwidth, lineHeight, items, - "ROM info viewer ", lwidth, kRomViewer); - wid.push_back(myRomViewerPopup); - ypos += lineHeight + V_GAP; + myRomViewerSize = new SliderWidget(myTab, font, xpos, ypos, "ROM info width ", + lwidth, kRomViewer, 6 * fontWidth, "% "); + myRomViewerSize->setMinValue(0); + myRomViewerSize->setMaxValue(100); + myRomViewerSize->setStepValue(2); + // set tickmarks every ~20% + myRomViewerSize->setTickmarkIntervals((myRomViewerSize->getMaxValue() - myRomViewerSize->getMinValue()) / 20); + + wid.push_back(myRomViewerSize); + ypos += lineHeight + VGAP; // Snapshot path (load files) xpos = HBORDER + INDENT; - bwidth = font.getStringWidth("Image path" + ELLIPSIS) + 20 + 1; + bwidth = font.getStringWidth("Image path" + ELLIPSIS) + fontWidth * 2 + 1; myOpenBrowserButton = new ButtonWidget(myTab, font, xpos, ypos, bwidth, buttonHeight, "Image path" + ELLIPSIS, kChooseSnapLoadDirCmd); wid.push_back(myOpenBrowserButton); - mySnapLoadPath = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos + 1, + mySnapLoadPath = new EditTextWidget(myTab, font, HBORDER + lwidth, + ypos + (buttonHeight - lineHeight) / 2 - 1, _w - lwidth - HBORDER * 2 - 2, lineHeight, ""); wid.push_back(mySnapLoadPath); - ypos += lineHeight + V_GAP * 4; + ypos += lineHeight + VGAP * 4; // Exit to Launcher xpos = HBORDER; @@ -255,10 +282,11 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, // Add message concerning usage xpos = HBORDER; - ypos = myTab->getHeight() - 5 - fontHeight - ifont.getFontHeight() - 10; - lwidth = ifont.getStringWidth("(*) Changes require application restart"); - new StaticTextWidget(myTab, ifont, xpos, ypos, std::min(lwidth, _w - 20), fontHeight, - "(*) Changes require application restart"); + ypos = myTab->getHeight() - fontHeight - ifont.getFontHeight() - VGAP - VBORDER; + lwidth = ifont.getStringWidth("(*) Changes require an application restart"); + new StaticTextWidget(myTab, ifont, xpos, ypos, + std::min(lwidth, _w - HBORDER * 2), ifont.getFontHeight(), + "(*) Changes require an application restart"); // Add items for tab 1 addToFocusList(wid, myTab, tabID); @@ -277,6 +305,10 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent, wid.clear(); addDefaultsOKCancelBGroup(wid, font); addBGroupToFocusList(wid); + +#ifndef WINDOWED_SUPPORT + myCenter->clearFlags(Widget::FLAG_ENABLED); +#endif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -304,13 +336,17 @@ void UIDialog::loadConfig() myLauncherWidthSlider->setValue(w); myLauncherHeightSlider->setValue(h); + // Follow Launcher path + myFollowLauncherWidget->setState(settings.getBool("followlauncher")); + // Launcher font - const string& font = settings.getString("launcherfont"); - myLauncherFontPopup->setSelected(font, "medium"); + const string& launcherFont = settings.getString("launcherfont"); + myLauncherFontPopup->setSelected(launcherFont, "medium"); // ROM launcher info viewer - const string& viewer = settings.getString("romviewer"); - myRomViewerPopup->setSelected(viewer, "0"); + float zoom = instance().settings().getFloat("romviewer"); + int percentage = zoom * TIAConstants::viewableWidth * 100 / w; + myRomViewerSize->setValue(percentage); // ROM launcher info viewer image path mySnapLoadPath->setText(settings.getString("snaploaddir")); @@ -323,6 +359,10 @@ void UIDialog::loadConfig() const string& pal = settings.getString("uipalette"); myPalettePopup->setSelected(pal, "standard"); + // Dialog font + const string& dialogFont = settings.getString("dialogfont"); + myDialogFontPopup->setSelected(dialogFont, "medium"); + // Enable HiDPI mode if (!instance().frameBuffer().hidpiAllowed()) { @@ -334,12 +374,12 @@ void UIDialog::loadConfig() myHidpiWidget->setState(settings.getBool("hidpi")); } - // Confirm dialog when exiting emulation - myConfirmExitWidget->setState(settings.getBool("confirmexit")); - // Dialog position myPositionPopup->setSelected(settings.getString("dialogpos"), "0"); + // Center window + myCenter->setState(settings.getBool("center")); + // Listwidget quick delay int delay = settings.getInt("listdelay"); myListDelaySlider->setValue(delay); @@ -360,6 +400,7 @@ void UIDialog::loadConfig() int cr = settings.getInt("ctrlrate"); myControllerRateSlider->setValue(cr); + handleLauncherSize(); handleRomViewer(); myTab->loadConfig(); @@ -373,6 +414,9 @@ void UIDialog::saveConfig() // ROM path settings.setValue("romdir", myRomPath->getText()); + // Follow Launcher path + settings.setValue("followlauncher", myFollowLauncherWidget->getState()); + // Launcher size settings.setValue("launcherres", Common::Size(myLauncherWidthSlider->getValue(), @@ -380,11 +424,12 @@ void UIDialog::saveConfig() // Launcher font settings.setValue("launcherfont", - myLauncherFontPopup->getSelectedTag().toString()); + myLauncherFontPopup->getSelectedTag().toString()); // ROM launcher info viewer - settings.setValue("romviewer", - myRomViewerPopup->getSelectedTag().toString()); + int w = myLauncherWidthSlider->getValue(); + float zoom = myRomViewerSize->getValue() * w / 100.F / TIAConstants::viewableWidth; + settings.setValue("romviewer", zoom); // ROM launcher info viewer image path settings.setValue("snaploaddir", mySnapLoadPath->getText()); @@ -397,14 +442,18 @@ void UIDialog::saveConfig() myPalettePopup->getSelectedTag().toString()); instance().frameBuffer().setUIPalette(); + // Dialog font + settings.setValue("dialogfont", + myDialogFontPopup->getSelectedTag().toString()); + // Enable HiDPI mode settings.setValue("hidpi", myHidpiWidget->getState()); // Dialog position settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString()); - // Confirm dialog when exiting emulation - settings.setValue("confirmexit", myConfirmExitWidget->getState()); + // Center window + settings.setValue("center", myCenter->getState()); // Listwidget quick delay settings.setValue("listdelay", myListDelaySlider->getValue()); @@ -438,9 +487,10 @@ void UIDialog::setDefaults() { case 0: // Misc. options myPalettePopup->setSelected("standard"); + myDialogFontPopup->setSelected("medium", ""); myHidpiWidget->setState(false); myPositionPopup->setSelected("0"); - myConfirmExitWidget->setState(false); + myCenter->setState(false); myListDelaySlider->setValue(300); myWheelLinesSlider->setValue(4); myDoubleClickSlider->setValue(500); @@ -456,8 +506,8 @@ void UIDialog::setDefaults() myLauncherWidthSlider->setValue(w); myLauncherHeightSlider->setValue(h); myLauncherFontPopup->setSelected("medium", ""); - myRomViewerPopup->setSelected("1", ""); - mySnapLoadPath->setText(instance().defaultLoadDir()); + myRomViewerSize->setValue(35); + mySnapLoadPath->setText(instance().defaultLoadDir().getShortPath()); myLauncherExitWidget->setState(false); break; } @@ -472,16 +522,23 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) switch(cmd) { case GuiObject::kOKCmd: + { + bool inform = myIsGlobal && + myRomPath->getText() != instance().settings().getString("romdir"); saveConfig(); close(); - if(myIsGlobal) // Let the boss know romdir has changed + if(inform) // Let the boss know romdir has changed sendCommand(LauncherDialog::kRomDirChosenCmd, 0, 0); break; - + } case GuiObject::kDefaultsCmd: setDefaults(); break; + case kDialogFont: + handleLauncherSize(); + break; + case kListDelay: if(myListDelaySlider->getValue() == 0) { @@ -530,7 +587,6 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) myRomPath->setText(myBrowser->getResult().getShortPath()); break; - case kLauncherSize: case kRomViewer: handleRomViewer(); break; @@ -553,30 +609,88 @@ void UIDialog::handleCommand(CommandSender* sender, int cmd, int data, int id) } } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void UIDialog::handleLauncherSize() +{ + // Determine minimal launcher sizebased on the default font + // So what fits with default font should fit for any font. + FontDesc fd = instance().frameBuffer().getFontDesc(myDialogFontPopup->getSelectedTag().toString()); + int w = std::max(FBMinimum::Width, FBMinimum::Width * fd.maxwidth / GUI::stellaMediumDesc.maxwidth); + int h = std::max(FBMinimum::Height, FBMinimum::Height * fd.height / GUI::stellaMediumDesc.height); + const Common::Size& ds = instance().frameBuffer().desktopSize(); + + myLauncherWidthSlider->setMinValue(w); + if(myLauncherWidthSlider->getValue() < myLauncherWidthSlider->getMinValue()) + myLauncherWidthSlider->setValue(w); + // one tickmark every ~100 pixel + myLauncherWidthSlider->setTickmarkIntervals((ds.w - w + 67) / 100); + + myLauncherHeightSlider->setMinValue(h); + if(myLauncherHeightSlider->getValue() < myLauncherHeightSlider->getMinValue()) + myLauncherHeightSlider->setValue(h); + // one tickmark every ~100 pixel + myLauncherHeightSlider->setTickmarkIntervals((ds.h - h + 67) / 100); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +/*void UIDialog::handleLauncherSize() +// an attempt to limit the minimal and maximal ROM info percentages +// whiche became too complex +{ + string launcherFont = myLauncherFontPopup->getSelectedTag().toString(); + int fwidth, fheight; + if(launcherFont == "small") + { + fwidth = GUI::consoleDesc.maxwidth; + fheight = GUI::consoleDesc.height; + } + else if(launcherFont == "medium") + { + fwidth = GUI::stellaMediumDesc.maxwidth; + fheight = GUI::stellaMediumDesc.height; + } + else + { + fwidth = GUI::stellaLargeDesc.maxwidth; + fheight = GUI::stellaLargeDesc.height; + } + int minInfoWidth = instance().frameBuffer().smallFont().getMaxCharWidth() * 20 + 16; + int minInfoHeight = instance().frameBuffer().smallFont().getLineHeight() * 8 + 16; + int minLauncherWidth = fwidth * 20 + 64; + int w = myLauncherWidthSlider->getValue(); + int h = myLauncherHeightSlider->getValue(); + int size = std::max(minInfoWidth * 100.F / w, minInfoHeight * 100.F / h); + + myRomViewerSize->setMinValue(size); + myRomViewerSize->setMaxValue(100 - minLauncherWidth * 100.F / w); + // set tickmarks every ~10% + myRomViewerSize->setTickmarkIntervals((myRomViewerSize->getMaxValue() - myRomViewerSize->getMinValue()) / 10); + + size = myRomViewerSize->getValue(); + size = std::max(size, myRomViewerSize->getMinValue()); + size = std::min(size, myRomViewerSize->getMaxValue()); + + myRomViewerSize->setValue(size); +}*/ + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void UIDialog::handleRomViewer() { - int size = myRomViewerPopup->getSelected(); - bool enable = myRomViewerPopup->getSelectedName() != "Off"; - VariantList items; + int size = myRomViewerSize->getValue(); + bool enable = size > myRomViewerSize->getMinValue(); + if(enable) + { + myRomViewerSize->setValueLabel(size); + myRomViewerSize->setValueUnit("%"); + } + else + { + myRomViewerSize->setValueLabel("Off"); + myRomViewerSize->setValueUnit(""); + } myOpenBrowserButton->setEnabled(enable); mySnapLoadPath->setEnabled(enable); - - items.clear(); - VarList::push_back(items, "Off", "0"); - VarList::push_back(items, "1x (640x480) ", "1"); - if(myLauncherWidthSlider->getValue() >= 1000 && - myLauncherHeightSlider->getValue() >= 760) - { - VarList::push_back(items, "2x (1000x760)", "2"); - } - else if (size == 2) - { - myRomViewerPopup->setSelected(1); - } - - myRomViewerPopup->addItems(items); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 9774c2290..6ed1c655f 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -33,17 +33,18 @@ class UIDialog : public Dialog, public CommandSender void setDefaults() override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void handleLauncherSize(); void handleRomViewer(); void createBrowser(const string& title); private: enum { + kDialogFont = 'UIDf', kListDelay = 'UILd', kMouseWheel = 'UIMw', kControllerDelay = 'UIcd', kChooseRomDirCmd = 'LOrm', // rom select - kLauncherSize = 'UIls', kRomViewer = 'UIRv', kChooseSnapLoadDirCmd = 'UIsl', // snapshot dir (load files) kSnapLoadDirChosenCmd = 'UIsc' // snap chosen (load files) @@ -54,19 +55,21 @@ class UIDialog : public Dialog, public CommandSender // Launcher options EditTextWidget* myRomPath{nullptr}; + CheckboxWidget* myFollowLauncherWidget{nullptr}; SliderWidget* myLauncherWidthSlider{nullptr}; SliderWidget* myLauncherHeightSlider{nullptr}; PopUpWidget* myLauncherFontPopup{nullptr}; - PopUpWidget* myRomViewerPopup{nullptr}; + SliderWidget* myRomViewerSize{nullptr}; ButtonWidget* myOpenBrowserButton{nullptr}; EditTextWidget* mySnapLoadPath{nullptr}; CheckboxWidget* myLauncherExitWidget{nullptr}; // Misc options PopUpWidget* myPalettePopup{nullptr}; + PopUpWidget* myDialogFontPopup{nullptr}; CheckboxWidget* myHidpiWidget{nullptr}; PopUpWidget* myPositionPopup{nullptr}; - CheckboxWidget* myConfirmExitWidget{nullptr}; + CheckboxWidget* myCenter{nullptr}; SliderWidget* myListDelaySlider{nullptr}; SliderWidget* myWheelLinesSlider{nullptr}; SliderWidget* myControllerRateSlider{nullptr}; diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx new file mode 100644 index 000000000..edb40c7bb --- /dev/null +++ b/src/gui/VideoAudioDialog.cxx @@ -0,0 +1,1106 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include + +#include "bspf.hxx" +#include "Base.hxx" +#include "Control.hxx" +#include "Cart.hxx" +#include "CartDPC.hxx" +#include "Dialog.hxx" +#include "Menu.hxx" +#include "OSystem.hxx" +#include "EditTextWidget.hxx" +#include "PopUpWidget.hxx" +#include "ColorWidget.hxx" +#include "Console.hxx" +#include "PaletteHandler.hxx" +#include "TIA.hxx" +#include "Settings.hxx" +#include "Sound.hxx" +#include "AudioSettings.hxx" +#include "Widget.hxx" +#include "Font.hxx" +#include "TabWidget.hxx" +#include "NTSCFilter.hxx" +#include "TIASurface.hxx" + +#include "VideoAudioDialog.hxx" + +#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ + myTV ## obj = \ + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, \ + desc, lwidth, cmd, fontWidth*4, "%"); \ + myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ + myTV ## obj->setStepValue(1); \ + myTV ## obj->setTickmarkIntervals(2); \ + wid.push_back(myTV ## obj); \ + ypos += lineHeight + VGAP; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent, + const GUI::Font& font, int max_w, int max_h) + : Dialog(osystem, parent, font, "Video & Audio settings") +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int xpos, ypos; + + // Set real dimensions + setSize(44 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2, + _th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3, + max_w, max_h); + + // The tab widget + xpos = 2; ypos = VGAP; + myTab = new TabWidget(this, font, xpos, ypos + _th, + _w - 2*xpos, + _h - _th - VGAP - buttonHeight - VBORDER * 2); + addTabWidget(myTab); + + addDisplayTab(); + addPaletteTab(); + addTVEffectsTab(); + addAudioTab(); + + // Add Defaults, OK and Cancel buttons + WidgetArray wid; + addDefaultsOKCancelBGroup(wid, _font); + addBGroupToFocusList(wid); + + // Activate the first tab + myTab->setActiveTab(0); + + // Disable certain functions when we know they aren't present +#ifndef WINDOWED_SUPPORT + myFullscreen->clearFlags(Widget::FLAG_ENABLED); + myUseStretch->clearFlags(Widget::FLAG_ENABLED); + myTVOverscan->clearFlags(Widget::FLAG_ENABLED); +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addDisplayTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int lwidth = _font.getStringWidth("V-Size adjust "), + pwidth = _font.getStringWidth("OpenGLES2"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Display ", TabWidget::AUTO_WIDTH); + + // Video renderer + myRenderer = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + instance().frameBuffer().supportedRenderers(), + "Renderer ", lwidth); + wid.push_back(myRenderer); + const int swidth = myRenderer->getWidth() - lwidth; + ypos += lineHeight + VGAP; + + // TIA interpolation + myTIAInterpolate = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Interpolation "); + wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP * 4; + + // TIA zoom levels (will be dynamically filled later) + myTIAZoom = new SliderWidget(myTab, _font, xpos, ypos - 1, swidth, lineHeight, + "Zoom ", lwidth, 0, fontWidth * 4, "%"); + myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); + wid.push_back(myTIAZoom); + ypos += lineHeight + VGAP; + + // Fullscreen + myFullscreen = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); + wid.push_back(myFullscreen); + ypos += lineHeight + VGAP; + + // FS stretch + myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch"); + wid.push_back(myUseStretch); + +#ifdef ADAPTABLE_REFRESH_SUPPORT + // Adapt refresh rate + ypos += lineHeight + VGAP; + myRefreshAdapt = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Adapt display refresh rate"); + wid.push_back(myRefreshAdapt); +#else + myRefreshAdapt = nullptr; +#endif + + // FS overscan + ypos += lineHeight + VGAP; + myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight, + "Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%"); + myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); + myTVOverscan->setTickmarkIntervals(2); + wid.push_back(myTVOverscan); + + // Vertical size + ypos += lineHeight + VGAP; + myVSizeAdjust = + new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, + "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); + myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); + myVSizeAdjust->setTickmarkIntervals(2); + wid.push_back(myVSizeAdjust); + + + // Add items for tab 0 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addPaletteTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = fontWidth * 2; + const int VGAP = fontHeight / 4; + const int lwidth = _font.getStringWidth(" NTSC phase "); + const int pwidth = _font.getStringWidth("Standard"); + int xpos = HBORDER, + ypos = VBORDER; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Palettes ", TabWidget::AUTO_WIDTH); + + // TIA Palette + items.clear(); + VarList::push_back(items, "Standard", PaletteHandler::SETTING_STANDARD); + VarList::push_back(items, "z26", PaletteHandler::SETTING_Z26); + if (instance().checkUserPalette()) + VarList::push_back(items, "User", PaletteHandler::SETTING_USER); + VarList::push_back(items, "Custom", PaletteHandler::SETTING_CUSTOM); + myTIAPalette = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, + lineHeight, items, "Palette ", lwidth, kPaletteChanged); + wid.push_back(myTIAPalette); + ypos += lineHeight + VGAP; + + const int swidth = myTIAPalette->getWidth() - lwidth; + const int plWidth = _font.getStringWidth("NTSC phase "); + const int pswidth = swidth - INDENT + lwidth - plWidth; + + myPhaseShiftNtsc = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5); + myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftNtsc->setTickmarkIntervals(4); + wid.push_back(myPhaseShiftNtsc); + ypos += lineHeight + VGAP; + + myPhaseShiftPal = + new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight, + "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5); + myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10); + myPhaseShiftPal->setTickmarkIntervals(4); + wid.push_back(myPhaseShiftPal); + ypos += lineHeight + VGAP; + + CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated) + CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated) + + // The resulting palette + xpos = myPhaseShiftNtsc->getRight() + fontWidth * 2; + addPalette(xpos, VBORDER, _w - 2 * 2 - HBORDER - xpos, + myTVGamma->getBottom() - myTIAPalette->getTop()); + + // Add items for tab 2 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addTVEffectsTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2; + const int VGAP = fontHeight / 4; + int xpos = HBORDER, + ypos = VBORDER; + const int lwidth = _font.getStringWidth("Saturation "); + const int pwidth = _font.getStringWidth("Bad adjust "); + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" TV Effects ", TabWidget::AUTO_WIDTH); + + items.clear(); + VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); + VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); + VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); + VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); + VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); + VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); + myTVMode = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, + items, "TV mode ", 0, kTVModeChanged); + wid.push_back(myTVMode); + ypos += lineHeight + VGAP; + + // Custom adjustables (using macro voodoo) + const int swidth = myTVMode->getWidth() - INDENT - lwidth; + xpos += INDENT; + + CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) + CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) + CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) + CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) + CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) + + ypos += VGAP * 3; + + xpos = HBORDER; + + // TV Phosphor effect + myTVPhosphor = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); + wid.push_back(myTVPhosphor); + ypos += lineHeight + VGAP / 2; + + // TV Phosphor blend level + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend", kPhosBlendChanged) + ypos += VGAP; + + // Scanline intensity and interpolation + xpos -= INDENT; + myTVScanLabel = new StaticTextWidget(myTab, _font, xpos, ypos, "Scanlines:"); + ypos += lineHeight + VGAP / 2; + + xpos += INDENT; + CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged) + + // Create buttons in 2nd column + int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5; + xpos = _w - HBORDER - 2 * 2 - cloneWidth; + ypos = VBORDER - VGAP / 2; + + // Adjustable presets +#define CREATE_CLONE_BUTTON(obj, desc) \ + myClone ## obj = \ + new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\ + desc, kClone ## obj ##Cmd); \ + wid.push_back(myClone ## obj); \ + ypos += buttonHeight + VGAP; + + ypos += VGAP; + CREATE_CLONE_BUTTON(RGB, "Clone RGB") + CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") + CREATE_CLONE_BUTTON(Composite, "Clone Composite") + CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") + CREATE_CLONE_BUTTON(Custom, "Revert") + + // Add items for tab 3 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addAudioTab() +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(); + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + const int INDENT = CheckboxWidget::prefixSize(_font); + const int VGAP = fontHeight / 4; + + int xpos, ypos; + int lwidth = _font.getStringWidth("Volume "), + pwidth; + WidgetArray wid; + VariantList items; + const int tabID = myTab->addTab(" Audio ", TabWidget::AUTO_WIDTH); + + xpos = HBORDER; ypos = VBORDER; + + // Enable sound + mySoundEnableCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Enable sound", kSoundEnableChanged); + wid.push_back(mySoundEnableCheckbox); + ypos += lineHeight + VGAP; + xpos += CheckboxWidget::prefixSize(_font); + + // Volume + myVolumeSlider = new SliderWidget(myTab, _font, xpos, ypos, + "Volume", lwidth, 0, 4 * fontWidth, "%"); + myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100); + myVolumeSlider->setTickmarkIntervals(4); + wid.push_back(myVolumeSlider); + ypos += lineHeight + VGAP; + + // Device + myDevicePopup = new PopUpWidget(myTab, _font, xpos, ypos, + _w - xpos - lwidth - HBORDER - PopUpWidget::dropDownWidth(_font) - 2, lineHeight, + instance().sound().supportedDevices(), + "Device", lwidth, kDeviceChanged); + wid.push_back(myDevicePopup); + ypos += lineHeight + VGAP; + + // Mode + items.clear(); + VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag)); + VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag)); + VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag)); + VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag)); + VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom)); + myModePopup = new PopUpWidget(myTab, _font, xpos, ypos, + _font.getStringWidth("Ultry quality, minimal lag"), lineHeight, + items, "Mode", lwidth, kModeChanged); + wid.push_back(myModePopup); + ypos += lineHeight + VGAP; + xpos += INDENT; + + // Fragment size + lwidth = _font.getStringWidth("Resampling quality "); + pwidth = myModePopup->getRight() - xpos - lwidth - PopUpWidget::dropDownWidth(_font); + items.clear(); + VarList::push_back(items, "128 samples", 128); + VarList::push_back(items, "256 samples", 256); + VarList::push_back(items, "512 samples", 512); + VarList::push_back(items, "1k samples", 1024); + VarList::push_back(items, "2k samples", 2048); + VarList::push_back(items, "4K samples", 4096); + myFragsizePopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Fragment size", lwidth); + wid.push_back(myFragsizePopup); + ypos += lineHeight + VGAP; + + // Output frequency + items.clear(); + VarList::push_back(items, "44100 Hz", 44100); + VarList::push_back(items, "48000 Hz", 48000); + VarList::push_back(items, "96000 Hz", 96000); + myFreqPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Sample rate", lwidth); + wid.push_back(myFreqPopup); + ypos += lineHeight + VGAP; + + // Resampling quality + items.clear(); + VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour)); + VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2)); + VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3)); + myResamplingPopup = new PopUpWidget(myTab, _font, xpos, ypos, + pwidth, lineHeight, + items, "Resampling quality ", lwidth); + wid.push_back(myResamplingPopup); + ypos += lineHeight + VGAP; + + // Param 1 + int swidth = pwidth + PopUpWidget::dropDownWidth(_font); + myHeadroomSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Headroom ", 0, kHeadroomChanged, 10 * fontWidth); + myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM); + myHeadroomSlider->setTickmarkIntervals(5); + wid.push_back(myHeadroomSlider); + ypos += lineHeight + VGAP; + + // Param 2 + myBufferSizeSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth); + myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE); + myBufferSizeSlider->setTickmarkIntervals(5); + wid.push_back(myBufferSizeSlider); + ypos += lineHeight + VGAP; + + // Stereo sound + xpos -= INDENT; + myStereoSoundCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos, + "Stereo for all ROMs"); + wid.push_back(myStereoSoundCheckbox); + ypos += lineHeight + VGAP; + + swidth += INDENT - fontWidth * 4; + myDpcPitch = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight, + "Pitfall II music pitch ", 0, 0, 5 * fontWidth); + myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000); + myDpcPitch->setStepValue(100); + myDpcPitch->setTickmarkIntervals(2); + wid.push_back(myDpcPitch); + + // Add items for tab 4 + addToFocusList(wid, myTab, tabID); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadConfig() +{ + // Display tab + // Renderer settings + myRenderer->setSelected(instance().settings().getString("video"), "default"); + + // TIA interpolation + myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); + + // TIA zoom levels + // These are dynamically loaded, since they depend on the size of + // the desktop and which renderer we're using + float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values + float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); + + myTIAZoom->setMinValue(minZoom * 100); + myTIAZoom->setMaxValue(maxZoom * 100); + myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% + myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); + + // Fullscreen + myFullscreen->setState(instance().settings().getBool("fullscreen")); + // Fullscreen stretch setting + myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); +#ifdef ADAPTABLE_REFRESH_SUPPORT + // Adapt refresh rate + myRefreshAdapt->setState(instance().settings().getBool("tia.fs_refresh")); +#endif + // Fullscreen overscan setting + myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); + handleFullScreenChange(); + + // Aspect ratio setting (NTSC and PAL) + myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); + + ///////////////////////////////////////////////////////////////////////////// + // Palettes tab + // TIA Palette + myPalette = instance().settings().getString("palette"); + myTIAPalette->setSelected(myPalette, PaletteHandler::SETTING_STANDARD); + + // Palette adjustables + instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj); + myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc); + myPhaseShiftPal->setValue(myPaletteAdj.phasePal); + myTVHue->setValue(myPaletteAdj.hue); + myTVBright->setValue(myPaletteAdj.brightness); + myTVContrast->setValue(myPaletteAdj.contrast); + myTVSatur->setValue(myPaletteAdj.saturation); + myTVGamma->setValue(myPaletteAdj.gamma); + handlePaletteChange(); + colorPalette(); + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + myTVMode->setSelected( + instance().settings().getString("tv.filter"), "0"); + int preset = instance().settings().getInt("tv.filter"); + handleTVModeChange(NTSCFilter::Preset(preset)); + + // TV Custom adjustables + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + + // TV phosphor mode + myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); + + // TV phosphor blend + myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); + handlePhosphorChange(); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enable sound +#ifdef SOUND_SUPPORT + mySoundEnableCheckbox->setState(audioSettings.enabled()); +#else + mySoundEnableCheckbox->setState(false); +#endif + + // Volume + myVolumeSlider->setValue(audioSettings.volume()); + + // Device + uInt32 deviceId = BSPF::clamp(audioSettings.device(), 0u, + uInt32(instance().sound().supportedDevices().size() - 1)); + myDevicePopup->setSelected(deviceId); + + // Stereo + myStereoSoundCheckbox->setState(audioSettings.stereo()); + + // DPC Pitch + myDpcPitch->setValue(audioSettings.dpcPitch()); + + // Preset / mode + myModePopup->setSelected(static_cast(audioSettings.preset())); + + updateSettingsWithPreset(instance().audioSettings()); + + updateEnabledState(); + + myTab->loadConfig(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings) +{ + // Fragsize + myFragsizePopup->setSelected(audioSettings.fragmentSize()); + + // Output frequency + myFreqPopup->setSelected(audioSettings.sampleRate()); + + // Headroom + myHeadroomSlider->setValue(audioSettings.headroom()); + + // Buffer size + myBufferSizeSlider->setValue(audioSettings.bufferSize()); + + // Resampling quality + myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality())); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::saveConfig() +{ + ///////////////////////////////////////////////////////////////////////////// + // Display tab + // Renderer setting + instance().settings().setValue("video", + myRenderer->getSelectedTag().toString()); + + // TIA interpolation + instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); + + // Fullscreen + instance().settings().setValue("fullscreen", myFullscreen->getState()); + // Fullscreen stretch setting + instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); +#ifdef ADAPTABLE_REFRESH_SUPPORT + // Adapt refresh rate + instance().settings().setValue("tia.fs_refresh", myRefreshAdapt->getState()); +#endif + // Fullscreen overscan + instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); + + // TIA zoom levels + instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); + + // Aspect ratio setting (NTSC and PAL) + const int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); + const int newAdjust = myVSizeAdjust->getValue(); + const bool vsizeChanged = oldAdjust != newAdjust; + + instance().settings().setValue("tia.vsizeadjust", newAdjust); + + + // Note: Palette values are saved directly when changed! + + ///////////////////////////////////////////////////////////////////////////// + // TV Effects tab + // TV Mode + instance().settings().setValue("tv.filter", + myTVMode->getSelectedTag().toString()); + // TV Custom adjustables + NTSCFilter::Adjustable ntscAdj; + ntscAdj.sharpness = myTVSharp->getValue(); + ntscAdj.resolution = myTVRes->getValue(); + ntscAdj.artifacts = myTVArtifacts->getValue(); + ntscAdj.fringing = myTVFringe->getValue(); + ntscAdj.bleed = myTVBleed->getValue(); + instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(ntscAdj); + + // TV phosphor mode + instance().settings().setValue("tv.phosphor", + myTVPhosphor->getState() ? "always" : "byrom"); + // TV phosphor blend + instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" + ? "0" : myTVPhosLevel->getValueLabel()); + + // TV scanline intensity + instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); + + if(instance().hasConsole()) + { + instance().console().setTIAProperties(); + + if(vsizeChanged) + { + instance().console().tia().clearFrameBuffer(); + instance().console().initializeVideo(); + } + } + + // Finally, issue a complete framebuffer re-initialization... + instance().createFrameBuffer(); + + // ... and apply potential setting changes to the TIA surface + instance().frameBuffer().tiaSurface().updateSurfaceSettings(); + + ///////////////////////////////////////////////////////////////////////////// + // Audio tab + AudioSettings& audioSettings = instance().audioSettings(); + + // Enabled + audioSettings.setEnabled(mySoundEnableCheckbox->getState()); + instance().sound().setEnabled(mySoundEnableCheckbox->getState()); + + // Volume + audioSettings.setVolume(myVolumeSlider->getValue()); + instance().sound().setVolume(myVolumeSlider->getValue()); + + // Device + audioSettings.setDevice(myDevicePopup->getSelected()); + + // Stereo + audioSettings.setStereo(myStereoSoundCheckbox->getState()); + + // DPC Pitch + audioSettings.setDpcPitch(myDpcPitch->getValue()); + // update if current cart is Pitfall II + if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC") + { + CartridgeDPC& cart = static_cast(instance().console().cartridge()); + cart.setDpcPitch(myDpcPitch->getValue()); + } + + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + audioSettings.setPreset(preset); + + if (preset == AudioSettings::Preset::custom) { + // Fragsize + audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt()); + audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt()); + audioSettings.setHeadroom(myHeadroomSlider->getValue()); + audioSettings.setBufferSize(myBufferSizeSlider->getValue()); + audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt())); + } + + // Only force a re-initialization when necessary, since it can + // be a time-consuming operation + if(instance().hasConsole()) + instance().console().initializeAudio(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::setDefaults() +{ + switch(myTab->getActiveTab()) + { + case 0: // General + { + myRenderer->setSelectedIndex(0); + myTIAInterpolate->setState(false); + // screen size + myFullscreen->setState(false); + myUseStretch->setState(false); + #ifdef ADAPTABLE_REFRESH_SUPPORT + myRefreshAdapt->setState(false); + #endif + myTVOverscan->setValue(0); + myTIAZoom->setValue(300); + myVSizeAdjust->setValue(0); + + handleFullScreenChange(); + break; + } + + case 1: // Palettes + myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD); + myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10); + myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10); + myTVHue->setValue(50); + myTVSatur->setValue(50); + myTVContrast->setValue(50); + myTVBright->setValue(50); + myTVGamma->setValue(50); + handlePaletteChange(); + handlePaletteUpdate(); + break; + + case 2: // TV effects + { + myTVMode->setSelected("0", "0"); + + // TV phosphor mode + myTVPhosphor->setState(false); + + // TV phosphor blend + myTVPhosLevel->setValue(50); + + // TV scanline intensity and interpolation + myTVScanIntense->setValue(25); + + // Make sure that mutually-exclusive items are not enabled at the same time + handleTVModeChange(NTSCFilter::Preset::OFF); + handlePhosphorChange(); + loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + } + case 3: // Audio + mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED); + myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME); + myDevicePopup->setSelected(AudioSettings::DEFAULT_DEVICE); + myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO); + myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH); + myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET)); + + if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) { + myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY)); + myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE); + myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE); + myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM); + myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE); + } + else updatePreset(); + + updateEnabledState(); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleTVModeChange(NTSCFilter::Preset preset) +{ + bool enable = preset == NTSCFilter::Preset::CUSTOM; + + myTVSharp->setEnabled(enable); + myTVRes->setEnabled(enable); + myTVArtifacts->setEnabled(enable); + myTVFringe->setEnabled(enable); + myTVBleed->setEnabled(enable); + myCloneComposite->setEnabled(enable); + myCloneSvideo->setEnabled(enable); + myCloneRGB->setEnabled(enable); + myCloneBad->setEnabled(enable); + myCloneCustom->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::loadTVAdjustables(NTSCFilter::Preset preset) +{ + NTSCFilter::Adjustable adj; + instance().frameBuffer().tiaSurface().ntsc().getAdjustables( + adj, NTSCFilter::Preset(preset)); + myTVSharp->setValue(adj.sharpness); + myTVRes->setValue(adj.resolution); + myTVArtifacts->setValue(adj.artifacts); + myTVFringe->setValue(adj.fringing); + myTVBleed->setValue(adj.bleed); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePaletteChange() +{ + bool enable = myTIAPalette->getSelectedTag().toString() == "custom"; + + myPhaseShiftNtsc->setEnabled(enable); + myPhaseShiftPal->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePaletteUpdate() +{ + // TIA Palette + instance().settings().setValue("palette", + myTIAPalette->getSelectedTag().toString()); + // Palette adjustables + PaletteHandler::Adjustable paletteAdj; + paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue(); + paletteAdj.phasePal = myPhaseShiftPal->getValue(); + paletteAdj.hue = myTVHue->getValue(); + paletteAdj.saturation = myTVSatur->getValue(); + paletteAdj.contrast = myTVContrast->getValue(); + paletteAdj.brightness = myTVBright->getValue(); + paletteAdj.gamma = myTVGamma->getValue(); + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj); + + if(instance().hasConsole()) + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleFullScreenChange() +{ + bool enable = myFullscreen->getState(); + myUseStretch->setEnabled(enable); +#ifdef ADAPTABLE_REFRESH_SUPPORT + myRefreshAdapt->setEnabled(enable); +#endif + myTVOverscan->setEnabled(enable); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleOverscanChange() +{ + if (myTVOverscan->getValue() == 0) + { + myTVOverscan->setValueLabel("Off"); + myTVOverscan->setValueUnit(""); + } + else + myTVOverscan->setValueUnit("%"); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handlePhosphorChange() +{ + myTVPhosLevel->setEnabled(myTVPhosphor->getState()); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd, + int data, int id) +{ + switch (cmd) + { + case GuiObject::kOKCmd: + saveConfig(); + close(); + break; + + case GuiObject::kCloseCmd: + // restore palette settings + instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj); + instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette); + Dialog::handleCommand(sender, cmd, data, 0); + break; + + case GuiObject::kDefaultsCmd: + setDefaults(); + break; + + case kPaletteChanged: + handlePaletteChange(); + handlePaletteUpdate(); + break; + + case kPaletteUpdated: + handlePaletteUpdate(); + break; + + case kNtscShiftChanged: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE; + myPhaseShiftNtsc->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kPalShiftChanged: + { + std::ostringstream ss; + + ss << std::setw(4) << std::fixed << std::setprecision(1) + << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE; + myPhaseShiftPal->setValueLabel(ss.str()); + handlePaletteUpdate(); + break; + } + case kVSizeChanged: + { + int adjust = myVSizeAdjust->getValue(); + + if (!adjust) + { + myVSizeAdjust->setValueLabel("Default"); + myVSizeAdjust->setValueUnit(""); + } + else + myVSizeAdjust->setValueUnit("%"); + break; + } + case kFullScreenChanged: + handleFullScreenChange(); + break; + + case kOverscanChanged: + handleOverscanChange(); + break; + + case kTVModeChanged: + handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); + break; + + case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); + break; + case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); + break; + case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); + break; + case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); + break; + case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); + break; + + case kScanlinesChanged: + if (myTVScanIntense->getValue() == 0) + { + myTVScanIntense->setValueLabel("Off"); + myTVScanIntense->setValueUnit(""); + } + else + myTVScanIntense->setValueUnit("%"); + break; + + case kPhosphorChanged: + handlePhosphorChange(); + break; + + case kPhosBlendChanged: + if (myTVPhosLevel->getValue() == 0) + { + myTVPhosLevel->setValueLabel("Off"); + myTVPhosLevel->setValueUnit(""); + } + else + myTVPhosLevel->setValueUnit("%"); + break; + + case kSoundEnableChanged: + updateEnabledState(); + break; + + case kModeChanged: + updatePreset(); + updateEnabledState(); + break; + + case kHeadroomChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames"; + myHeadroomSlider->setValueLabel(ss.str()); + break; + } + case kBufferSizeChanged: + { + std::ostringstream ss; + ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames"; + myBufferSizeSlider->setValueLabel(ss.str()); + break; + } + + default: + Dialog::handleCommand(sender, cmd, data, 0); + break; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::addPalette(int x, int y, int w, int h) +{ + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const GUI::Font& ifont = instance().frameBuffer().infoFont(); + const int lwidth = ifont.getMaxCharWidth() * 1.5; + const float COLW = float(w - lwidth) / NUM_LUMA; + const float COLH = float(h) / NUM_CHROMA; + const int yofs = (COLH - ifont.getFontHeight() + 1) / 2; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " "); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH, + COLW + 1, COLH + 1, 0, false); + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::colorPalette() +{ + if(instance().hasConsole()) + { + constexpr int NUM_LUMA = 8; + constexpr int NUM_CHROMA = 16; + const int order[2][NUM_CHROMA] = + { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15} + }; + const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0; + + for(int idx = 0; idx < NUM_CHROMA; ++idx) + { + ostringstream ss; + const int color = order[type][idx]; + + ss << Common::Base::HEX1 << std::uppercase << color; + myColorLbl[idx]->setLabel(ss.str()); + for(int lum = 0; lum < NUM_LUMA; ++lum) + { + myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updateEnabledState() +{ + bool active = mySoundEnableCheckbox->getState(); + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + bool userMode = preset == AudioSettings::Preset::custom; + + myVolumeSlider->setEnabled(active); + myDevicePopup->setEnabled(active); + myStereoSoundCheckbox->setEnabled(active); + myModePopup->setEnabled(active); + // enable only for Pitfall II cart + myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC"); + + myFragsizePopup->setEnabled(active && userMode); + myFreqPopup->setEnabled(active && userMode); + myResamplingPopup->setEnabled(active && userMode); + myHeadroomSlider->setEnabled(active && userMode); + myBufferSizeSlider->setEnabled(active && userMode); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void VideoAudioDialog::updatePreset() +{ + AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt()); + + // Make a copy that does not affect the actual settings... + AudioSettings audioSettings = instance().audioSettings(); + audioSettings.setPersistent(false); + // ... and set the requested preset + audioSettings.setPreset(preset); + + updateSettingsWithPreset(audioSettings); +} diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoAudioDialog.hxx similarity index 60% rename from src/gui/VideoDialog.hxx rename to src/gui/VideoAudioDialog.hxx index 34931481d..ef0f850a8 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoAudioDialog.hxx @@ -15,74 +15,75 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ -#ifndef VIDEO_DIALOG_HXX -#define VIDEO_DIALOG_HXX +#ifndef VIDEOAUDIO_DIALOG_HXX +#define VIDEOAUDIO_DIALOG_HXX class CommandSender; class CheckboxWidget; +class ColorWidget; class DialogContainer; class PopUpWidget; +class RadioButtonGroup; class SliderWidget; class StaticTextWidget; class TabWidget; class OSystem; #include "Dialog.hxx" +#include "PaletteHandler.hxx" #include "NTSCFilter.hxx" #include "bspf.hxx" -class VideoDialog : public Dialog +class VideoAudioDialog : public Dialog { public: - VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, int max_w, int max_h); - virtual ~VideoDialog() = default; + virtual ~VideoAudioDialog() = default; private: void loadConfig() override; void saveConfig() override; void setDefaults() override; + void addDisplayTab(); + void addPaletteTab(); + void addTVEffectsTab(); + void addAudioTab(); void handleTVModeChange(NTSCFilter::Preset); void loadTVAdjustables(NTSCFilter::Preset preset); + void handlePaletteChange(); + void handlePaletteUpdate(); void handleFullScreenChange(); void handleOverscanChange(); void handlePhosphorChange(); void handleCommand(CommandSender* sender, int cmd, int data, int id) override; + void addPalette(int x, int y, int h, int w); + void colorPalette(); + void updatePreset(); + void updateEnabledState(); + void updateSettingsWithPreset(AudioSettings&); private: TabWidget* myTab; // General options PopUpWidget* myRenderer{nullptr}; - SliderWidget* myTIAZoom{nullptr}; - PopUpWidget* myTIAPalette{nullptr}; CheckboxWidget* myTIAInterpolate{nullptr}; - SliderWidget* myVSizeAdjust{nullptr}; - SliderWidget* mySpeed{nullptr}; - CheckboxWidget* myFullscreen{nullptr}; - //PopUpWidget* myFullScreenMode; CheckboxWidget* myUseStretch{nullptr}; SliderWidget* myTVOverscan{nullptr}; - CheckboxWidget* myUseVSync{nullptr}; - CheckboxWidget* myUIMessages{nullptr}; - CheckboxWidget* myCenter{nullptr}; - CheckboxWidget* myFastSCBios{nullptr}; - CheckboxWidget* myUseThreads{nullptr}; + CheckboxWidget* myRefreshAdapt{nullptr}; + SliderWidget* myTIAZoom{nullptr}; + SliderWidget* myVSizeAdjust{nullptr}; // TV effects adjustables (custom mode) PopUpWidget* myTVMode{nullptr}; SliderWidget* myTVSharp{nullptr}; - SliderWidget* myTVHue{nullptr}; SliderWidget* myTVRes{nullptr}; SliderWidget* myTVArtifacts{nullptr}; SliderWidget* myTVFringe{nullptr}; SliderWidget* myTVBleed{nullptr}; - SliderWidget* myTVBright{nullptr}; - SliderWidget* myTVContrast{nullptr}; - SliderWidget* myTVSatur{nullptr}; - SliderWidget* myTVGamma{nullptr}; // TV phosphor effect CheckboxWidget* myTVPhosphor{nullptr}; @@ -99,12 +100,45 @@ class VideoDialog : public Dialog ButtonWidget* myCloneBad{nullptr}; ButtonWidget* myCloneCustom{nullptr}; + // Palettes + PopUpWidget* myTIAPalette{nullptr}; + SliderWidget* myPhaseShiftNtsc{nullptr}; + SliderWidget* myPhaseShiftPal{nullptr}; + SliderWidget* myTVHue{nullptr}; + SliderWidget* myTVSatur{nullptr}; + SliderWidget* myTVBright{nullptr}; + SliderWidget* myTVContrast{nullptr}; + SliderWidget* myTVGamma{nullptr}; + std::array myColorLbl{nullptr}; + ColorWidget* myColor[16][8]{{nullptr}}; + + // Audio + CheckboxWidget* mySoundEnableCheckbox{nullptr}; + SliderWidget* myVolumeSlider{nullptr}; + PopUpWidget* myDevicePopup{nullptr}; + CheckboxWidget* myStereoSoundCheckbox{nullptr}; + PopUpWidget* myModePopup{nullptr}; + PopUpWidget* myFragsizePopup{nullptr}; + PopUpWidget* myFreqPopup{nullptr}; + PopUpWidget* myResamplingPopup{nullptr}; + SliderWidget* myHeadroomSlider{nullptr}; + SliderWidget* myBufferSizeSlider{nullptr}; + SliderWidget* myDpcPitch{nullptr}; + + string myPalette; + PaletteHandler::Adjustable myPaletteAdj; + enum { - kSpeedupChanged = 'VDSp', + kZoomChanged = 'VDZo', kVSizeChanged = 'VDVs', kFullScreenChanged = 'VDFs', kOverscanChanged = 'VDOv', + kPaletteChanged = 'VDpl', + kNtscShiftChanged = 'VDns', + kPalShiftChanged = 'VDps', + kPaletteUpdated = 'VDpu', + kTVModeChanged = 'VDtv', kCloneCompositeCmd = 'CLcp', kCloneSvideoCmd = 'CLsv', @@ -113,16 +147,22 @@ class VideoDialog : public Dialog kCloneCustomCmd = 'CLcu', kPhosphorChanged = 'VDph', kPhosBlendChanged = 'VDbl', - kScanlinesChanged = 'VDsc' + kScanlinesChanged = 'VDsc', + + kSoundEnableChanged = 'ADse', + kDeviceChanged = 'ADdc', + kModeChanged = 'ADmc', + kHeadroomChanged = 'ADhc', + kBufferSizeChanged = 'ADbc' }; private: // Following constructors and assignment operators not supported - VideoDialog() = delete; - VideoDialog(const VideoDialog&) = delete; - VideoDialog(VideoDialog&&) = delete; - VideoDialog& operator=(const VideoDialog&) = delete; - VideoDialog& operator=(VideoDialog&&) = delete; + VideoAudioDialog() = delete; + VideoAudioDialog(const VideoAudioDialog&) = delete; + VideoAudioDialog(VideoAudioDialog&&) = delete; + VideoAudioDialog& operator=(const VideoAudioDialog&) = delete; + VideoAudioDialog& operator=(VideoAudioDialog&&) = delete; }; #endif diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx deleted file mode 100644 index 981e1a4e0..000000000 --- a/src/gui/VideoDialog.cxx +++ /dev/null @@ -1,693 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony -// and the Stella Team -// -// See the file "License.txt" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -//============================================================================ - -#include - -#include "bspf.hxx" -#include "Control.hxx" -#include "Dialog.hxx" -#include "Menu.hxx" -#include "OSystem.hxx" -#include "EditTextWidget.hxx" -#include "PopUpWidget.hxx" -#include "Console.hxx" -#include "TIA.hxx" -#include "Settings.hxx" -#include "Widget.hxx" -#include "Font.hxx" -#include "TabWidget.hxx" -#include "NTSCFilter.hxx" -#include "TIASurface.hxx" - -#include "VideoDialog.hxx" - -namespace { - // Emulation speed is a positive float that multiplies the framerate. However, the UI controls - // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following - // mapping and formatting functions implement this conversion. The speedup factor is represented - // by an integer value between -900 and 900 (0 means no speedup). - - constexpr int MAX_SPEED = 900; - constexpr int MIN_SPEED = -900; - constexpr int SPEED_STEP = 10; - - int mapSpeed(float speed) - { - speed = std::abs(speed); - - return BSPF::clamp( - static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))), - MIN_SPEED, MAX_SPEED - ); - } - - float unmapSpeed(int speed) - { - float f_speed = static_cast(speed) / 100; - - return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed; - } - - string formatSpeed(int speed) { - stringstream ss; - - ss - << std::setw(3) << std::fixed << std::setprecision(0) - << (unmapSpeed(speed) * 100); - - return ss.str(); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent, - const GUI::Font& font, int max_w, int max_h) - : Dialog(osystem, parent, font, "Video settings") -{ - const int VGAP = 4; - const int VBORDER = 8; - const int HBORDER = 10; - const int INDENT = 20; - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - buttonHeight = font.getLineHeight() + 4; - int xpos, ypos, tabID; - int lwidth = font.getStringWidth("V-Size adjust "), - pwidth = font.getStringWidth("XXXXxXXXX"), - swidth = font.getMaxCharWidth() * 10 - 2; - - WidgetArray wid; - VariantList items; - - // Set real dimensions - setSize(60 * fontWidth + HBORDER * 2, 14 * (lineHeight + VGAP) + 14 + _th, max_w, max_h); - - // The tab widget - xpos = 2; ypos = 4; - myTab = new TabWidget(this, font, xpos, ypos + _th, _w - 2*xpos, _h - _th - buttonHeight - 20); - addTabWidget(myTab); - - xpos = HBORDER; ypos = VBORDER; - ////////////////////////////////////////////////////////// - // 1) General options - tabID = myTab->addTab(" General "); - - // Video renderer - myRenderer = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedRenderers(), - "Renderer ", lwidth); - wid.push_back(myRenderer); - ypos += lineHeight + VGAP; - - // TIA Palette - items.clear(); - VarList::push_back(items, "Standard", "standard"); - VarList::push_back(items, "z26", "z26"); - if (instance().checkUserPalette()) - VarList::push_back(items, "User", "user"); - myTIAPalette = new PopUpWidget(myTab, font, xpos, ypos, pwidth, - lineHeight, items, "Palette ", lwidth); - wid.push_back(myTIAPalette); - ypos += lineHeight + VGAP; - - // TIA interpolation - myTIAInterpolate = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Interpolation "); - wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP; - - - // TIA zoom levels (will be dynamically filled later) - myTIAZoom = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight, - "Zoom ", lwidth, 0, fontWidth * 4, "%"); - myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100); - wid.push_back(myTIAZoom); - ypos += lineHeight + VGAP; - - // Aspect ratio (NTSC mode) - myVSizeAdjust = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true); - myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5); - myVSizeAdjust->setTickmarkIntervals(2); - wid.push_back(myVSizeAdjust); - ypos += lineHeight + VGAP; - - // Speed - mySpeed = - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, - "Emul. speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%"); - mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED); - mySpeed->setStepValue(SPEED_STEP); - mySpeed->setTickmarkIntervals(2); - wid.push_back(mySpeed); - ypos += lineHeight + VGAP; - - // Use sync to vblank - myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync"); - wid.push_back(myUseVSync); - - // Move over to the next column - xpos += mySpeed->getWidth() + 44; - ypos = VBORDER; - - // Fullscreen - myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged); - wid.push_back(myFullscreen); - ypos += lineHeight + VGAP; - - /*pwidth = font.getStringWidth("0: 3840x2860@120Hz"); - myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight, - instance().frameBuffer().supportedScreenModes(), "Mode "); - wid.push_back(myFullScreenMode); - ypos += lineHeight + VGAP;*/ - - // FS stretch - myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "Stretch"); - wid.push_back(myUseStretch); - ypos += lineHeight + VGAP; - - // FS overscan - myTVOverscan = new SliderWidget(myTab, font, xpos + INDENT, ypos - 1, swidth, lineHeight, - "Overscan", font.getStringWidth("Overscan "), kOverscanChanged, fontWidth * 3, "%"); - myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10); - myTVOverscan->setTickmarkIntervals(2); - wid.push_back(myTVOverscan); - ypos += (lineHeight + VGAP) * 2; - - // Skip progress load bars for SuperCharger ROMs - // Doesn't really belong here, but I couldn't find a better place for it - myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fast SuperCharger load"); - wid.push_back(myFastSCBios); - ypos += lineHeight + VGAP; - - // Show UI messages onscreen - myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Show UI messages"); - wid.push_back(myUIMessages); - ypos += lineHeight + VGAP; - - // Center window (in windowed mode) - myCenter = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Center window"); - wid.push_back(myCenter); - ypos += (lineHeight + VGAP) * 2; - - // Use multi-threading - myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Multi-threading"); - wid.push_back(myUseThreads); - - // Add items for tab 0 - addToFocusList(wid, myTab, tabID); - - ////////////////////////////////////////////////////////// - // 2) TV effects options - wid.clear(); - tabID = myTab->addTab(" TV Effects "); - xpos = HBORDER; - ypos = VBORDER; - swidth = font.getMaxCharWidth() * 8 - 4; - - // TV Mode - items.clear(); - VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF)); - VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB)); - VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO)); - VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE)); - VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD)); - VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM)); - lwidth = font.getStringWidth("TV Mode "); - pwidth = font.getStringWidth("Bad adjust"); - myTVMode = - new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, - items, "TV mode ", lwidth, kTVModeChanged); - wid.push_back(myTVMode); - ypos += lineHeight + VGAP; - - // Custom adjustables (using macro voodoo) - xpos += INDENT - 2; ypos += 0; - lwidth = font.getStringWidth("Saturation "); - -#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \ - myTV ## obj = \ - new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \ - desc, lwidth, cmd, fontWidth*4, "%"); \ - myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \ - myTV ## obj->setTickmarkIntervals(2); \ - wid.push_back(myTV ## obj); \ - ypos += lineHeight + VGAP; - - CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0) - CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0) - CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0) - CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0) - CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0) - CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0) - CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0) - CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0) - CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0) - CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0) - - xpos += myTVContrast->getWidth() + 30; - ypos = VBORDER; - - lwidth = font.getStringWidth("Intensity "); - - // TV Phosphor effect - myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged); - wid.push_back(myTVPhosphor); - ypos += lineHeight + VGAP / 2; - - // TV Phosphor blend level - xpos += INDENT; - swidth = font.getMaxCharWidth() * 10; - CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged) - ypos += 8; - - // Scanline intensity and interpolation - xpos -= INDENT; - myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanlines:"); - ypos += lineHeight + VGAP / 2; - - xpos += INDENT; - CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity ", kScanlinesChanged) - ypos += lineHeight + 2; - - // Adjustable presets - xpos -= INDENT; - int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20; -#define CREATE_CLONE_BUTTON(obj, desc) \ - myClone ## obj = \ - new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\ - desc, kClone ## obj ##Cmd); \ - wid.push_back(myClone ## obj); \ - ypos += lineHeight + 4 + VGAP; - - ypos += VGAP; - CREATE_CLONE_BUTTON(RGB, "Clone RGB") - CREATE_CLONE_BUTTON(Svideo, "Clone S-Video") - CREATE_CLONE_BUTTON(Composite, "Clone Composite") - CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust") - CREATE_CLONE_BUTTON(Custom, "Revert") - - // Add items for tab 2 - addToFocusList(wid, myTab, tabID); - - // Activate the first tab - myTab->setActiveTab(0); - - // Add Defaults, OK and Cancel buttons - wid.clear(); - addDefaultsOKCancelBGroup(wid, font); - addBGroupToFocusList(wid); - - // Disable certain functions when we know they aren't present -#ifndef WINDOWED_SUPPORT - myFullscreen->clearFlags(Widget::FLAG_ENABLED); - myCenter->clearFlags(Widget::FLAG_ENABLED); -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadConfig() -{ - // Renderer settings - myRenderer->setSelected(instance().settings().getString("video"), "default"); - - // TIA zoom levels - // These are dynamically loaded, since they depend on the size of - // the desktop and which renderer we're using - float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values - float maxZoom = instance().frameBuffer().supportedTIAMaxZoom(); - - myTIAZoom->setMinValue(minZoom * 100); - myTIAZoom->setMaxValue(maxZoom * 100); - myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50% - myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100); - - // TIA Palette - myTIAPalette->setSelected( - instance().settings().getString("palette"), "standard"); - - // TIA interpolation - myTIAInterpolate->setState(instance().settings().getBool("tia.inter")); - - // Aspect ratio setting (NTSC and PAL) - myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust")); - - // Emulation speed - int speed = mapSpeed(instance().settings().getFloat("speed")); - mySpeed->setValue(speed); - mySpeed->setValueLabel(formatSpeed(speed)); - - // Fullscreen - myFullscreen->setState(instance().settings().getBool("fullscreen")); - /*string mode = instance().settings().getString("fullscreenmode"); - myFullScreenMode->setSelected(mode);*/ - // Fullscreen stretch setting - myUseStretch->setState(instance().settings().getBool("tia.fs_stretch")); - // Fullscreen overscan setting - myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan")); - handleFullScreenChange(); - - // Use sync to vertical blank - myUseVSync->setState(instance().settings().getBool("vsync")); - - // Show UI messages - myUIMessages->setState(instance().settings().getBool("uimessages")); - - // Center window - myCenter->setState(instance().settings().getBool("center")); - - // Fast loading of Supercharger BIOS - myFastSCBios->setState(instance().settings().getBool("fastscbios")); - - // Multi-threaded rendering - myUseThreads->setState(instance().settings().getBool("threads")); - - // TV Mode - myTVMode->setSelected( - instance().settings().getString("tv.filter"), "0"); - int preset = instance().settings().getInt("tv.filter"); - handleTVModeChange(NTSCFilter::Preset(preset)); - - // TV Custom adjustables - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - - // TV phosphor mode - myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always"); - - // TV phosphor blend - myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend")); - handlePhosphorChange(); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines")); - - myTab->loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::saveConfig() -{ - // Renderer setting - instance().settings().setValue("video", - myRenderer->getSelectedTag().toString()); - - // TIA zoom levels - instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0); - - // TIA Palette - instance().settings().setValue("palette", - myTIAPalette->getSelectedTag().toString()); - - // TIA interpolation - instance().settings().setValue("tia.inter", myTIAInterpolate->getState()); - - // Aspect ratio setting (NTSC and PAL) - int oldAdjust = instance().settings().getInt("tia.vsizeadjust"); - int newAdjust = myVSizeAdjust->getValue(); - bool vsizeChanged = oldAdjust != newAdjust; - - instance().settings().setValue("tia.vsizeadjust", newAdjust); - - // Speed - int speedup = mySpeed->getValue(); - instance().settings().setValue("speed", unmapSpeed(speedup)); - if (instance().hasConsole()) instance().console().initializeAudio(); - - // Fullscreen - instance().settings().setValue("fullscreen", myFullscreen->getState()); - // Fullscreen stretch setting - instance().settings().setValue("tia.fs_stretch", myUseStretch->getState()); - // Fullscreen overscan - instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel()); - - // Use sync to vertical blank - instance().settings().setValue("vsync", myUseVSync->getState()); - - // Show UI messages - instance().settings().setValue("uimessages", myUIMessages->getState()); - - // Center window - instance().settings().setValue("center", myCenter->getState()); - - // Fast loading of Supercharger BIOS - instance().settings().setValue("fastscbios", myFastSCBios->getState()); - - // Multi-threaded rendering - instance().settings().setValue("threads", myUseThreads->getState()); - if (instance().hasConsole()) - instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState()); - - // TV Mode - instance().settings().setValue("tv.filter", - myTVMode->getSelectedTag().toString()); - - // TV Custom adjustables - NTSCFilter::Adjustable adj; - adj.hue = myTVHue->getValue(); - adj.saturation = myTVSatur->getValue(); - adj.contrast = myTVContrast->getValue(); - adj.brightness = myTVBright->getValue(); - adj.sharpness = myTVSharp->getValue(); - adj.gamma = myTVGamma->getValue(); - adj.resolution = myTVRes->getValue(); - adj.artifacts = myTVArtifacts->getValue(); - adj.fringing = myTVFringe->getValue(); - adj.bleed = myTVBleed->getValue(); - instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj); - - // TV phosphor mode - instance().settings().setValue("tv.phosphor", - myTVPhosphor->getState() ? "always" : "byrom"); - // TV phosphor blend - instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" - ? "0" : myTVPhosLevel->getValueLabel()); - - // TV scanline intensity - instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel()); - - if (instance().hasConsole()) - instance().console().setTIAProperties(); - - if (vsizeChanged && instance().hasConsole()) { - instance().console().tia().clearFrameBuffer(); - instance().console().initializeVideo(); - } - - // Finally, issue a complete framebuffer re-initialization... - instance().createFrameBuffer(); - - // ... and apply potential setting changes to the TIA surface - instance().frameBuffer().tiaSurface().updateSurfaceSettings(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::setDefaults() -{ - switch(myTab->getActiveTab()) - { - case 0: // General - { - myRenderer->setSelectedIndex(0); - myTIAZoom->setValue(300); - myTIAPalette->setSelected("standard", ""); - myTIAInterpolate->setState(false); - myVSizeAdjust->setValue(0); - mySpeed->setValue(0); - - myFullscreen->setState(false); - //myFullScreenMode->setSelectedIndex(0); - myUseStretch->setState(false); - myUseVSync->setState(true); - myUIMessages->setState(true); - myCenter->setState(false); - myFastSCBios->setState(true); - myUseThreads->setState(false); - break; - } - - case 1: // TV effects - { - myTVMode->setSelected("0", "0"); - - // TV phosphor mode - myTVPhosphor->setState(false); - - // TV phosphor blend - myTVPhosLevel->setValue(50); - - // TV scanline intensity and interpolation - myTVScanIntense->setValue(25); - - // Make sure that mutually-exclusive items are not enabled at the same time - handleTVModeChange(NTSCFilter::Preset::OFF); - handlePhosphorChange(); - loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset) -{ - bool enable = preset == NTSCFilter::Preset::CUSTOM; - - myTVSharp->setEnabled(enable); - myTVHue->setEnabled(enable); - myTVRes->setEnabled(enable); - myTVArtifacts->setEnabled(enable); - myTVFringe->setEnabled(enable); - myTVBleed->setEnabled(enable); - myTVBright->setEnabled(enable); - myTVContrast->setEnabled(enable); - myTVSatur->setEnabled(enable); - myTVGamma->setEnabled(enable); - myCloneComposite->setEnabled(enable); - myCloneSvideo->setEnabled(enable); - myCloneRGB->setEnabled(enable); - myCloneBad->setEnabled(enable); - myCloneCustom->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset) -{ - NTSCFilter::Adjustable adj; - instance().frameBuffer().tiaSurface().ntsc().getAdjustables( - adj, NTSCFilter::Preset(preset)); - myTVSharp->setValue(adj.sharpness); - myTVHue->setValue(adj.hue); - myTVRes->setValue(adj.resolution); - myTVArtifacts->setValue(adj.artifacts); - myTVFringe->setValue(adj.fringing); - myTVBleed->setValue(adj.bleed); - myTVBright->setValue(adj.brightness); - myTVContrast->setValue(adj.contrast); - myTVSatur->setValue(adj.saturation); - myTVGamma->setValue(adj.gamma); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleFullScreenChange() -{ - bool enable = myFullscreen->getState(); - myUseStretch->setEnabled(enable); - myTVOverscan->setEnabled(enable); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleOverscanChange() -{ - if (myTVOverscan->getValue() == 0) - { - myTVOverscan->setValueLabel("Off"); - myTVOverscan->setValueUnit(""); - } - else - myTVOverscan->setValueUnit("%"); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handlePhosphorChange() -{ - myTVPhosLevel->setEnabled(myTVPhosphor->getState()); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void VideoDialog::handleCommand(CommandSender* sender, int cmd, - int data, int id) -{ - switch (cmd) - { - case GuiObject::kOKCmd: - saveConfig(); - close(); - break; - - case GuiObject::kDefaultsCmd: - setDefaults(); - break; - - case kVSizeChanged: - { - int adjust = myVSizeAdjust->getValue(); - - if (!adjust) - { - myVSizeAdjust->setValueLabel("Default"); - myVSizeAdjust->setValueUnit(""); - } - else - myVSizeAdjust->setValueUnit("%"); - break; - } - - case kSpeedupChanged: - mySpeed->setValueLabel(formatSpeed(mySpeed->getValue())); - break; - - case kFullScreenChanged: - handleFullScreenChange(); - break; - - case kOverscanChanged: - handleOverscanChange(); - break; - - case kTVModeChanged: - handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt())); - break; - - case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE); - break; - case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO); - break; - case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB); - break; - case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD); - break; - case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM); - break; - - case kScanlinesChanged: - if (myTVScanIntense->getValue() == 0) - { - myTVScanIntense->setValueLabel("Off"); - myTVScanIntense->setValueUnit(""); - } - else - myTVScanIntense->setValueUnit("%"); - break; - - case kPhosphorChanged: - handlePhosphorChange(); - break; - - case kPhosBlendChanged: - if (myTVPhosLevel->getValue() == 0) - { - myTVPhosLevel->setValueLabel("Off"); - myTVPhosLevel->setValueUnit(""); - } - else - myTVPhosLevel->setValueUnit("%"); - break; - - default: - Dialog::handleCommand(sender, cmd, data, 0); - break; - } -} diff --git a/src/gui/WhatsNewDialog.cxx b/src/gui/WhatsNewDialog.cxx new file mode 100644 index 000000000..7f6c15084 --- /dev/null +++ b/src/gui/WhatsNewDialog.cxx @@ -0,0 +1,99 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#include "Version.hxx" + +#include "WhatsNewDialog.hxx" + +constexpr int MAX_CHARS = 64; // maximum number of chars per line + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +WhatsNewDialog::WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + int max_w, int max_h) +#if defined(RETRON77) + : Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + " for RetroN 77?") +#else + : Dialog(osystem, parent, font, "What's New in Stella " + string(STELLA_VERSION) + "?") +#endif +{ + const int fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + buttonHeight = _font.getLineHeight() * 1.25; + const int VGAP = fontHeight / 4; + const int VBORDER = fontHeight / 2; + const int HBORDER = fontWidth * 1.25; + int ypos = _th + VBORDER; + + + // Set preliminary dimensions + setSize(MAX_CHARS * fontWidth + HBORDER * 2, max_h, + max_w, max_h); + +#if defined(RETRON77) + add(ypos, "added adjustable autofire (see 'Advanced Settings')"); + add(ypos, "added new UI theme 'Dark' (see 'Advanced Settings')"); +#else + add(ypos, "added adjustable autofire"); + add(ypos, "added 'Dark' UI theme"); + //add(ypos, "extended global hotkeys for debug options"); + add(ypos, "added option to playback a game using the Time Machine"); + //add(ypos, "allow taking snapshots from within the Time Machine dialog"); + add(ypos, "added the ability to access most files that Stella uses from within a ZIP file"); + add(ypos, "added option to select the audio device"); + //add(ypos, "added option to display detected settings info when a ROM is loaded"); + //add(ypos, "replaced 'Re-disassemble' with 'Disassemble @ current line' in debugger"); + //add(ypos, "fixed bug when taking fullscreen snapshots; the dimensions were sometimes cut"); + add(ypos, ELLIPSIS + " (for a complete list see 'docs/Changes.txt')"); +#endif + + // Set needed dimensions + setSize(MAX_CHARS * fontWidth + HBORDER * 2, + ypos + VGAP * 2 + buttonHeight + VBORDER, + max_w, max_h); + + WidgetArray wid; + addOKBGroup(wid, _font); + addBGroupToFocusList(wid); + + // We don't have a close/cancel button, but we still want the cancel + // event to be processed + processCancelWithoutWidget(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void WhatsNewDialog::add(int& ypos, const string& text) +{ + const int lineHeight = _font.getLineHeight(), + fontHeight = _font.getFontHeight(), + fontWidth = _font.getMaxCharWidth(), + HBORDER = fontWidth * 1.25; + const string DOT = "\x1f"; + string txt = DOT + " " + text; + + // automatically wrap too long texts + while(txt.length() > MAX_CHARS) + { + int i = MAX_CHARS; + + while(--i && txt[i] != ' '); + new StaticTextWidget(this, _font, HBORDER, ypos, txt.substr(0, i)); + txt = " " + txt.substr(i); + ypos += fontHeight; + } + new StaticTextWidget(this, _font, HBORDER, ypos, txt); + ypos += lineHeight; +} diff --git a/src/gui/WhatsNewDialog.hxx b/src/gui/WhatsNewDialog.hxx new file mode 100644 index 000000000..d90edbd15 --- /dev/null +++ b/src/gui/WhatsNewDialog.hxx @@ -0,0 +1,34 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony +// and the Stella Team +// +// See the file "License.txt" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +//============================================================================ + +#ifndef WHATSNEW_DIALOG_HXX +#define WHATSNEW_DIALOG_HXX + +#include "Dialog.hxx" + +class WhatsNewDialog : public Dialog +{ + public: + WhatsNewDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font, + int max_w, int max_h); + virtual ~WhatsNewDialog() = default; + + private: + void add(int& ypos, const string& text); +}; + +#endif diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 895f68158..ed6ba2f02 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -482,26 +482,28 @@ void ButtonWidget::drawWidget(bool hilite) CheckboxWidget::CheckboxWidget(GuiObject* boss, const GUI::Font& font, int x, int y, const string& label, int cmd) - : ButtonWidget(boss, font, x, y, 16, 16, label, cmd) + : ButtonWidget(boss, font, x, y, font.getFontHeight() < 24 ? 16 : 24, + font.getFontHeight() < 24 ? 16 : 24, label, cmd) { _flags = Widget::FLAG_ENABLED; _bgcolor = _bgcolorhi = kWidColor; _bgcolorlo = kDlgColor; _editable = true; + _boxSize = boxSize(font); if(label == "") - _w = 14; + _w = _boxSize; else - _w = font.getStringWidth(label) + 20; - _h = font.getFontHeight() < 14 ? 14 : font.getFontHeight(); + _w = font.getStringWidth(label) + _boxSize + font.getMaxCharWidth() * 0.75; + _h = font.getFontHeight() < _boxSize ? _boxSize : font.getFontHeight(); // Depending on font size, either the font or box will need to be // centered vertically - if(_h > 14) // center box - _boxY = (_h - 14) / 2; + if(_h > _boxSize) // center box + _boxY = (_h - _boxSize) / 2; else // center text - _textY = (14 - _font.getFontHeight()) / 2; + _textY = (_boxSize - _font.getFontHeight()) / 2; setFill(CheckboxWidget::FillType::Normal); } @@ -549,7 +551,8 @@ void CheckboxWidget::setEditable(bool editable) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void CheckboxWidget::setFill(FillType type) { - /* 8x8 checkbox bitmap */ + /* 10x10 checkbox bitmap */ + // small versions static constexpr std::array checked_img_active = { 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111, 0b1111111111 @@ -565,17 +568,36 @@ void CheckboxWidget::setFill(FillType type) 0b1111111111, 0b1111111111, 0b0111111110, 0b0111111110, 0b0001111000 }; + /* 18x18 checkbox bitmap */ + // large versions + static constexpr std::array checked_img_active_large = { + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, + 0b111111111111111111, 0b111111111111111111 + }; + + static constexpr std::array checked_img_inactive_large = { + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111, + 0b111111110011111111, 0b111111100001111111, 0b111111000000111111, 0b111110000000011111, + 0b111100000000001111, 0b111000000000000111, 0b111000000000000111, 0b111100000000001111, + 0b111110000000011111, 0b111111000000111111, 0b111111100001111111, 0b111111110011111111, + 0b111111111111111111, 0b111111111111111111, 0b111111111111111111 + }; + switch(type) { case CheckboxWidget::FillType::Normal: - _img = checked_img_active.data(); + _img = _boxSize == 14 ? checked_img_active.data() : checked_img_active_large.data(); _drawBox = true; break; case CheckboxWidget::FillType::Inactive: - _img = checked_img_inactive.data(); + _img = _boxSize == 14 ? checked_img_inactive.data() : checked_img_inactive_large.data(); _drawBox = true; break; case CheckboxWidget::FillType::Circle: + // only used in debugger which only has smaller fonts _img = checked_img_circle.data(); _drawBox = false; break; @@ -601,17 +623,17 @@ void CheckboxWidget::drawWidget(bool hilite) bool onTop = _boss->dialog().isOnTop(); if(_drawBox) - s.frameRect(_x, _y + _boxY, 14, 14, onTop && hilite && isEnabled() && isEditable() ? kWidColorHi : kColor); + s.frameRect(_x, _y + _boxY, _boxSize, _boxSize, onTop && hilite && isEnabled() && isEditable() ? kWidColorHi : kColor); // Do we draw a square or cross? - s.fillRect(_x + 1, _y + _boxY + 1, 12, 12, + s.fillRect(_x + 1, _y + _boxY + 1, _boxSize - 2, _boxSize - 2, _changed ? onTop ? kDbgChangedColor : kDlgColor : isEnabled() && onTop ? _bgcolor : kDlgColor); if(_state) s.drawBitmap(_img, _x + 2, _y + _boxY + 2, onTop && isEnabled() ? hilite && isEditable() ? kWidColorHi : kCheckColor - : kColor, 10); + : kColor, _boxSize - 4); // Finally draw the label - s.drawString(_font, _label, _x + 20, _y + _textY, _w, + s.drawString(_font, _label, _x + prefixSize(_font), _y + _textY, _w, onTop && isEnabled() ? kTextColor : kColor); setDirty(); @@ -640,7 +662,7 @@ SliderWidget::SliderWidget(GuiObject* boss, const GUI::Font& font, if(_valueLabelWidth == 0) _valueLabelGap = 0; if(_valueLabelGap == 0) - _valueLabelGap = DEF_LBL_GAP; + _valueLabelGap = font.getMaxCharWidth() / 2; _w = w + _labelWidth + _valueLabelGap + _valueLabelWidth; } @@ -807,9 +829,9 @@ void SliderWidget::drawWidget(bool hilite) s.drawString(_font, _label, _x, _y + 2, _labelWidth, isEnabled() ? kTextColor : kColor); int p = valueToPos(_value), - h = _h - 10, + h = _h - _font.getFontHeight() / 2 - 1, x = _x + _labelWidth, - y = _y + (_h - h) / 2 + 1; + y = _y + 2 + _font.desc().ascent - (_font.getFontHeight() + 1) / 2 - 1; // align to bottom of font // Fill the box s.fillRect(x, y, _w - _labelWidth - _valueLabelGap - _valueLabelWidth, h, diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx index aa45a5420..b20b8b159 100644 --- a/src/gui/Widget.hxx +++ b/src/gui/Widget.hxx @@ -23,14 +23,13 @@ class Dialog; -namespace GUI { - class Font; -} - #include #include "bspf.hxx" #include "Event.hxx" +#include "EventHandlerConstants.hxx" +#include "FrameBufferConstants.hxx" +#include "StellaKeys.hxx" #include "GuiObject.hxx" #include "Font.hxx" @@ -285,7 +284,14 @@ class CheckboxWidget : public ButtonWidget void handleMouseEntered() override; void handleMouseLeft() override; - static int boxSize() { return 14; } // box is square + static int boxSize(const GUI::Font& font) + { + return font.getFontHeight() < 24 ? 14 : 22; // box is square + } + static int prefixSize(const GUI::Font& font) + { + return boxSize(font) + font.getMaxCharWidth() * 0.75; + } protected: void drawWidget(bool hilite) override; @@ -296,10 +302,13 @@ class CheckboxWidget : public ButtonWidget bool _drawBox{true}; bool _changed{false}; + const uInt32* _outerCircle{nullptr}; + const uInt32* _innerCircle{nullptr}; const uInt32* _img{nullptr}; ColorId _fillColor{kColor}; int _boxY{0}; int _textY{0}; + int _boxSize{14}; private: // Following constructors and assignment operators not supported @@ -342,9 +351,6 @@ class SliderWidget : public ButtonWidget void setTickmarkIntervals(int numIntervals); - protected: - const int DEF_LBL_GAP = 4; - protected: void handleMouseMoved(int x, int y) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; diff --git a/src/gui/module.mk b/src/gui/module.mk index bb8943e85..e935a4c33 100644 --- a/src/gui/module.mk +++ b/src/gui/module.mk @@ -2,7 +2,6 @@ MODULE := src/gui MODULE_OBJS := \ src/gui/AboutDialog.o \ - src/gui/AudioDialog.o \ src/gui/BrowserDialog.o \ src/gui/CheckListWidget.o \ src/gui/ColorWidget.o \ @@ -15,6 +14,7 @@ MODULE_OBJS := \ src/gui/Dialog.o \ src/gui/EditableWidget.o \ src/gui/EditTextWidget.o \ + src/gui/EmulationDialog.o \ src/gui/EventMappingWidget.o \ src/gui/FileListWidget.o \ src/gui/Font.o \ @@ -51,7 +51,8 @@ MODULE_OBJS := \ src/gui/TimeMachineDialog.o \ src/gui/TimeMachine.o \ src/gui/UIDialog.o \ - src/gui/VideoDialog.o \ + src/gui/VideoAudioDialog.o \ + src/gui/WhatsNewDialog.o \ src/gui/Widget.o MODULE_DIRS += \ diff --git a/src/libpng/pngconf.h b/src/libpng/pngconf.h index 927a769db..b5f468ae5 100644 --- a/src/libpng/pngconf.h +++ b/src/libpng/pngconf.h @@ -230,7 +230,7 @@ * the type. */ # ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# define PNG_EXPORT_TYPE(name) name PNG_IMPEXP # endif # define PNG_DLL_EXPORT __export # else /* newer compiler */ @@ -450,7 +450,7 @@ # define PNG_FP_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) +# define PNG_FP_EXPORT(ordinal, name, name, args) # endif #endif #ifndef PNG_FIXED_EXPORT /* A fixed point API. */ @@ -458,7 +458,7 @@ # define PNG_FIXED_EXPORT(ordinal, type, name, args)\ PNG_EXPORT(ordinal, type, name, args); # else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# define PNG_FIXED_EXPORT(ordinal, name, name, args) # endif #endif diff --git a/src/libretro/FSNodeLIBRETRO.cxx b/src/libretro/FSNodeLIBRETRO.cxx index c2ee02b97..f3670f0a2 100644 --- a/src/libretro/FSNodeLIBRETRO.cxx +++ b/src/libretro/FSNodeLIBRETRO.cxx @@ -15,6 +15,8 @@ // this file, and for a DISCLAIMER OF ALL WARRANTIES. //============================================================================ +#include "bspf.hxx" +#include "Cart.hxx" #include "FSNodeLIBRETRO.hxx" #ifdef _WIN32 @@ -92,7 +94,7 @@ AbstractFSNodePtr FilesystemNodeLIBRETRO::getParent() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - size_t FilesystemNodeLIBRETRO::read(ByteBuffer& image) const { - image = make_unique(512 * 1024); + image = make_unique(Cartridge::maxSize()); extern uInt32 libretro_read_rom(void* data); return libretro_read_rom(image.get()); diff --git a/src/libretro/FrameBufferLIBRETRO.hxx b/src/libretro/FrameBufferLIBRETRO.hxx index 6b2035397..4ac6dbb30 100644 --- a/src/libretro/FrameBufferLIBRETRO.hxx +++ b/src/libretro/FrameBufferLIBRETRO.hxx @@ -115,6 +115,21 @@ class FrameBufferLIBRETRO : public FrameBuffer vector& windowedRes, VariantList& renderers) override; + /** + This method is called to query if the current window is not centered or fullscreen. + + @return True, if the current window is positioned + */ + bool isCurrentWindowPositioned() const override { return true; } + + /** + This method is called to query the video hardware for position of + the current window + + @return The position of the currently displayed window + */ + Common::Point getCurrentWindowPos() const override { return Common::Point{}; } + /** This method is called to query the video hardware for the index of the display the current window is displayed on @@ -122,12 +137,7 @@ class FrameBufferLIBRETRO : public FrameBuffer @return the current display index or a negative value if no window is displayed */ - Int32 getCurrentDisplayIndex() override { return 0; } - - /** - This method is called to preserve the last current windowed position. - */ - void updateWindowedPos() override { } + Int32 getCurrentDisplayIndex() const override { return 0; } /** This method is called to change to the given video mode. diff --git a/src/libretro/Makefile b/src/libretro/Makefile index a1bc5025a..8d17db9db 100644 --- a/src/libretro/Makefile +++ b/src/libretro/Makefile @@ -57,7 +57,7 @@ endif # Unix ifneq (,$(findstring unix,$(platform))) CXXFLAGS += $(LTO) - LDFLAGS += $(LTO) $(PTHREAD_FLAGS) + LDFLAGS += $(LTO) $(PTHREAD_FLAGS) -static-libgcc -static-libstdc++ TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC ifneq ($(findstring SunOS,$(shell uname -a)),) diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common index 34268a29d..994628725 100644 --- a/src/libretro/Makefile.common +++ b/src/libretro/Makefile.common @@ -23,6 +23,7 @@ SOURCES_CXX := \ $(CORE_DIR)/common/KeyMap.cxx \ $(CORE_DIR)/common/Logger.cxx \ $(CORE_DIR)/common/MouseControl.cxx \ + $(CORE_DIR)/common/PaletteHandler.cxx \ $(CORE_DIR)/common/PhosphorHandler.cxx \ $(CORE_DIR)/common/PhysicalJoystick.cxx \ $(CORE_DIR)/common/PJoystickHandler.cxx \ @@ -37,10 +38,15 @@ SOURCES_CXX := \ $(CORE_DIR)/emucore/AtariVox.cxx \ $(CORE_DIR)/emucore/Bankswitch.cxx \ $(CORE_DIR)/emucore/Booster.cxx \ + $(CORE_DIR)/emucore/Cart.cxx \ + $(CORE_DIR)/emucore/CartCreator.cxx \ + $(CORE_DIR)/emucore/CartDetector.cxx \ + $(CORE_DIR)/emucore/CartEnhanced.cxx \ $(CORE_DIR)/emucore/Cart0840.cxx \ $(CORE_DIR)/emucore/Cart2K.cxx \ $(CORE_DIR)/emucore/Cart3E.cxx \ $(CORE_DIR)/emucore/Cart3EPlus.cxx \ + $(CORE_DIR)/emucore/Cart3EX.cxx \ $(CORE_DIR)/emucore/Cart3F.cxx \ $(CORE_DIR)/emucore/Cart4A50.cxx \ $(CORE_DIR)/emucore/Cart4K.cxx \ @@ -53,10 +59,6 @@ SOURCES_CXX := \ $(CORE_DIR)/emucore/CartCM.cxx \ $(CORE_DIR)/emucore/CartCTY.cxx \ $(CORE_DIR)/emucore/CartCV.cxx \ - $(CORE_DIR)/emucore/CartCVPlus.cxx \ - $(CORE_DIR)/emucore/Cart.cxx \ - $(CORE_DIR)/emucore/CartDASH.cxx \ - $(CORE_DIR)/emucore/CartDetector.cxx \ $(CORE_DIR)/emucore/CartDF.cxx \ $(CORE_DIR)/emucore/CartDFSC.cxx \ $(CORE_DIR)/emucore/CartDPC.cxx \ @@ -80,6 +82,7 @@ SOURCES_CXX := \ $(CORE_DIR)/emucore/CartMDM.cxx \ $(CORE_DIR)/emucore/CartMNetwork.cxx \ $(CORE_DIR)/emucore/CartSB.cxx \ + $(CORE_DIR)/emucore/CartTVBoy.cxx \ $(CORE_DIR)/emucore/CartUA.cxx \ $(CORE_DIR)/emucore/CartWD.cxx \ $(CORE_DIR)/emucore/CartX07.cxx \ diff --git a/src/libretro/SoundLIBRETRO.cxx b/src/libretro/SoundLIBRETRO.cxx index 8d424b1fa..eef9c7dd5 100644 --- a/src/libretro/SoundLIBRETRO.cxx +++ b/src/libretro/SoundLIBRETRO.cxx @@ -120,4 +120,9 @@ void SoundLIBRETRO::dequeue(Int16* stream, uInt32* samples) *samples = outIndex / 2; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void SoundLIBRETRO::queryHardware(VariantList& devices) +{ +} + #endif // SOUND_SUPPORT diff --git a/src/libretro/SoundLIBRETRO.hxx b/src/libretro/SoundLIBRETRO.hxx index 9709e4b3d..7f68c0127 100644 --- a/src/libretro/SoundLIBRETRO.hxx +++ b/src/libretro/SoundLIBRETRO.hxx @@ -27,7 +27,6 @@ class AudioSettings; #include "bspf.hxx" #include "Sound.hxx" -#include "AudioQueue.hxx" /** This class implements the sound API for LIBRTRO. @@ -96,17 +95,15 @@ class SoundLIBRETRO : public Sound /** Adjusts the volume of the sound device based on the given direction. - @param direction Increase or decrease the current volume by a predefined - amount based on the direction (1 = increase, -1 = decrease) + @param direction +1 indicates increase, -1 indicates decrease. */ - void adjustVolume(Int8 direction) override { } + void adjustVolume(int direction = +1) override { } /** This method is called to provide information about the sound device. */ string about() const override { return ""; } - public: /** Empties the playback buffer. @@ -115,6 +112,14 @@ class SoundLIBRETRO : public Sound */ void dequeue(Int16* stream, uInt32* samples); + protected: + /** + This method is called to query the audio devices. + + @param devices List of device names + */ + void queryHardware(VariantList& devices) override; + private: // Indicates if the sound device was successfully initialized bool myIsInitializedFlag; diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx index f475fbc0b..38e52e734 100644 --- a/src/libretro/StellaLIBRETRO.cxx +++ b/src/libretro/StellaLIBRETRO.cxx @@ -21,6 +21,7 @@ #include "FrameBufferLIBRETRO.hxx" #include "AtariNTSC.hxx" +#include "PaletteHandler.hxx" #include "AudioSettings.hxx" #include "Serializer.hxx" #include "StateManager.hxx" @@ -28,7 +29,6 @@ #include "TIA.hxx" #include "TIASurface.hxx" - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - StellaLIBRETRO::StellaLIBRETRO() { @@ -40,7 +40,7 @@ StellaLIBRETRO::StellaLIBRETRO() video_aspect_ntsc = 0; video_aspect_pal = 0; - video_palette = "standard"; + video_palette = PaletteHandler::SETTING_STANDARD; video_filter = NTSCFilter::Preset::OFF; video_ready = false; @@ -61,8 +61,6 @@ bool StellaLIBRETRO::create(bool logging) { system_ready = false; - FilesystemNode rom("rom"); - // build play system destroy(); @@ -115,6 +113,8 @@ bool StellaLIBRETRO::create(bool logging) settings.setValue(AudioSettings::SETTING_VOLUME, 100); settings.setValue(AudioSettings::SETTING_STEREO, audio_mode); + FilesystemNode rom(rom_path); + if(myOSystem->createConsole(rom) != EmptyString) return false; @@ -188,7 +188,6 @@ void StellaLIBRETRO::updateVideo() if(tia.scanlines() == 0) break; } - video_ready = tia.newFramePending(); if (video_ready) @@ -221,7 +220,7 @@ bool StellaLIBRETRO::loadState(const void* data, size_t size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool StellaLIBRETRO::saveState(void* data, size_t size) +bool StellaLIBRETRO::saveState(void* data, size_t size) const { Serializer state; @@ -236,7 +235,7 @@ bool StellaLIBRETRO::saveState(void* data, size_t size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -size_t StellaLIBRETRO::getStateSize() +size_t StellaLIBRETRO::getStateSize() const { Serializer state; @@ -247,52 +246,52 @@ size_t StellaLIBRETRO::getStateSize() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -float StellaLIBRETRO::getVideoAspectPar() +float StellaLIBRETRO::getVideoAspectPar() const { float par; if (getVideoNTSC()) { - if (!video_aspect_ntsc) - { - if (video_filter != NTSCFilter::Preset::OFF) + if (!video_aspect_ntsc) { - // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels - par = (6.1363635f / 3.579545454f) / 2.0; + if (video_filter != NTSCFilter::Preset::OFF) + { + // non-interlace square pixel clock -- 1.0 pixel @ color burst -- double-width pixels + par = (6.1363635f / 3.579545454f) / 2.0; + } + else + { + // blargg filter + par = 1.0; + } } else - { - // blargg filter - par = 1.0; - } - } - else - par = video_aspect_ntsc / 100.0; + par = video_aspect_ntsc / 100.0; } else { - if (!video_aspect_pal) - { - if (video_filter != NTSCFilter::Preset::OFF) + if (!video_aspect_pal) { - // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels - par = (7.3750000f / (4.43361875f * 4.0f / 5.0f)) / 2.0f; + if (video_filter != NTSCFilter::Preset::OFF) + { + // non-interlace square pixel clock -- 0.8 pixel @ color burst -- double-width pixels + par = (7.3750000f / (4.43361875f * 4.0f / 5.0f)) / 2.0f; + } + else + { + // blargg filter + par = 1.0; + } } else - { - // blargg filter - par = 1.0; - } - } - else - par = video_aspect_pal / 100.0; + par = video_aspect_pal / 100.0; } return par; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -float StellaLIBRETRO::getVideoAspect() +float StellaLIBRETRO::getVideoAspect() const { uInt32 width = myOSystem->console().tia().width() * 2; @@ -301,7 +300,7 @@ float StellaLIBRETRO::getVideoAspect() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void* StellaLIBRETRO::getVideoBuffer() +void* StellaLIBRETRO::getVideoBuffer() const { FrameBufferLIBRETRO& frame = static_cast(myOSystem->frameBuffer()); @@ -309,7 +308,7 @@ void* StellaLIBRETRO::getVideoBuffer() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool StellaLIBRETRO::getVideoNTSC() +bool StellaLIBRETRO::getVideoNTSC() const { const ConsoleInfo& console_info = myOSystem->console().about(); string format = console_info.DisplayFormat; @@ -334,8 +333,10 @@ bool StellaLIBRETRO::getVideoResize() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaLIBRETRO::setROM(const void* data, size_t size) +void StellaLIBRETRO::setROM(const char* path, const void* data, size_t size) { + rom_path = path; + memcpy(rom_image.get(), data, size); rom_size = static_cast(size); @@ -346,13 +347,13 @@ void StellaLIBRETRO::setConsoleFormat(uInt32 mode) { switch(mode) { - case 0: console_format = "AUTO"; break; - case 1: console_format = "NTSC"; break; - case 2: console_format = "PAL"; break; - case 3: console_format = "SECAM"; break; - case 4: console_format = "NTSC50"; break; - case 5: console_format = "PAL60"; break; - case 6: console_format = "SECAM60"; break; + case 0: console_format = "AUTO"; break; + case 1: console_format = "NTSC"; break; + case 2: console_format = "PAL"; break; + case 3: console_format = "SECAM"; break; + case 4: console_format = "NTSC50"; break; + case 5: console_format = "PAL60"; break; + case 6: console_format = "SECAM60"; break; } if (system_ready) @@ -372,19 +373,12 @@ void StellaLIBRETRO::setVideoFilter(NTSCFilter::Preset mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void StellaLIBRETRO::setVideoPalette(uInt32 mode) +void StellaLIBRETRO::setVideoPalette(const string& mode) { - switch (mode) - { - case 0: video_palette = "standard"; break; - case 1: video_palette = "z26"; break; - case 2: video_palette = "user"; break; - } - if (system_ready) { myOSystem->settings().setValue("palette", video_palette); - myOSystem->console().setPalette(video_palette); + myOSystem->frameBuffer().tiaSurface().paletteHandler().setPalette(video_palette); } } @@ -393,9 +387,9 @@ void StellaLIBRETRO::setVideoPhosphor(uInt32 mode, uInt32 blend) { switch (mode) { - case 0: video_phosphor = "byrom"; break; - case 1: video_phosphor = "never"; break; - case 2: video_phosphor = "always"; break; + case 0: video_phosphor = "byrom"; break; + case 1: video_phosphor = "never"; break; + case 2: video_phosphor = "always"; break; } video_phosphor_blend = blend; @@ -419,9 +413,9 @@ void StellaLIBRETRO::setAudioStereo(int mode) { switch (mode) { - case 0: audio_mode = "byrom"; break; - case 1: audio_mode = "mono"; break; - case 2: audio_mode = "stereo"; break; + case 0: audio_mode = "byrom"; break; + case 1: audio_mode = "mono"; break; + case 2: audio_mode = "stereo"; break; } if (system_ready) diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx index 79ea4da0b..b3d87725b 100644 --- a/src/libretro/StellaLIBRETRO.hxx +++ b/src/libretro/StellaLIBRETRO.hxx @@ -21,6 +21,7 @@ #include "bspf.hxx" #include "OSystemLIBRETRO.hxx" +#include "Cart.hxx" #include "Console.hxx" #include "ConsoleTiming.hxx" #include "Control.hxx" @@ -32,7 +33,6 @@ #include "TIA.hxx" #include "TIASurface.hxx" - /** This class wraps Stella core for easier libretro maintenance */ @@ -52,69 +52,88 @@ class StellaLIBRETRO void runFrame(); bool loadState(const void* data, size_t size); - bool saveState(void* data, size_t size); + bool saveState(void* data, size_t size) const; public: - const char* getCoreName() { return "Stella"; } - const char* getROMExtensions() { return "a26|bin"; } + const char* getCoreName() const { return "Stella"; } + const char* getROMExtensions() const { return "a26|bin"; } - void* getROM() { return rom_image.get(); } - uInt32 getROMSize() { return rom_size; } - uInt32 getROMMax() { return 512 * 1024; } + void* getROM() const { return rom_image.get(); } + uInt32 getROMSize() const { return rom_size; } + constexpr uInt32 getROMMax() const { return Cartridge::maxSize(); } uInt8* getRAM() { return system_ram; } - uInt32 getRAMSize() { return 128; } + constexpr uInt32 getRAMSize() const { return 128; } - size_t getStateSize(); + size_t getStateSize() const; - bool getConsoleNTSC() { return console_timing == ConsoleTiming::ntsc; } + bool getConsoleNTSC() const { return console_timing == ConsoleTiming::ntsc; } - float getVideoAspectPar(); - float getVideoAspect(); - bool getVideoNTSC(); - float getVideoRate() { return getVideoNTSC() ? 60.0 : 50.0; } + float getVideoAspectPar() const; + float getVideoAspect() const; + bool getVideoNTSC() const; + float getVideoRate() const { return getVideoNTSC() ? 60.0 : 50.0; } - bool getVideoReady() { return video_ready; } - uInt32 getVideoZoom() { return myOSystem->frameBuffer().tiaSurface().ntscEnabled() ? 2 : 1; } + bool getVideoReady() const { return video_ready; } + uInt32 getVideoZoom() const { + return myOSystem->frameBuffer().tiaSurface().ntscEnabled() ? 2 : 1; + } bool getVideoResize(); - void* getVideoBuffer(); - uInt32 getVideoWidth() { return getVideoZoom()==1 ? myOSystem->console().tia().width() : getVideoWidthMax(); } - uInt32 getVideoHeight() { return myOSystem->console().tia().height(); } - uInt32 getVideoPitch() { return getVideoWidthMax() * 4; } + void* getVideoBuffer() const; + uInt32 getVideoWidth() const { + return getVideoZoom() == 1 ? myOSystem->console().tia().width() : getVideoWidthMax(); + } + uInt32 getVideoHeight() const { + return myOSystem->console().tia().height(); + } + constexpr uInt32 getVideoPitch() const { return getVideoWidthMax() * 4; } - uInt32 getVideoWidthMax() { return AtariNTSC::outWidth(160); } - uInt32 getVideoHeightMax() { return 312; } + constexpr uInt32 getVideoWidthMax() const { return AtariNTSC::outWidth(160); } + constexpr uInt32 getVideoHeightMax() const { return 312; } - uInt32 getRenderWidth() { return getVideoZoom()==1 ? myOSystem->console().tia().width() * 2 : getVideoWidthMax(); } - uInt32 getRenderHeight() { return myOSystem->console().tia().height() * getVideoZoom(); } + uInt32 getRenderWidth() const { + return getVideoZoom() == 1 ? myOSystem->console().tia().width() * 2 + : getVideoWidthMax(); + } + uInt32 getRenderHeight() const { + return myOSystem->console().tia().height() * getVideoZoom(); + } - float getAudioRate() { return getConsoleNTSC() ? (262 * 76 * 60) / 38.0 : (312 * 76 * 50) / 38.0; } - bool getAudioReady() { return audio_samples > 0; } - uInt32 getAudioSize() { return audio_samples; } + float getAudioRate() const { + return getConsoleNTSC() ? (262 * 76 * 60) / 38.0 : (312 * 76 * 50) / 38.0; + } + bool getAudioReady() const { return audio_samples > 0; } + uInt32 getAudioSize() const { return audio_samples; } Int16* getAudioBuffer() { return audio_buffer.get(); } public: - void setROM(const void* data, size_t size); + void setROM(const char* path, const void* data, size_t size); void setConsoleFormat(uInt32 mode); void setVideoAspectNTSC(uInt32 value) { video_aspect_ntsc = value; }; - void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; }; + void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; }; void setVideoFilter(NTSCFilter::Preset mode); - void setVideoPalette(uInt32 mode); + void setVideoPalette(const string& mode); void setVideoPhosphor(uInt32 mode, uInt32 blend); void setAudioStereo(int mode); - void setInputEvent(Event::Type type, Int32 state) { myOSystem->eventHandler().handleEvent(type, state); } + void setInputEvent(Event::Type type, Int32 state) { + myOSystem->eventHandler().handleEvent(type, state); + } - Controller::Type getLeftControllerType() { return myOSystem->console().leftController().type(); } - Controller::Type getRightControllerType() { return myOSystem->console().rightController().type(); } + Controller::Type getLeftControllerType() const { + return myOSystem->console().leftController().type(); + } + Controller::Type getRightControllerType() const { + return myOSystem->console().rightController().type(); + } - void setPaddleJoypadSensitivity(int sensitivity) + void setPaddleJoypadSensitivity(int sensitivity) { if(getLeftControllerType() == Controller::Type::Paddles) static_cast(myOSystem->console().leftController()).setDigitalSensitivity(sensitivity); @@ -137,8 +156,9 @@ class StellaLIBRETRO unique_ptr myOSystem; uInt32 system_ready; - unique_ptr rom_image; + ByteBuffer rom_image; uInt32 rom_size; + string rom_path; ConsoleTiming console_timing; string console_format; diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx index 6d1dc0f89..42408bd97 100644 --- a/src/libretro/libretro.cxx +++ b/src/libretro/libretro.cxx @@ -15,6 +15,7 @@ #include "StellaLIBRETRO.hxx" #include "Event.hxx" #include "NTSCFilter.hxx" +#include "PaletteHandler.hxx" #include "Version.hxx" @@ -30,11 +31,12 @@ static retro_audio_sample_batch_t audio_batch_cb; // libretro UI settings static int setting_ntsc, setting_pal; -static int setting_stereo, setting_palette; +static int setting_stereo; static int setting_phosphor, setting_console, setting_phosphor_blend; static int stella_paddle_joypad_sensitivity; static int setting_crop_hoverscan, crop_left; static NTSCFilter::Preset setting_filter; +static const char* setting_palette; static bool system_reset; @@ -275,17 +277,11 @@ static void update_variables(bool init = false) RETRO_GET("stella_palette") { - int value = 0; - - if(!strcmp(var.value, "standard")) value = 0; - else if(!strcmp(var.value, "z26")) value = 1; - else if(!strcmp(var.value, "user")) value = 2; - - if(setting_palette != value) + if(setting_palette != var.value) { - stella.setVideoPalette(value); + stella.setVideoPalette(var.value); - setting_palette = value; + setting_palette = var.value; } } @@ -494,7 +490,7 @@ void retro_set_environment(retro_environment_t cb) static struct retro_variable variables[] = { // Adding more variables and rearranging them is safe. { "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60" }, - { "stella_palette", "Palette colors; standard|z26|user" }, + { "stella_palette", "Palette colors; standard|z26|user|custom" }, { "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted" }, { "stella_ntsc_aspect", "NTSC aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, { "stella_pal_aspect", "PAL aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" }, @@ -563,7 +559,7 @@ bool retro_load_game(const struct retro_game_info *info) { 0, 0, 0, 0, NULL }, }; - if(!info || info->size >= stella.getROMMax()) return false; + if(!info || info->size > stella.getROMMax()) return false; environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); @@ -574,7 +570,7 @@ bool retro_load_game(const struct retro_game_info *info) } - stella.setROM(info->data, info->size); + stella.setROM(info->path, info->data, info->size); return reset_system(); } diff --git a/src/macos/Info-Stella.plist b/src/macos/Info-Stella.plist index 8f37a40c3..d9eb7520e 100644 --- a/src/macos/Info-Stella.plist +++ b/src/macos/Info-Stella.plist @@ -45,7 +45,7 @@ CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion - 6.1 + 6.2.1 CFBundleName Stella CFBundlePackageType @@ -53,7 +53,7 @@ CFBundleSignature StLa CFBundleVersion - 6.1 + 6.2.1 LSApplicationCategoryType public.app-category.games LSMinimumSystemVersionByArchitecture diff --git a/src/macos/SerialPortMACOS.cxx b/src/macos/SerialPortMACOS.cxx index 90235e0a8..9745eceff 100644 --- a/src/macos/SerialPortMACOS.cxx +++ b/src/macos/SerialPortMACOS.cxx @@ -73,3 +73,15 @@ bool SerialPortMACOS::writeByte(uInt8 data) } return false; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool SerialPortMACOS::isCTS() +{ + if(myHandle) + { + int status = 0; + ioctl(myHandle, TIOCMGET, &status); + return status & TIOCM_CTS; + } + return false; +} diff --git a/src/macos/SerialPortMACOS.hxx b/src/macos/SerialPortMACOS.hxx index 0c83e5045..3d71d5135 100644 --- a/src/macos/SerialPortMACOS.hxx +++ b/src/macos/SerialPortMACOS.hxx @@ -48,6 +48,13 @@ class SerialPortMACOS : public SerialPort */ bool writeByte(uInt8 data) override; + /** + Test for 'Clear To Send' enabled. + + @return True if CTS signal enabled, else false + */ + bool isCTS() override; + private: // File descriptor for serial connection int myHandle{0}; diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj index 4f96dff80..44732af79 100644 --- a/src/macos/stella.xcodeproj/project.pbxproj +++ b/src/macos/stella.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ 2D9173FA09BA90380026E9FF /* FrameBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D71062895B2006265D9 /* FrameBuffer.hxx */; }; 2D9173FB09BA90380026E9FF /* Settings.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D77062895F1006265D9 /* Settings.hxx */; }; 2D91740009BA90380026E9FF /* AboutDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */; }; - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */; }; 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */; }; 2D91740309BA90380026E9FF /* Command.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAA084578BF00812C11 /* Command.hxx */; }; 2D91740409BA90380026E9FF /* Dialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAC084578BF00812C11 /* Dialog.hxx */; }; @@ -61,7 +60,6 @@ 2D91741209BA90380026E9FF /* ProgressDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAC9084578BF00812C11 /* ProgressDialog.hxx */; }; 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */; }; 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */; }; - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */; }; 2D91741809BA90380026E9FF /* Widget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD5084578BF00812C11 /* Widget.hxx */; }; 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7108457B7D00812C11 /* CartUA.hxx */; }; 2D91741A09BA90380026E9FF /* FSNode.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7308457B7D00812C11 /* FSNode.hxx */; }; @@ -142,7 +140,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2D944848062904E800DD9879 /* Settings.cxx */; }; 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */; }; 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */; }; - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */; }; 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */; }; 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAB084578BF00812C11 /* Dialog.cxx */; }; 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAD084578BF00812C11 /* DialogContainer.cxx */; }; @@ -157,7 +154,6 @@ 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAC8084578BF00812C11 /* ProgressDialog.cxx */; }; 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEACA084578BF00812C11 /* ScrollBarWidget.cxx */; }; 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */; }; - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */; }; 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD4084578BF00812C11 /* Widget.cxx */; }; 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7008457B7D00812C11 /* CartUA.cxx */; }; 2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7208457B7D00812C11 /* FSNode.cxx */; }; @@ -226,6 +222,8 @@ DC1B2EC81E50036100F62837 /* TrakBall.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC1B2EC21E50036100F62837 /* TrakBall.hxx */; }; DC1BC6662066B4390076F74A /* PKeyboardHandler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC1BC6642066B4390076F74A /* PKeyboardHandler.cxx */; }; DC1BC6672066B4390076F74A /* PKeyboardHandler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC1BC6652066B4390076F74A /* PKeyboardHandler.hxx */; }; + DC1E474E24D34F3B0047E61A /* WhatsNewDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC1E474C24D34F3A0047E61A /* WhatsNewDialog.cxx */; }; + DC1E474F24D34F3B0047E61A /* WhatsNewDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC1E474D24D34F3A0047E61A /* WhatsNewDialog.hxx */; }; DC21E5BF21CA903E007D0E1A /* OSystemMACOS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC21E5B921CA903E007D0E1A /* OSystemMACOS.cxx */; }; DC21E5C021CA903E007D0E1A /* OSystemMACOS.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC21E5BA21CA903E007D0E1A /* OSystemMACOS.hxx */; }; DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC21E5BB21CA903E007D0E1A /* SerialPortMACOS.cxx */; }; @@ -233,8 +231,6 @@ DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */; }; DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */; }; DC2874071F8F2278004BF21A /* TrapArray.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2874061F8F2278004BF21A /* TrapArray.hxx */; }; - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */; }; - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */; }; DC2AADB0194F389C0026C7A4 /* TIASurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */; }; DC2AADB1194F389C0026C7A4 /* TIASurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */; }; DC2AADB4194F390F0026C7A4 /* CartRamWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */; }; @@ -250,6 +246,18 @@ DC368F5918A2FB710084199C /* SoundSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC368F5318A2FB710084199C /* SoundSDL2.hxx */; }; DC36D2C814CAFAB0007DC821 /* CartFA2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */; }; DC36D2C914CAFAB0007DC821 /* CartFA2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */; }; + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */; }; + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */; }; + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */; }; + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */; }; + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */; }; + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */; }; + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */; }; + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */; }; + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */; }; + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */; }; + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */; }; + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */; }; DC3DAFAC1F2E233B00A64410 /* PointingDevice.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */; }; DC3EE8561E2C0E6D00905161 /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83C1E2C0E6D00905161 /* adler32.c */; settings = {COMPILER_FLAGS = "-w"; }; }; DC3EE8571E2C0E6D00905161 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83D1E2C0E6D00905161 /* compress.c */; settings = {COMPILER_FLAGS = "-w"; }; }; @@ -375,6 +383,9 @@ DC6F394A21B897C700897AD8 /* FatalEmulationError.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6F394821B897C700897AD8 /* FatalEmulationError.hxx */; }; DC6F394D21B897F300897AD8 /* ThreadDebugging.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC6F394B21B897F300897AD8 /* ThreadDebugging.cxx */; }; DC6F394E21B897F300897AD8 /* ThreadDebugging.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC6F394C21B897F300897AD8 /* ThreadDebugging.hxx */; }; + DC70065C241EC97900A459AB /* Stella12x24tFont.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC700659241EC97900A459AB /* Stella12x24tFont.hxx */; }; + DC70065D241EC97900A459AB /* Stella16x32tFont.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC70065A241EC97900A459AB /* Stella16x32tFont.hxx */; }; + DC70065E241EC97900A459AB /* Stella14x28tFont.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC70065B241EC97900A459AB /* Stella14x28tFont.hxx */; }; DC71C399221623D9005DE92F /* ControllerDetector.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC71C397221623D8005DE92F /* ControllerDetector.hxx */; }; DC71C39A221623D9005DE92F /* ControllerDetector.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC71C398221623D9005DE92F /* ControllerDetector.cxx */; }; DC71EA9D1FDA06D2008827CB /* CartE78K.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC71EA991FDA06D2008827CB /* CartE78K.cxx */; }; @@ -390,8 +401,6 @@ DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; }; DC73BD8A1915E5E3003FAFAD /* FBSurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD881915E5E3003FAFAD /* FBSurface.hxx */; }; DC74D6A2138D4D7E00F05C5C /* StringParser.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */; }; - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */; }; - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */; }; DC79F81217A88D9E00288B91 /* Base.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC79F81017A88D9E00288B91 /* Base.cxx */; }; DC79F81317A88D9E00288B91 /* Base.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC79F81117A88D9E00288B91 /* Base.hxx */; }; DC7A24D5173B1CF600B20FE9 /* Variant.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC7A24D4173B1CF600B20FE9 /* Variant.hxx */; }; @@ -400,6 +409,12 @@ DC8078DB0B4BD5F3005E9305 /* DebuggerExpressions.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8078DA0B4BD5F3005E9305 /* DebuggerExpressions.hxx */; }; DC8078EA0B4BD697005E9305 /* UIDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8078E60B4BD697005E9305 /* UIDialog.cxx */; }; DC8078EB0B4BD697005E9305 /* UIDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8078E70B4BD697005E9305 /* UIDialog.hxx */; }; + DC84397B247B294E00C6A4FC /* CartTVBoy.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC843979247B294D00C6A4FC /* CartTVBoy.hxx */; }; + DC84397C247B294E00C6A4FC /* CartTVBoy.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */; }; + DC84397F247B297A00C6A4FC /* CartTVBoyWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */; }; + DC843980247B297A00C6A4FC /* CartTVBoyWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */; }; + DC857D352482F66200C7C14F /* CartCreator.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC857D332482F66200C7C14F /* CartCreator.cxx */; }; + DC857D362482F66200C7C14F /* CartCreator.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC857D342482F66200C7C14F /* CartCreator.hxx */; }; DC8C1BAD14B25DE7006440EE /* CartCM.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8C1BA714B25DE7006440EE /* CartCM.cxx */; }; DC8C1BAE14B25DE7006440EE /* CartCM.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC8C1BA814B25DE7006440EE /* CartCM.hxx */; }; DC8C1BAF14B25DE7006440EE /* CompuMate.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC8C1BA914B25DE7006440EE /* CompuMate.cxx */; }; @@ -491,10 +506,6 @@ DCAAE5F11715887B0080BB82 /* CartFAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */; }; DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */; }; DCAAE5F31715887B0080BB82 /* CartUAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */; }; - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */; }; - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */; }; - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBAD21C54298300703A9B /* CartCVPlus.cxx */; }; - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBAD31C54298300703A9B /* CartCVPlus.hxx */; }; DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */; }; DCAD60A91152F8BD00BC4184 /* CartDPCPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */; }; DCB20EC71A0C506C0048F595 /* main.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCB20EC61A0C506C0048F595 /* main.cxx */; }; @@ -697,6 +708,8 @@ isa = PBXBuildRule; compilerSpec = com.apple.compilers.llvm.clang.1_0; fileType = sourcecode.c; + inputFiles = ( + ); isEditable = 1; outputFiles = ( ); @@ -706,6 +719,8 @@ isa = PBXBuildRule; compilerSpec = com.apple.compilers.llvm.clang.1_0; fileType = sourcecode.asm; + inputFiles = ( + ); isEditable = 1; outputFiles = ( ); @@ -715,6 +730,8 @@ isa = PBXBuildRule; compilerSpec = com.apple.compilers.llvm.clang.1_0; fileType = sourcecode.cpp; + inputFiles = ( + ); isEditable = 1; outputFiles = ( ); @@ -825,8 +842,6 @@ 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FSNodePOSIX.cxx; sourceTree = ""; }; 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AboutDialog.cxx; sourceTree = ""; }; 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AboutDialog.hxx; sourceTree = ""; }; - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDialog.cxx; sourceTree = ""; }; - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AudioDialog.hxx; sourceTree = ""; }; 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BrowserDialog.cxx; sourceTree = ""; }; 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = BrowserDialog.hxx; sourceTree = ""; }; 2DDBEAAA084578BF00812C11 /* Command.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Command.hxx; sourceTree = ""; }; @@ -857,8 +872,6 @@ 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ScrollBarWidget.hxx; sourceTree = ""; }; 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TabWidget.cxx; sourceTree = ""; }; 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = TabWidget.hxx; sourceTree = ""; }; - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDialog.cxx; sourceTree = ""; }; - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = VideoDialog.hxx; sourceTree = ""; }; 2DDBEAD4084578BF00812C11 /* Widget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Widget.cxx; sourceTree = ""; }; 2DDBEAD5084578BF00812C11 /* Widget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Widget.hxx; sourceTree = ""; }; 2DDBEB7008457B7D00812C11 /* CartUA.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartUA.cxx; sourceTree = ""; }; @@ -962,6 +975,8 @@ DC1B2EC21E50036100F62837 /* TrakBall.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrakBall.hxx; sourceTree = ""; }; DC1BC6642066B4390076F74A /* PKeyboardHandler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PKeyboardHandler.cxx; sourceTree = ""; }; DC1BC6652066B4390076F74A /* PKeyboardHandler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PKeyboardHandler.hxx; sourceTree = ""; }; + DC1E474C24D34F3A0047E61A /* WhatsNewDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WhatsNewDialog.cxx; sourceTree = ""; }; + DC1E474D24D34F3A0047E61A /* WhatsNewDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = WhatsNewDialog.hxx; sourceTree = ""; }; DC21E5B921CA903E007D0E1A /* OSystemMACOS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSystemMACOS.cxx; sourceTree = SOURCE_ROOT; }; DC21E5BA21CA903E007D0E1A /* OSystemMACOS.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OSystemMACOS.hxx; sourceTree = SOURCE_ROOT; }; DC21E5BB21CA903E007D0E1A /* SerialPortMACOS.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerialPortMACOS.cxx; sourceTree = SOURCE_ROOT; }; @@ -969,8 +984,6 @@ DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MinUICommandDialog.hxx; sourceTree = ""; }; DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinUICommandDialog.cxx; sourceTree = ""; }; DC2874061F8F2278004BF21A /* TrapArray.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrapArray.hxx; sourceTree = ""; }; - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASH.cxx; sourceTree = ""; }; - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASH.hxx; sourceTree = ""; }; DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TIASurface.cxx; sourceTree = ""; }; DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TIASurface.hxx; sourceTree = ""; }; DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartRamWidget.cxx; sourceTree = ""; }; @@ -986,6 +999,18 @@ DC368F5318A2FB710084199C /* SoundSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundSDL2.hxx; sourceTree = ""; }; DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartFA2.cxx; sourceTree = ""; }; DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFA2.hxx; sourceTree = ""; }; + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaletteHandler.cxx; sourceTree = ""; }; + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PaletteHandler.hxx; sourceTree = ""; }; + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoAudioDialog.cxx; sourceTree = ""; }; + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationDialog.cxx; sourceTree = ""; }; + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VideoAudioDialog.hxx; sourceTree = ""; }; + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EmulationDialog.hxx; sourceTree = ""; }; + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhanced.cxx; sourceTree = ""; }; + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cart3EX.hxx; sourceTree = ""; }; + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhanced.hxx; sourceTree = ""; }; + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cart3EX.cxx; sourceTree = ""; }; + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhancedWidget.cxx; sourceTree = ""; }; + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhancedWidget.hxx; sourceTree = ""; }; DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PointingDevice.hxx; sourceTree = ""; }; DC3EE83C1E2C0E6D00905161 /* adler32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adler32.c; sourceTree = ""; }; DC3EE83D1E2C0E6D00905161 /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; }; @@ -1111,6 +1136,9 @@ DC6F394821B897C700897AD8 /* FatalEmulationError.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = FatalEmulationError.hxx; path = exception/FatalEmulationError.hxx; sourceTree = ""; }; DC6F394B21B897F300897AD8 /* ThreadDebugging.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadDebugging.cxx; sourceTree = ""; }; DC6F394C21B897F300897AD8 /* ThreadDebugging.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ThreadDebugging.hxx; sourceTree = ""; }; + DC700659241EC97900A459AB /* Stella12x24tFont.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stella12x24tFont.hxx; sourceTree = ""; }; + DC70065A241EC97900A459AB /* Stella16x32tFont.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stella16x32tFont.hxx; sourceTree = ""; }; + DC70065B241EC97900A459AB /* Stella14x28tFont.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stella14x28tFont.hxx; sourceTree = ""; }; DC71C397221623D8005DE92F /* ControllerDetector.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ControllerDetector.hxx; sourceTree = ""; }; DC71C398221623D9005DE92F /* ControllerDetector.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ControllerDetector.cxx; sourceTree = ""; }; DC71EA991FDA06D2008827CB /* CartE78K.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartE78K.cxx; sourceTree = ""; }; @@ -1126,8 +1154,6 @@ DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = ""; }; DC73BD881915E5E3003FAFAD /* FBSurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurface.hxx; sourceTree = ""; }; DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringParser.hxx; sourceTree = ""; }; - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASHWidget.cxx; sourceTree = ""; }; - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASHWidget.hxx; sourceTree = ""; }; DC79F81017A88D9E00288B91 /* Base.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base.cxx; sourceTree = ""; }; DC79F81117A88D9E00288B91 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hxx; sourceTree = ""; }; DC7A24D4173B1CF600B20FE9 /* Variant.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Variant.hxx; sourceTree = ""; }; @@ -1136,6 +1162,12 @@ DC8078DA0B4BD5F3005E9305 /* DebuggerExpressions.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = DebuggerExpressions.hxx; sourceTree = ""; }; DC8078E60B4BD697005E9305 /* UIDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = UIDialog.cxx; sourceTree = ""; }; DC8078E70B4BD697005E9305 /* UIDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = UIDialog.hxx; sourceTree = ""; }; + DC843979247B294D00C6A4FC /* CartTVBoy.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartTVBoy.hxx; sourceTree = ""; }; + DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartTVBoy.cxx; sourceTree = ""; }; + DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartTVBoyWidget.hxx; sourceTree = ""; }; + DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartTVBoyWidget.cxx; sourceTree = ""; }; + DC857D332482F66200C7C14F /* CartCreator.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCreator.cxx; sourceTree = ""; }; + DC857D342482F66200C7C14F /* CartCreator.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCreator.hxx; sourceTree = ""; }; DC8C1BA714B25DE7006440EE /* CartCM.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCM.cxx; sourceTree = ""; }; DC8C1BA814B25DE7006440EE /* CartCM.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCM.hxx; sourceTree = ""; }; DC8C1BA914B25DE7006440EE /* CompuMate.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompuMate.cxx; sourceTree = ""; }; @@ -1228,10 +1260,6 @@ DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFAWidget.hxx; sourceTree = ""; }; DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartUAWidget.cxx; sourceTree = ""; }; DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartUAWidget.hxx; sourceTree = ""; }; - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlusWidget.cxx; sourceTree = ""; }; - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlusWidget.hxx; sourceTree = ""; }; - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlus.cxx; sourceTree = ""; }; - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlus.hxx; sourceTree = ""; }; DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDPCPlus.cxx; sourceTree = ""; }; DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDPCPlus.hxx; sourceTree = ""; }; DCB20EC61A0C506C0048F595 /* main.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cxx; sourceTree = ""; }; @@ -1583,12 +1611,8 @@ DC676A2C1729A0B000E4E73D /* CartCMWidget.hxx */, DC676A2D1729A0B000E4E73D /* CartCTYWidget.cxx */, DC676A2E1729A0B000E4E73D /* CartCTYWidget.hxx */, - DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */, - DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */, DCAAE5BA1715887B0080BB82 /* CartCVWidget.cxx */, DCAAE5BB1715887B0080BB82 /* CartCVWidget.hxx */, - DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */, - DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */, DC5ACB5D1FBFCEB800A213FD /* CartDebugWidget.cxx */, DCAAE5BC1715887B0080BB82 /* CartDebugWidget.hxx */, DCAACB0A188D636F00A4D282 /* CartDFSCWidget.cxx */, @@ -1609,6 +1633,8 @@ DCAAE5BE1715887B0080BB82 /* CartEFSCWidget.hxx */, DCAAE5BF1715887B0080BB82 /* CartEFWidget.cxx */, DCAAE5C01715887B0080BB82 /* CartEFWidget.hxx */, + DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */, + DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */, DCAAE5C11715887B0080BB82 /* CartF0Widget.cxx */, DCAAE5C21715887B0080BB82 /* CartF0Widget.hxx */, DCAAE5C31715887B0080BB82 /* CartF4SCWidget.cxx */, @@ -1639,6 +1665,8 @@ DC2AADB3194F390F0026C7A4 /* CartRamWidget.hxx */, DC676A3D1729A0B000E4E73D /* CartSBWidget.cxx */, DC676A3E1729A0B000E4E73D /* CartSBWidget.hxx */, + DC84397E247B297A00C6A4FC /* CartTVBoyWidget.cxx */, + DC84397D247B297A00C6A4FC /* CartTVBoyWidget.hxx */, DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */, DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */, DC6D39851A3CE65000171E71 /* CartWDWidget.cxx */, @@ -1738,6 +1766,8 @@ DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */, DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */, DC56FCDD14CCCC4900A31CC3 /* MouseControl.hxx */, + DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */, + DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */, DCA233AE23B583FE0032ABF3 /* PhosphorHandler.cxx */, DCA233AF23B583FE0032ABF3 /* PhosphorHandler.hxx */, DC6DC91A205DB879004A5FC3 /* PhysicalJoystick.cxx */, @@ -1818,6 +1848,8 @@ 2D9555DA0880E78000466554 /* Cart3E.hxx */, DCBDDE9C1D6A5F2F009DF1E9 /* Cart3EPlus.cxx */, DCBDDE9D1D6A5F2F009DF1E9 /* Cart3EPlus.hxx */, + DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */, + DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */, 2DE2DF160627AE07006BEC99 /* Cart3F.cxx */, 2DE2DF170627AE07006BEC99 /* Cart3F.hxx */, DCD56D360B247D920092F9F8 /* Cart4A50.cxx */, @@ -1840,14 +1872,12 @@ CFE3F6121E84A9CE00A8204E /* CartCDF.hxx */, DC8C1BA714B25DE7006440EE /* CartCM.cxx */, DC8C1BA814B25DE7006440EE /* CartCM.hxx */, + DC857D332482F66200C7C14F /* CartCreator.cxx */, + DC857D342482F66200C7C14F /* CartCreator.hxx */, DC6727081556F4860023653B /* CartCTY.cxx */, DC6727091556F4860023653B /* CartCTY.hxx */, 2DE2DF1C0627AE07006BEC99 /* CartCV.cxx */, 2DE2DF1D0627AE07006BEC99 /* CartCV.hxx */, - DCACBAD21C54298300703A9B /* CartCVPlus.cxx */, - DCACBAD31C54298300703A9B /* CartCVPlus.hxx */, - DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */, - DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */, DCB2ECAC1F0AECA3009738A6 /* CartDetector.cxx */, DCB2ECAD1F0AECA3009738A6 /* CartDetector.hxx */, DCAACAF2188D631500A4D282 /* CartDF.cxx */, @@ -1868,6 +1898,8 @@ DCF467BF0F939A1400B25D7A /* CartEF.hxx */, DCF467C00F939A1400B25D7A /* CartEFSC.cxx */, DCF467C10F939A1400B25D7A /* CartEFSC.hxx */, + DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */, + DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */, DCF7B0D910A762FC007A2870 /* CartF0.cxx */, DCF7B0DA10A762FC007A2870 /* CartF0.hxx */, 2DE2DF240627AE07006BEC99 /* CartF4.cxx */, @@ -1896,6 +1928,8 @@ DC71EA9C1FDA06D2008827CB /* CartMNetwork.hxx */, DC0984830D3985160073C852 /* CartSB.cxx */, DC0984840D3985160073C852 /* CartSB.hxx */, + DC84397A247B294D00C6A4FC /* CartTVBoy.cxx */, + DC843979247B294D00C6A4FC /* CartTVBoy.hxx */, 2DDBEB7008457B7D00812C11 /* CartUA.cxx */, 2DDBEB7108457B7D00812C11 /* CartUA.hxx */, DCDA03AE1A2009BA00711920 /* CartWD.cxx */, @@ -1997,8 +2031,6 @@ children = ( 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */, 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */, - 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */, - 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */, 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */, 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */, 2DEF21F808BC033500B246B4 /* CheckListWidget.cxx */, @@ -2028,6 +2060,8 @@ 2D403BA1086116D1001E31A1 /* EditableWidget.hxx */, 2D403BA4086116D1001E31A1 /* EditTextWidget.cxx */, 2D403BA5086116D1001E31A1 /* EditTextWidget.hxx */, + DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */, + DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */, 2D05FF5E096E269100A518FE /* EventMappingWidget.cxx */, 2D05FF5F096E269100A518FE /* EventMappingWidget.hxx */, DC7A24DD173B1DBC00B20FE9 /* FileListWidget.cxx */, @@ -2081,6 +2115,9 @@ 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */, DCDE17F817724E5D00EB1AC6 /* SnapshotDialog.cxx */, DCDE17F917724E5D00EB1AC6 /* SnapshotDialog.hxx */, + DC700659241EC97900A459AB /* Stella12x24tFont.hxx */, + DC70065B241EC97900A459AB /* Stella14x28tFont.hxx */, + DC70065A241EC97900A459AB /* Stella16x32tFont.hxx */, DC5D2C4F0F117CFD004D1660 /* StellaFont.hxx */, DC5D2C500F117CFD004D1660 /* StellaLargeFont.hxx */, DC5D2C510F117CFD004D1660 /* StellaMediumFont.hxx */, @@ -2098,8 +2135,10 @@ DCA82C701FEB4E780059340F /* TimeMachineDialog.hxx */, DC8078E60B4BD697005E9305 /* UIDialog.cxx */, DC8078E70B4BD697005E9305 /* UIDialog.hxx */, - 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */, - 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */, + DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */, + DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */, + DC1E474C24D34F3A0047E61A /* WhatsNewDialog.cxx */, + DC1E474D24D34F3A0047E61A /* WhatsNewDialog.hxx */, 2DDBEAD4084578BF00812C11 /* Widget.cxx */, 2DDBEAD5084578BF00812C11 /* Widget.hxx */, ); @@ -2353,6 +2392,7 @@ 2D9173CF09BA90380026E9FF /* Cart3F.hxx in Headers */, DC3EE86D1E2C0E6D00905161 /* zlib.h in Headers */, E08FCD5523A037EB0051F59B /* Blitter.hxx in Headers */, + DC84397F247B297A00C6A4FC /* CartTVBoyWidget.hxx in Headers */, E034A5EF209FB25D00C89E9E /* EmulationTiming.hxx in Headers */, DC3EE86A1E2C0E6D00905161 /* trees.h in Headers */, 2D9173D009BA90380026E9FF /* Cart4K.hxx in Headers */, @@ -2382,10 +2422,9 @@ DC5AAC2D1FCB24DF00C420A6 /* RadioButtonWidget.hxx in Headers */, 2D9173E309BA90380026E9FF /* Driving.hxx in Headers */, 2D9173E409BA90380026E9FF /* Event.hxx in Headers */, + DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */, 2D9173E509BA90380026E9FF /* Joystick.hxx in Headers */, 2D9173E609BA90380026E9FF /* Keyboard.hxx in Headers */, - DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */, - DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */, DC1B2EC81E50036100F62837 /* TrakBall.hxx in Headers */, 2D9173E709BA90380026E9FF /* M6532.hxx in Headers */, E0893AF3211B9842008B170D /* HighPass.hxx in Headers */, @@ -2408,7 +2447,7 @@ DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */, DC96162F1F817830008A2206 /* AtariMouseWidget.hxx in Headers */, DCF4907A1A0ECE5B00A67AA9 /* Vec.hxx in Headers */, - 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */, + DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */, DC71EA9E1FDA06D2008827CB /* CartE78K.hxx in Headers */, 2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */, 2D91740309BA90380026E9FF /* Command.hxx in Headers */, @@ -2437,7 +2476,6 @@ 2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */, 2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */, DCB2ECB01F0AECA3009738A6 /* CartDetector.hxx in Headers */, - 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */, 2D91741809BA90380026E9FF /* Widget.hxx in Headers */, 2D91741909BA90380026E9FF /* CartUA.hxx in Headers */, DCE8B1871E7E03B300189864 /* FrameLayout.hxx in Headers */, @@ -2467,6 +2505,7 @@ DC3EE86C1E2C0E6D00905161 /* zconf.h in Headers */, 2D91743609BA90380026E9FF /* DebuggerSystem.hxx in Headers */, 2D91743A09BA90380026E9FF /* Expression.hxx in Headers */, + DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */, 2D91744F09BA90380026E9FF /* InputTextDialog.hxx in Headers */, DC1B2EC61E50036100F62837 /* AtariMouse.hxx in Headers */, DC9616331F817830008A2206 /* PointingDeviceWidget.hxx in Headers */, @@ -2476,6 +2515,7 @@ 2D91745209BA90380026E9FF /* CommandDialog.hxx in Headers */, 2D91745309BA90380026E9FF /* CommandMenu.hxx in Headers */, E0306E111F93E916003DDD52 /* JitterEmulation.hxx in Headers */, + DC1E474F24D34F3B0047E61A /* WhatsNewDialog.hxx in Headers */, 2D91745509BA90380026E9FF /* CpuWidget.hxx in Headers */, 2D91745609BA90380026E9FF /* DataGridOpsWidget.hxx in Headers */, 2D91745709BA90380026E9FF /* DataGridWidget.hxx in Headers */, @@ -2493,7 +2533,7 @@ DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */, DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */, 2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */, - DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */, + DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */, 2D91745A09BA90380026E9FF /* RamWidget.hxx in Headers */, 2D91745B09BA90380026E9FF /* RomListWidget.hxx in Headers */, 2D91745C09BA90380026E9FF /* RomWidget.hxx in Headers */, @@ -2504,8 +2544,10 @@ 2D91746109BA90380026E9FF /* TogglePixelWidget.hxx in Headers */, 2D91746209BA90380026E9FF /* ToggleWidget.hxx in Headers */, 2D91746409BA90380026E9FF /* TiaZoomWidget.hxx in Headers */, + DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */, DC1BC6672066B4390076F74A /* PKeyboardHandler.hxx in Headers */, 2D91746609BA90380026E9FF /* AudioWidget.hxx in Headers */, + DC70065E241EC97900A459AB /* Stella14x28tFont.hxx in Headers */, 2D91746909BA90380026E9FF /* EventMappingWidget.hxx in Headers */, 2D91746A09BA90380026E9FF /* InputDialog.hxx in Headers */, DC47455609C34BFA00EDDA3A /* BankRomCheat.hxx in Headers */, @@ -2534,6 +2576,7 @@ DC4613680D92C03600D8DAB9 /* RomAuditDialog.hxx in Headers */, DC487FB70DA5350900E12499 /* AtariVox.hxx in Headers */, DC11F78E0DB36933003B505E /* MT24LC256.hxx in Headers */, + DC70065C241EC97900A459AB /* Stella12x24tFont.hxx in Headers */, DCA00FF80DBABCAD00C3823D /* RiotDebug.hxx in Headers */, DC4AC6F00DC8DACB00CD3AD2 /* RiotWidget.hxx in Headers */, DCA233B123B583FE0032ABF3 /* PhosphorHandler.hxx in Headers */, @@ -2552,6 +2595,7 @@ DC9EA8880F729A36000452B5 /* KidVid.hxx in Headers */, DCF7F128223D796000701A47 /* ConsoleIO.hxx in Headers */, DCF467B80F93993B00B25D7A /* SoundNull.hxx in Headers */, + DC857D362482F66200C7C14F /* CartCreator.hxx in Headers */, DCBDDE9F1D6A5F2F009DF1E9 /* Cart3EPlus.hxx in Headers */, DCF467BD0F9399F500B25D7A /* Version.hxx in Headers */, DC2B85E81EF5EF2300379EB9 /* AtariNTSC.hxx in Headers */, @@ -2582,7 +2626,6 @@ DCD6FC7111C281ED005DA767 /* png.h in Headers */, DCD6FC7211C281ED005DA767 /* pngconf.h in Headers */, DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */, - DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */, DCD6FC7711C281ED005DA767 /* pngpriv.h in Headers */, CFE3F60C1E84A9A200A8204E /* CartBUSWidget.hxx in Headers */, DCD6FC9411C28C6F005DA767 /* PNGLibrary.hxx in Headers */, @@ -2626,6 +2669,7 @@ DCE395EF16CB0B5F008DB1E5 /* FSNodeFactory.hxx in Headers */, DCE395F116CB0B5F008DB1E5 /* FSNodeZIP.hxx in Headers */, DCE395F316CB0B5F008DB1E5 /* ZipHandler.hxx in Headers */, + DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */, DCAAE5D41715887B0080BB82 /* Cart2KWidget.hxx in Headers */, DCF7F129223D796000701A47 /* ProfilingRunner.hxx in Headers */, DCAAE5D61715887B0080BB82 /* Cart3FWidget.hxx in Headers */, @@ -2637,6 +2681,7 @@ DC6DC921205DB879004A5FC3 /* PJoystickHandler.hxx in Headers */, DCAAE5DF1715887B0080BB82 /* CartEFSCWidget.hxx in Headers */, DCAAE5E11715887B0080BB82 /* CartEFWidget.hxx in Headers */, + DC70065D241EC97900A459AB /* Stella16x32tFont.hxx in Headers */, DCDFF08220B781B0001227C0 /* DispatchResult.hxx in Headers */, DCF8621A21C9D43300F95F52 /* StaggeredLogger.hxx in Headers */, DCAAE5E31715887B0080BB82 /* CartF0Widget.hxx in Headers */, @@ -2684,6 +2729,7 @@ DCAACAFB188D631500A4D282 /* CartBFSC.hxx in Headers */, DCAACAFD188D631500A4D282 /* CartDF.hxx in Headers */, DCAACAFF188D631500A4D282 /* CartDFSC.hxx in Headers */, + DC84397B247B294E00C6A4FC /* CartTVBoy.hxx in Headers */, DCAACB0F188D636F00A4D282 /* Cart4KSCWidget.hxx in Headers */, DCAACB11188D636F00A4D282 /* CartBFSCWidget.hxx in Headers */, DCA82C741FEB4E780059340F /* TimeMachineDialog.hxx in Headers */, @@ -2804,7 +2850,9 @@ E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */, E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */, 2D91747409BA90380026E9FF /* SDLMain.m in Sources */, + DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */, 2D91747509BA90380026E9FF /* Booster.cxx in Sources */, + DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */, DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */, 2D91747609BA90380026E9FF /* Cart.cxx in Sources */, 2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */, @@ -2819,6 +2867,7 @@ 2D91747D09BA90380026E9FF /* CartE0.cxx in Sources */, DCF8621921C9D43300F95F52 /* StaggeredLogger.cxx in Sources */, E0DCD3AA20A64E96000B614E /* ConvolutionBuffer.cxx in Sources */, + DC843980247B297A00C6A4FC /* CartTVBoyWidget.cxx in Sources */, 2D91747E09BA90380026E9FF /* CartE7.cxx in Sources */, DC9616321F817830008A2206 /* PointingDeviceWidget.cxx in Sources */, 2D91747F09BA90380026E9FF /* CartF4.cxx in Sources */, @@ -2832,6 +2881,7 @@ DCF3A6FA1DFC75E3008A8AF3 /* Player.cxx in Sources */, 2D91748609BA90380026E9FF /* CartFE.cxx in Sources */, 2D91748909BA90380026E9FF /* Console.cxx in Sources */, + DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */, DC6DC91E205DB879004A5FC3 /* PhysicalJoystick.cxx in Sources */, E08FCD5323A037EB0051F59B /* QisBlitter.cxx in Sources */, DCCE0355225104BF008C246F /* StellaSettingsDialog.cxx in Sources */, @@ -2855,7 +2905,6 @@ 2D9174A309BA90380026E9FF /* Settings.cxx in Sources */, 2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */, 2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */, - 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */, 2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */, 2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */, 2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */, @@ -2865,20 +2914,22 @@ 2D9174B309BA90380026E9FF /* LauncherDialog.cxx in Sources */, 2D9174B509BA90380026E9FF /* ListWidget.cxx in Sources */, 2D9174B609BA90380026E9FF /* Menu.cxx in Sources */, + DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */, CFE3F60D1E84A9A200A8204E /* CartCDFWidget.cxx in Sources */, 2D9174B709BA90380026E9FF /* OptionsDialog.cxx in Sources */, 2D9174B809BA90380026E9FF /* PopUpWidget.cxx in Sources */, + DC1E474E24D34F3B0047E61A /* WhatsNewDialog.cxx in Sources */, DCBDDE9A1D6A5F0E009DF1E9 /* Cart3EPlusWidget.cxx in Sources */, DCE9158B201543B900960CC0 /* TimeLineWidget.cxx in Sources */, DCE5CDE31BA10024005CD08A /* RiotRamWidget.cxx in Sources */, 2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */, 2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */, 2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */, - 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */, DC6A18FC19B3E67A00DEB242 /* CartMDM.cxx in Sources */, 2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */, 2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */, DC3EE86E1E2C0E6D00905161 /* zutil.c in Sources */, + DC857D352482F66200C7C14F /* CartCreator.cxx in Sources */, CFE3F60B1E84A9A200A8204E /* CartBUSWidget.cxx in Sources */, DCEC58581E945125002F0246 /* DelayQueueWidget.cxx in Sources */, 2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */, @@ -2902,7 +2953,6 @@ 2D9174F109BA90380026E9FF /* InputTextDialog.cxx in Sources */, DC6DC920205DB879004A5FC3 /* PJoystickHandler.cxx in Sources */, DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */, - DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */, 2D9174F209BA90380026E9FF /* CheckListWidget.cxx in Sources */, 2D9174F309BA90380026E9FF /* StringListWidget.cxx in Sources */, 2D9174F409BA90380026E9FF /* CommandDialog.cxx in Sources */, @@ -2919,7 +2969,6 @@ DC5963132139FA14002736F2 /* Bankswitch.cxx in Sources */, DCDFF08120B781B0001227C0 /* DispatchResult.cxx in Sources */, 2D9174FC09BA90380026E9FF /* RamWidget.cxx in Sources */, - DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */, DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */, E007231F210FBF5E002CF343 /* FpsMeter.cxx in Sources */, 2D9174FD09BA90380026E9FF /* RomListWidget.cxx in Sources */, @@ -2948,7 +2997,6 @@ DC47455A09C34BFA00EDDA3A /* CheatManager.cxx in Sources */, DC47455C09C34BFA00EDDA3A /* CheetahCheat.cxx in Sources */, DC62E6471960E87B007AEF05 /* AtariVoxWidget.cxx in Sources */, - DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */, DC47455E09C34BFA00EDDA3A /* RamCheat.cxx in Sources */, E0FABEEC20E9948200EB8E28 /* AudioSettings.cxx in Sources */, DCD56D380B247D920092F9F8 /* Cart4A50.cxx in Sources */, @@ -2991,6 +3039,7 @@ DC6B2BA411037FF200F199A7 /* CartDebug.cxx in Sources */, DCB20EC71A0C506C0048F595 /* main.cxx in Sources */, DC6B2BA611037FF200F199A7 /* DiStella.cxx in Sources */, + DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */, CFE3F6151E84A9CE00A8204E /* CartCDF.cxx in Sources */, E08D2F3E23089B9B000BD709 /* JoyMap.cxx in Sources */, DCA82C711FEB4E780059340F /* TimeMachine.cxx in Sources */, @@ -3056,6 +3105,7 @@ DCDA03B01A2009BB00711920 /* CartWD.cxx in Sources */, DCC6A4B220A2622500863C59 /* SimpleResampler.cxx in Sources */, DC21E5BF21CA903E007D0E1A /* OSystemMACOS.cxx in Sources */, + DC84397C247B294E00C6A4FC /* CartTVBoy.cxx in Sources */, DCAAE5D91715887B0080BB82 /* Cart0840Widget.cxx in Sources */, DCAAE5DB1715887B0080BB82 /* CartCVWidget.cxx in Sources */, DCA233B423BAB1300032ABF3 /* Lightgun.cxx in Sources */, @@ -3091,6 +3141,7 @@ DC676A531729A0B000E4E73D /* CartFA2Widget.cxx in Sources */, DC676A551729A0B000E4E73D /* CartFEWidget.cxx in Sources */, DC676A591729A0B000E4E73D /* CartSBWidget.cxx in Sources */, + DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */, DC676A5B1729A0B000E4E73D /* CartX07Widget.cxx in Sources */, DC7A24DF173B1DBC00B20FE9 /* FileListWidget.cxx in Sources */, DC13B53F176FF2F500B8B4BB /* RomListSettings.cxx in Sources */, @@ -3104,7 +3155,6 @@ DCAACAFC188D631500A4D282 /* CartDF.cxx in Sources */, DCAACAFE188D631500A4D282 /* CartDFSC.cxx in Sources */, DCAACB0E188D636F00A4D282 /* Cart4KSCWidget.cxx in Sources */, - DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */, DCAACB10188D636F00A4D282 /* CartBFSCWidget.cxx in Sources */, DCAACB12188D636F00A4D282 /* CartBFWidget.cxx in Sources */, DCAACB14188D636F00A4D282 /* CartDFSCWidget.cxx in Sources */, diff --git a/src/tools/PropSet.pm b/src/tools/PropSet.pm index 02f0e1c1f..99d55a10f 100755 --- a/src/tools/PropSet.pm +++ b/src/tools/PropSet.pm @@ -3,31 +3,33 @@ package PropSet; # NOTE: If the property types ever change in Stella, the following hashmap # and array must be updated (and stay in sequence) my %prop_type = ( - "Cart.MD5" => 0, - "Cart.Manufacturer" => 1, - "Cart.ModelNo" => 2, - "Cart.Name" => 3, - "Cart.Note" => 4, - "Cart.Rarity" => 5, - "Cart.Sound" => 6, - "Cart.StartBank" => 7, - "Cart.Type" => 8, - "Console.LeftDiff" => 9, - "Console.RightDiff" => 10, - "Console.TVType" => 11, - "Console.SwapPorts" => 12, - "Controller.Left" => 13, - "Controller.Right" => 14, - "Controller.SwapPaddles" => 15, - "Controller.MouseAxis" => 16, - "Display.Format" => 17, - "Display.VCenter" => 18, - "Display.Phosphor" => 19, - "Display.PPBlend" => 20, - "Cart.Players" => 21, - "Cart.Variations" => 22, - "Cart.Formats" => 23, - "Cart.Addresses" => 24 + "Cart.MD5" => 0, + "Cart.Manufacturer" => 1, + "Cart.ModelNo" => 2, + "Cart.Name" => 3, + "Cart.Note" => 4, + "Cart.Rarity" => 5, + "Cart.Sound" => 6, + "Cart.StartBank" => 7, + "Cart.Type" => 8, + "Console.LeftDiff" => 9, + "Console.RightDiff" => 10, + "Console.TVType" => 11, + "Console.SwapPorts" => 12, + "Controller.Left" => 13, + "Controller.Right" => 14, + "Controller.SwapPaddles" => 15, + "Controller.PaddlesXCenter" => 16, + "Controller.PaddlesYCenter" => 17, + "Controller.MouseAxis" => 18, + "Display.Format" => 19, + "Display.VCenter" => 20, + "Display.Phosphor" => 21, + "Display.PPBlend" => 22, + "Cart.Players" => 23, + "Cart.Variations" => 24, + "Cart.Formats" => 25, + "Cart.Addresses" => 26 ); my @prop_type_as_string = ( "Cart.MD5", @@ -46,6 +48,8 @@ my @prop_type_as_string = ( "Controller.Left", "Controller.Right", "Controller.SwapPaddles", + "Controller.PaddlesXCenter", + "Controller.PaddlesYCenter", "Controller.MouseAxis", "Display.Format", "Display.VCenter", diff --git a/src/tools/convbdf.c b/src/tools/convbdf.c index c82dfa307..992095600 100644 --- a/src/tools/convbdf.c +++ b/src/tools/convbdf.c @@ -936,17 +936,17 @@ int gen_c_source(struct font* pf, char *path) if (pf->offset) sprintf(obuf, "%s_sysfont_offset,", fontname); else - sprintf(obuf, "0, /* no encode table*/"); + sprintf(obuf, "nullptr, /* no encode table*/"); if (pf->width) sprintf(buf, "%s_sysfont_width,", fontname); else - sprintf(buf, "0, /* fixed width*/"); + sprintf(buf, "nullptr, /* fixed width*/"); if (pf->bbx) sprintf(bbuf, "%s_sysfont_bbx,", fontname); else - sprintf(bbuf, "0, /* fixed bbox*/"); + sprintf(bbuf, "nullptr, /* fixed bbox*/"); fprintf(ofp, "/* Exported structure definition. */\n" @@ -980,7 +980,7 @@ int gen_c_source(struct font* pf, char *path) fontname); fprintf(ofp, "\n} // End of namespace GUI\n\n#endif\n"); - fcloise(ofp); + fclose(ofp); return 0; } diff --git a/src/unix/FSNodePOSIX.cxx b/src/unix/FSNodePOSIX.cxx index 33f6b5226..f483dc899 100644 --- a/src/unix/FSNodePOSIX.cxx +++ b/src/unix/FSNodePOSIX.cxx @@ -159,7 +159,7 @@ bool FilesystemNodePOSIX::getChildren(AbstractFSList& myList, ListMode mode) con if (entry._isDirectory) entry._path += "/"; - entry._isValid = entry._isDirectory || entry._isFile; + entry._isValid = true; } #endif diff --git a/src/unix/SerialPortUNIX.cxx b/src/unix/SerialPortUNIX.cxx index f114e18fe..1105d2092 100644 --- a/src/unix/SerialPortUNIX.cxx +++ b/src/unix/SerialPortUNIX.cxx @@ -49,6 +49,9 @@ bool SerialPortUNIX::openPort(const string& device) if(myHandle <= 0) return false; + // Open the device in nonblocking mode + fcntl(myHandle, F_SETFL, FNDELAY); + struct termios termios; memset(&termios, 0, sizeof(struct termios)); @@ -71,3 +74,15 @@ bool SerialPortUNIX::writeByte(uInt8 data) } return false; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool SerialPortUNIX::isCTS() +{ + if(myHandle) + { + int status = 0; + ioctl(myHandle, TIOCMGET, &status); + return status & TIOCM_CTS; + } + return false; +} diff --git a/src/unix/SerialPortUNIX.hxx b/src/unix/SerialPortUNIX.hxx index b46d0a64a..7a675298e 100644 --- a/src/unix/SerialPortUNIX.hxx +++ b/src/unix/SerialPortUNIX.hxx @@ -48,6 +48,13 @@ class SerialPortUNIX : public SerialPort */ bool writeByte(uInt8 data) override; + /** + Test for 'Clear To Send' enabled. + + @return True if CTS signal enabled, else false + */ + bool isCTS() override; + private: // File descriptor for serial connection int myHandle{0}; diff --git a/src/unix/r77/SettingsR77.cxx b/src/unix/r77/SettingsR77.cxx index ba8ce6858..2b3dc0525 100644 --- a/src/unix/r77/SettingsR77.cxx +++ b/src/unix/r77/SettingsR77.cxx @@ -50,8 +50,8 @@ SettingsR77::SettingsR77() setPermanent("snaploaddir", "/mnt/stella/snapshots"); setPermanent("launcherres", "1280x720"); - setPermanent("launcherfont", "large"); - setPermanent("romviewer", "2"); + setPermanent("launcherfont", "large12"); + setPermanent("romviewer", "1.6"); setPermanent("exitlauncher", "true"); setTemporary("minimal_ui", true); diff --git a/src/unix/stella.spec b/src/unix/stella.spec index e4f1dbe65..c54cf259a 100644 --- a/src/unix/stella.spec +++ b/src/unix/stella.spec @@ -1,5 +1,5 @@ %define name stella -%define version 6.1 +%define version 6.2.1 %define rel 1 %define enable_sound 1 @@ -100,7 +100,19 @@ rm -rf $RPM_BUILD_DIR/%{name}-%{version} %_datadir/icons/large/%{name}.png %changelog -* ddd Jan d 2020 Stephen Anthony 6.1-1 +* Sat Jun 20 2020 Stephen Anthony 6.2.1-1 +- Version 6.2.1 release + +* Sun Jun 7 2020 Stephen Anthony 6.2-1 +- Version 6.2 release + +* Sat Apr 25 2020 Stephen Anthony 6.1.2-1 +- Version 6.1.2 release + +* Sat Apr 04 2020 Stephen Anthony 6.1.1-1 +- Version 6.1.1 release + +* Sun Mar 22 2020 Stephen Anthony 6.1-1 - Version 6.1 release * Fri Oct 11 2019 Stephen Anthony 6.0.2-1 diff --git a/src/windows/SerialPortWINDOWS.cxx b/src/windows/SerialPortWINDOWS.cxx index 51ed73247..91b6c0bb3 100644 --- a/src/windows/SerialPortWINDOWS.cxx +++ b/src/windows/SerialPortWINDOWS.cxx @@ -79,3 +79,15 @@ bool SerialPortWINDOWS::writeByte(uInt8 data) } return false; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool SerialPortWINDOWS::isCTS() +{ + if(myHandle) + { + DWORD modemStat; + GetCommModemStatus(myHandle, &modemStat); + return modemStat & MS_CTS_ON; + } + return false; +} diff --git a/src/windows/SerialPortWINDOWS.hxx b/src/windows/SerialPortWINDOWS.hxx index 8c0ed789c..3f8513573 100644 --- a/src/windows/SerialPortWINDOWS.hxx +++ b/src/windows/SerialPortWINDOWS.hxx @@ -47,6 +47,14 @@ class SerialPortWINDOWS : public SerialPort */ bool writeByte(uInt8 data) override; + /** + Test for 'Clear To Send' enabled. By default, assume it's always + OK to send more data. + + @return True if CTS signal enabled, else false + */ + bool isCTS() override; + private: // Handle to serial port HANDLE myHandle{0}; diff --git a/src/windows/Stella.sln b/src/windows/Stella.sln index fb70ffeaf..3aae8e551 100755 --- a/src/windows/Stella.sln +++ b/src/windows/Stella.sln @@ -1,16 +1,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.168 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stella", "Stella.vcxproj", "{D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}" EndProject Global - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Debug-NoDebugger|Win32 = Debug-NoDebugger|Win32 + Debug-NoDebugger|x64 = Debug-NoDebugger|x64 Profile|Win32 = Profile|Win32 Profile|x64 = Profile|x64 Release|Win32 = Release|Win32 @@ -21,6 +20,10 @@ Global {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug|Win32.Build.0 = Debug|Win32 {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug|x64.ActiveCfg = Debug|x64 {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug|x64.Build.0 = Debug|x64 + {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug-NoDebugger|Win32.ActiveCfg = Debug-NoDebugger|Win32 + {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug-NoDebugger|Win32.Build.0 = Debug-NoDebugger|Win32 + {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug-NoDebugger|x64.ActiveCfg = Debug-NoDebugger|x64 + {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug-NoDebugger|x64.Build.0 = Debug-NoDebugger|x64 {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Profile|Win32.ActiveCfg = Profile|Win32 {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Profile|Win32.Build.0 = Profile|Win32 {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Profile|x64.ActiveCfg = Profile|x64 @@ -42,4 +45,7 @@ Global GlobalSection(Performance) = preSolution HasPerformanceSessions = true EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj index 9b6592655..449890d12 100644 --- a/src/windows/Stella.vcxproj +++ b/src/windows/Stella.vcxproj @@ -1,6 +1,14 @@  + + Debug-NoDebugger + Win32 + + + Debug-NoDebugger + x64 + Debug Win32 @@ -48,6 +56,11 @@ MultiByte v141_xp + + Application + MultiByte + v141_xp + Application MultiByte @@ -63,6 +76,11 @@ MultiByte v141_xp + + Application + MultiByte + v141_xp + false @@ -81,6 +99,10 @@ + + + + @@ -93,15 +115,25 @@ + + + + <_ProjectFileVersion>10.0.30319.1 $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ true + true $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ true + true $(Platform)\$(Configuration)\ Release\ $(Platform)\$(Configuration)\ @@ -111,11 +143,17 @@ $(Platform)\$(Configuration)\ $(Platform)\$(Configuration)\ AllRules.ruleset + AllRules.ruleset + + AllRules.ruleset + AllRules.ruleset + + AllRules.ruleset AllRules.ruleset @@ -133,6 +171,10 @@ $(ProjectDir)\SDL\lib\x86;$(LibraryPath) $(ProjectDir)\SDL\include;$(IncludePath) + + $(ProjectDir)\SDL\lib\x86;$(LibraryPath) + $(ProjectDir)\SDL\include;$(IncludePath) + $(ProjectDir)\SDL\lib\x86;$(LibraryPath) $(ProjectDir)\SDL\include;$(IncludePath) @@ -145,6 +187,10 @@ $(ProjectDir)\SDL\lib\x64;$(LibraryPath) $(ProjectDir)\SDL\include;$(IncludePath) + + $(ProjectDir)\SDL\lib\x64;$(LibraryPath) + $(ProjectDir)\SDL\include;$(IncludePath) + $(ProjectDir)\SDL\lib\x64;$(LibraryPath) $(ProjectDir)\SDL\include;$(IncludePath) @@ -187,6 +233,40 @@ Default + + + Disabled + ..\yacc;..\emucore;..\emucore\tia;..\emucore\tia\frame-manager;..\common;..\common\tv_filters;..\gui;..\debugger\gui;..\debugger;..\windows;..\cheat;..\zlib;..\libpng;%(AdditionalIncludeDirectories) + BSPF_WINDOWS;WIN32;NOMINMAX;DEBUG_BUILD;SDL_SUPPORT;GUI_SUPPORT;PNG_SUPPORT;ZIP_SUPPORT;JOYSTICK_SUPPORT;DEBUGGER_SUPPORT;WINDOWED_SUPPORT;SOUND_SUPPORT;CHEATCODE_SUPPORT;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDLL + + + Level4 + EditAndContinue + $(IntDir)obj\\windows\%(RelativeDir) + StreamingSIMDExtensions + stdcpp17 + true + 4100;4127;4146;4244;%(DisableSpecificWarnings) + CompileAsCpp + NoListing + $(IntDir)asm\windows\%(RelativeDir) + + + SDL2.lib;SDL2main.lib;SDL2main.lib;%(AdditionalDependencies) + $(OutDir)Stella.exe + true + $(OutDir)Stella.pdb + Console + false + + + MachineX86 + Default + + X64 @@ -223,6 +303,42 @@ Default + + + X64 + + + Disabled + ..\yacc;..\emucore;..\emucore\tia;..\emucore\tia\frame-manager;..\common;..\common\tv_filters;..\gui;..\debugger\gui;..\debugger;..\windows;..\cheat;..\zlib;..\libpng;%(AdditionalIncludeDirectories) + BSPF_WINDOWS;WIN32;NOMINMAX;DEBUG_BUILD;SDL_SUPPORT;GUI_SUPPORT;PNG_SUPPORT;ZIP_SUPPORT;JOYSTICK_SUPPORT;WINDOWED_SUPPORT;SOUND_SUPPORT;CHEATCODE_SUPPORT;%(PreprocessorDefinitions) + false + EnableFastChecks + MultiThreadedDLL + + + Level4 + ProgramDatabase + $(IntDir)obj\\windows\%(RelativeDir) + stdcpp17 + true + 4100;4127;4146;4244;%(DisableSpecificWarnings) + CompileAsCpp + NoListing + $(IntDir)asm\windows\%(RelativeDir) + + + SDL2.lib;SDL2main.lib;SDL2main.lib;%(AdditionalDependencies) + $(OutDir)Stella.exe + true + $(OutDir)Stella.pdb + Console + false + + + MachineX64 + Default + + true @@ -388,6 +504,7 @@ + @@ -404,81 +521,211 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + - - @@ -487,6 +734,7 @@ + @@ -516,6 +764,7 @@ + @@ -531,6 +780,7 @@ + @@ -594,33 +844,79 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + - @@ -652,425 +948,545 @@ - + CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC Level2 + Level2 Level2 Level2 Level2 + Level2 Level2 Level2 CompileAsC + CompileAsC CompileAsC CompileAsC CompileAsC + CompileAsC CompileAsC CompileAsC @@ -1098,6 +1514,7 @@ + @@ -1122,87 +1539,220 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + + - - @@ -1211,6 +1761,7 @@ + @@ -1227,6 +1778,7 @@ + @@ -1255,6 +1807,7 @@ + @@ -1266,10 +1819,14 @@ + + + + @@ -1342,33 +1899,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + @@ -1376,7 +1987,6 @@ - @@ -1412,7 +2022,7 @@ - + diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters index 05b9d9b0d..2536cee92 100644 --- a/src/windows/Stella.vcxproj.filters +++ b/src/windows/Stella.vcxproj.filters @@ -342,9 +342,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -438,9 +435,6 @@ Source Files\gui - - Source Files\gui - Source Files\gui @@ -723,9 +717,6 @@ Source Files\emucore - - Source Files\emucore - Source Files\debugger @@ -735,9 +726,6 @@ Source Files\debugger - - Source Files\debugger - Source Files\emucore @@ -759,12 +747,6 @@ Source Files\debugger - - Source Files\emucore - - - Source Files\debugger - Source Files\debugger @@ -1014,6 +996,36 @@ Source Files\gui + + Source Files\emucore + + + Source Files\debugger + + + Source Files\emucore + + + Source Files + + + Source Files\gui + + + Source Files\gui + + + Source Files\emucore + + + Source Files + + + Source Files\emucore + + + Source Files\gui + @@ -1325,9 +1337,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -1433,9 +1442,6 @@ Header Files\gui - - Header Files\gui - Header Files\gui @@ -1715,9 +1721,6 @@ Header Files\emucore - - Header Files\emucore - Header Files\debugger @@ -1727,9 +1730,6 @@ Header Files\debugger - - Header Files\debugger - Header Files\emucore @@ -1754,12 +1754,6 @@ Header Files\debugger - - Header Files\debugger - - - Header Files\emucore - Header Files\debugger @@ -2072,6 +2066,48 @@ Header Files\gui + + Header Files\gui + + + Header Files\gui + + + Header Files\gui + + + Header Files\emucore + + + Header Files\debugger + + + Header Files\emucore + + + Header Files + + + Header Files\gui + + + Header Files\gui + + + Header Files\emucore + + + Header Files + + + Header Files\emucore + + + Header Files\gui + + + Header Files\emucore + diff --git a/src/windows/stella.rc b/src/windows/stella.rc index d6fcd5ce3..0958a136d 100755 --- a/src/windows/stella.rc +++ b/src/windows/stella.rc @@ -36,8 +36,8 @@ IDI_ICON ICON "stella.ico" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 6,1,0,0 - PRODUCTVERSION 6,1,0,0 + FILEVERSION 6,2,1,0 + PRODUCTVERSION 6,2,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -55,12 +55,12 @@ BEGIN VALUE "Comments", "The multi-platform Atari 2600 emulator. Stella is released under the GPLv2." VALUE "CompanyName", "The Stella Team (https://stella-emu.github.io)" VALUE "FileDescription", "Stella" - VALUE "FileVersion", "6.1" + VALUE "FileVersion", "6.2.1" VALUE "InternalName", "Stella" VALUE "LegalCopyright", "Copyright (c) 1995-2020 The Stella Team" VALUE "OriginalFilename", "Stella.exe" VALUE "ProductName", "Stella" - VALUE "ProductVersion", "6.1" + VALUE "ProductVersion", "6.2.1" END END BLOCK "VarFileInfo" diff --git a/src/yacc/YaccParser.cxx b/src/yacc/YaccParser.cxx index 696987b38..8bc728ca0 100644 --- a/src/yacc/YaccParser.cxx +++ b/src/yacc/YaccParser.cxx @@ -181,10 +181,15 @@ CartMethod getCartSpecial(char* ch) { if(BSPF::equalsIgnoreCase(ch, "_bank")) return &CartDebug::getPCBank; - else if(BSPF::equalsIgnoreCase(ch, "__lastread")) + + else if(BSPF::equalsIgnoreCase(ch, "__lastbaseread")) return &CartDebug::lastReadBaseAddress; - else if(BSPF::equalsIgnoreCase(ch, "__lastwrite")) + else if(BSPF::equalsIgnoreCase(ch, "__lastbasewrite")) return &CartDebug::lastWriteBaseAddress; + else if(BSPF::equalsIgnoreCase(ch, "__lastread")) + return &CartDebug::lastReadAddress; + else if(BSPF::equalsIgnoreCase(ch, "__lastwrite")) + return &CartDebug::lastWriteAddress; else return nullptr; } @@ -229,7 +234,9 @@ TiaMethod getTiaSpecial(char* ch) { if(BSPF::equalsIgnoreCase(ch, "_scan")) return &TIADebug::scanlines; - if(BSPF::equalsIgnoreCase(ch, "_scycles")) + else if(BSPF::equalsIgnoreCase(ch, "_scanend")) + return &TIADebug::scanlinesLastFrame; + else if(BSPF::equalsIgnoreCase(ch, "_scycles")) return &TIADebug::cyclesThisLine; else if(BSPF::equalsIgnoreCase(ch, "_fcount")) return &TIADebug::frameCount; diff --git a/profile/128.bin b/test/roms/profile/128.bin similarity index 100% rename from profile/128.bin rename to test/roms/profile/128.bin diff --git a/profile/README.md b/test/roms/profile/README.md similarity index 100% rename from profile/README.md rename to test/roms/profile/README.md diff --git a/profile/catharsis_theory.bin b/test/roms/profile/catharsis_theory.bin similarity index 100% rename from profile/catharsis_theory.bin rename to test/roms/profile/catharsis_theory.bin