Repository: ppeccin/javatari.js Branch: master Commit: f954960ddfbd Files: 114 Total size: 4.4 MB Directory structure: gitextract_3gk_afnw/ ├── .gitignore ├── README.md ├── doc/ │ └── README.md ├── gruntfile.js ├── license.txt ├── package.json ├── release/ │ └── stable/ │ ├── 4.0/ │ │ ├── embedded/ │ │ │ ├── index.html │ │ │ └── javatari.js │ │ └── standalone/ │ │ ├── cache.manifest │ │ ├── index.html │ │ └── manifest.webapp │ ├── 5.0/ │ │ ├── embedded/ │ │ │ ├── index.html │ │ │ └── javatari.js │ │ └── standalone/ │ │ ├── cache.manifest │ │ ├── index.html │ │ └── manifest.webapp │ └── old/ │ ├── index.html │ └── javatari/ │ └── javatari.js ├── src/ │ ├── main/ │ │ ├── Configurator.js │ │ ├── Javatari.js │ │ ├── Launcher.js │ │ ├── atari/ │ │ │ ├── audio/ │ │ │ │ └── AudioSignal.js │ │ │ ├── cartridge/ │ │ │ │ ├── Cartridge.js │ │ │ │ ├── CartridgeCreator.js │ │ │ │ ├── CartridgeDatabase.js │ │ │ │ ├── CartridgeDatabaseUncompressed.js │ │ │ │ ├── CartridgeFormats.js │ │ │ │ ├── ROM.js │ │ │ │ └── formats/ │ │ │ │ ├── Cartridge10K_DPCa.js │ │ │ │ ├── Cartridge16K_E7.js │ │ │ │ ├── Cartridge24K_28K_32K_FA2.js │ │ │ │ ├── Cartridge2K_CV.js │ │ │ │ ├── Cartridge4K.js │ │ │ │ ├── Cartridge64K_F0.js │ │ │ │ ├── Cartridge64K_X07.js │ │ │ │ ├── Cartridge8K_0840.js │ │ │ │ ├── Cartridge8K_256K_SB.js │ │ │ │ ├── Cartridge8K_512K_3E.js │ │ │ │ ├── Cartridge8K_512K_3F.js │ │ │ │ ├── Cartridge8K_64K_AR.js │ │ │ │ ├── Cartridge8K_E0.js │ │ │ │ ├── Cartridge8K_FE.js │ │ │ │ ├── Cartridge8K_UA.js │ │ │ │ ├── CartridgeBankedByBusMonitoring.js │ │ │ │ └── CartridgeBankedByMaskedRange.js │ │ │ ├── console/ │ │ │ │ ├── AtariConsole.js │ │ │ │ └── Bus.js │ │ │ ├── controls/ │ │ │ │ ├── ConsoleControls.js │ │ │ │ └── JoystickButtons.js │ │ │ ├── cpu/ │ │ │ │ ├── M6502.js │ │ │ │ └── Ram64K.js │ │ │ ├── pia/ │ │ │ │ ├── Pia.js │ │ │ │ └── Ram.js │ │ │ ├── tia/ │ │ │ │ ├── Tia.js │ │ │ │ ├── TiaAudio.js │ │ │ │ ├── TiaAudioChannel.js │ │ │ │ └── TiaPalettes.js │ │ │ └── video/ │ │ │ ├── VideoSignal.js │ │ │ └── VideoStandard.js │ │ ├── images/ │ │ │ ├── Images.js │ │ │ └── originals/ │ │ │ ├── Controllers.xcf │ │ │ ├── IconSprites.xcf │ │ │ ├── LogoIcon.xcf │ │ │ ├── LogoJS.xcf │ │ │ ├── LogoSiteBar.xcf │ │ │ └── Panel.xcf │ │ ├── room/ │ │ │ ├── Room.js │ │ │ ├── clock/ │ │ │ │ └── Clock.js │ │ │ ├── controls/ │ │ │ │ ├── DOMConsoleControls.js │ │ │ │ ├── DOMKeys.js │ │ │ │ ├── DOMPeripheralControls.js │ │ │ │ ├── DOMTouchControls.js │ │ │ │ ├── GamepadButtons.js │ │ │ │ ├── GamepadConsoleControls.js │ │ │ │ ├── PeripheralControls.js │ │ │ │ └── TouchControls.js │ │ │ ├── files/ │ │ │ │ ├── FileDownloader.js │ │ │ │ ├── FileLoader.js │ │ │ │ └── RecentStoredROMs.js │ │ │ ├── netplay/ │ │ │ │ ├── NetClient.js │ │ │ │ └── NetServer.js │ │ │ ├── savestate/ │ │ │ │ └── LocalStorageSaveStateMedia.js │ │ │ ├── screen/ │ │ │ │ ├── CanvasDisplay.js │ │ │ │ ├── ConsolePanel.js │ │ │ │ ├── FullScreenSetup.js │ │ │ │ ├── Monitor.js │ │ │ │ ├── ScreenGUI.es5.js │ │ │ │ ├── dialogs/ │ │ │ │ │ ├── CartridgeFormatDialog.js │ │ │ │ │ ├── NetPlayDialog.js │ │ │ │ │ ├── QuickOptionsDialog.js │ │ │ │ │ ├── RecentROMsDialog.js │ │ │ │ │ └── SaveStateDialog.js │ │ │ │ ├── es6/ │ │ │ │ │ ├── ScreenGUI.js │ │ │ │ │ └── SettingsGUI.js │ │ │ │ └── settings/ │ │ │ │ ├── Settings.js │ │ │ │ └── SettingsGUI.es5.js │ │ │ └── speaker/ │ │ │ └── WebAudioSpeaker.js │ │ ├── userprefs/ │ │ │ ├── UserPreferences.js │ │ │ └── UserROMFormats.js │ │ └── util/ │ │ ├── EmbeddedFiles.js │ │ ├── MD5.js │ │ ├── MultiDownloader.js │ │ ├── MultiFileReader.js │ │ ├── Util.js │ │ └── ZIP.js │ └── runtime/ │ ├── embedded/ │ │ └── index.html │ ├── images/ │ │ └── EmbeddedImages.js │ └── standalone/ │ ├── cache.manifest │ ├── index.base.html │ ├── index.part1.html │ ├── index.part2.html │ └── manifest.webapp └── test/ ├── index.html └── manifest.webapp ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .idea/ node_modules/ temp/ ================================================ FILE: README.md ================================================ # Javatari **Javatari** is a new cross platform Atari 2600 emulator designed for the Web. It's great for displaying games running inside webpages. You can launch the emulator and load ROMs with a single link. And now you can play Atari 2600 games with touch controls on your Android/iOS device, even when offline! Join friends in multiplayer games with the new NetPlay! function. Please go to **https://javatari.org** to enjoy it online! Refer to [**/doc**](https://github.com/ppeccin/javatari.js/tree/master/doc) for parameters reference and URL usage examples. Refer to [**/release**](https://github.com/ppeccin/javatari.js/tree/master/release) for stable release files and deployment examples. Atari, VCS and the Atari logo are shown here as a tribute. All trademarks are property of their respective owners. #### New in Version 5.0 - NetPlay! Connect several users on the same Virtual Atari Console over the internet - Enjoy multiplayer gaming sessions with your friends online - P2P connection with automatic network discovery, no worries with IPs and ports - User interface for selecting Cartridge Mapper type - Several improvements and fixes ### Features - Cross platform HTML5/JS. Runs in any Browser, tested in Chrome/Firefox/Safari - Support for mobile iOS and Android devices - Finally enjoy Atari 2600 games on your iPhone/iPad - Customizable Touch Controls for mobile devices with Haptic feedback - Real Atari 2600 Console panel for a nostalgic feel! - Install as a WebApp on iOS/Android/Desktop, then run offline! - Put Atari 2600 games in webpages easily - Show games running with a single link to the Javatari page - Drag & Drop system for loading files - Open files from local storage, iCloud, Google Drive, Dropbox, web links - Savestates support. Export and share Savestate files - Fully customizable Joysticks, Joykeys and Touch controllers - Adjustable speed, Pause and Frame-by-frame advance - Screen Capture and Debug modes - Resizable Screen, Full Screen mode - Javascript API for loading ROMs and Console control ## About the NetPlay! feature Javatari 5.0 brings NetPlay!, in which any number of users may connect and control the same virtual Atari Console. To access the feature, open the NetPlay! control dialog available on the System Menu (Power button). One user must be the "Server" and start a NetPlay! Session. Just choose a name for the Session, or let the emulator generate it randomly, then hit "HOST". Once the Session is started and active, other users may join the Session simply by entering the same Session name and hitting "JOIN". All users connected have complete control over the machine, except that only the Server user may load/change media files (ROMs). All features of the emulator work during NetPlay! Any Client user may leave the Session at any time, but only the Server user may end the Session completely. Be careful not to make your Session name public! Anyone that knows your Session name will be able to join it while its active. Send the session name only to people you want to invite. Another way of sharing your Session to users is sending them a link that will open the emulator and join the session automatically. In the NetPlay! dialog, once you are Hosting a Session, there will be a link button on the upper right, that will generate the link and copy it to your clipboard. **IMPORTANT:** NetPlay! performance is completely dependent on the network quality. The lower the network latency between users, the better. Higher bandwidths with higher latencies won't help much. It uses a specialized P2P protocol, and tries to use STUN to traverse NATs/routers so users don't have to worry about IPs and opening ports. Use at your own risk! :-) To make all this work seamlessly, Javatari uses modern Web technologies including WebRTC, which are supported by all major browsers and platforms. Unfortunately, those technologies are still not available on Apple iOS, so NetPlay! will not work on iOS devices. Sorry but there is not much we can do about it, until Apple feels it should allow its customers to access those technologies. ## Javatari Configuration and Launch Options Several parameters are available for customizing the emulator. They can be changed either directly in Javascript if you are hosting the emulator in your own page, or via URL Query Parameters if you are creating links or bookmarks to open the emulator, or just using it in your browser. All parameters are in the form of properties in the global object `Javatari`. Just set these object properties in Javascript, or use URL Query parameter/value pairs. For example: ``` Javatari.CARTRIDGE_URL = "files/Game.rom"; is the same as https://javatari.org?ROM=files/Game.rom ``` **IMPORTANT:** Any parameter setting via Javascript must be done AFTER importing the `javatari.js` file. ## Media Loading The emulator can be set to automatically load files like ROMs images and Savestate files. Files may be compressed in ZIP or GZIP formats. Available parameters: | Parameter | Function | Shortcut for URL form | --- | --- | --- | `CARTRIDGE_URL` | URL of ROM image file to load | `ROM`, `CART` | `CARTRIDGE_FORMAT` | Force a specific ROM Format | `FORMAT` | `STATE_URL` | URL of SaveState file to load | `STATE`, `SAVESTATE` | `AUTODETECT_URL` | URL of file to load with media auto-detection | `AUTODETECT`, `AUTO`, `ANY` ### ROM Format (or Mapper Type) The ROM Format is auto-detected. To force a format, use the `CARTRIDGE_FORMAT` parameter. You can also put the format specification in the ROM file name, between brackets. Example: `Robotank [FE].rom` #### Valid Formats `4K`, `CV`, `E0`, `F0`, `FE`, `E7`, `F4`, `F6`, `F8`, `FA`, `FA2`, `FA2cu`, `EF`, `DPC`, `3F`, `3E`, `X07`, `0840`, `UA`, `SB`, `AR` ## Launch URL Examples Javatari is great for displaying Atari 2600 games in the web. With a simple URL, you can launch the emulator and automatically load and run anything. You may combine several settings and media loading options in a single link. Here are some examples: - To load a game in ROM format: ``` https://javatari.org?ROM=https://gamesarchive.org/Pitfall.rom ``` - To load a game in a ZIPped ROM Image and force the ROM Format to `FA2` ``` https://javatari.org?ROM=https://gamesarchive.org/StarCastle.zip&FORMAT=FA2 ``` ## Parameters Reference | Parameter | Default | Description | --- | :---: | --- | `CARTRIDGE_URL` | -- | URL of ROM image file to load | `CARTRIDGE_FORMAT` | -- | ROM Format to use. Leave unset for autodetection | `STATE_URL` | -- | URL of SaveState file to load | `AUTODETECT_URL` | -- | URL of file to load with media auto-detection | `SCREEN_ELEMENT_ID` | "javatari-screen" | HTML Element ID to place the Emulator Screen | `SCREEN_CONSOLE_PANEL_DISABLED` | false | Hide the Console Panel controls | `CARTRIDGE_SHOW_RECENT` | true | Show a list of recent loaded ROMs at startup | `CARTRIDGE_LABEL_COLORS` | "" | Space-separated colors for customised Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults | `ALLOW_URL_PARAMETERS` | true | Allows overriding any parameters via URL query parameters | `AUTO_START` | true | Auto-Start the emulator as soon as ready | `AUTO_POWER_ON_DELAY` | 1200 | Auto-Power-ON after specified msecs. -1: no Auto-Power-ON | `CARTRIDGE_CHANGE_DISABLED` | false | Block user from changing Cartridges | `SCREEN_RESIZE_DISABLED` | false | Block user from changing Screen size | `SCREEN_FULLSCREEN_MODE` | -1 | FullScreen mode. -2: disabled; -1: auto; 0: off; 1: on | `SCREEN_FILTER_MODE` | -3 | Screen CRT Filter level. -3: user set (default auto); -2: browser default; -1: auto; 0..3: smoothing level | `SCREEN_CRT_MODE` | 0 | Screen CRT Phosphor Effect. -1: auto; 0: off; 1: on | `SCREEN_DEFAULT_SCALE` | -1 | Screen size. -1: auto; 0.5..N in 0.1 steps | `SCREEN_DEFAULT_ASPECT` | 1 | Screen aspect ratio (width) in 0.1 steps | `SCREEN_CANVAS_SIZE` | 2 | Internal canvas size factor. Don't change! :-) | `SCREEN_CONTROL_BAR` | 1 | Screen Bottom Bar controls. 0: on hover; 1: always | `SCREEN_FORCE_HOST_NATIVE_FPS` | -1 | Force host native video frequency. -1: auto-detect. Don't change! :-) | `SCREEN_VSYNCH_MODE` | -2 | V-Synch mode. -2: user set (default on); -1: disabled; 0: off; 1: on | `AUDIO_MONITOR_BUFFER_BASE` | -3 | Audio buffer base size. -3: user set (default auto); -2: disable audio; -1: auto; 0: browser default; 1..6: base value. More buffer = more delay | `AUDIO_MONITOR_BUFFER_SIZE` | -1 | Audio buffer size. -1: auto; 256, 512, 1024, 2048, 4096, 8192, 16384: buffer size. More buffer = more delay. Don't change! :-) | `AUDIO_SIGNAL_BUFFER_RATIO` | 2 | Internal Audio Signal buffer based on Monitor buffer | `AUDIO_SIGNAL_ADD_FRAMES` | 3 | Additional frames in internal Audio Signal buffer based on Monitor buffer | `PADDLES_MODE` | -1 | Paddle controls. -1: auto; 0: off; 1: on | `TOUCH_MODE` | -1 | Touch controls. -1: auto; 0: disabled; 1: enabled; 2: enabled (swapped) | `RESET` | 0 | If value = 1 clear all saved data on the client | `PAGE_BACK_CSS` | -- | CSS to modify page background color. Applied to the body element ================================================ FILE: doc/README.md ================================================ # Javatari **Javatari** is a new cross platform Atari 2600 emulator designed for the Web. It's great for displaying games running inside webpages. You can launch the emulator and load ROMs with a single link. And now you can play Atari 2600 games with touch controls on your Android/iOS device, even when offline! Join friends in multiplayer games with the new NetPlay! function. Please go to **https://javatari.org** to enjoy it online! Refer to [**/doc**](https://github.com/ppeccin/javatari.js/tree/master/doc) for parameters reference and URL usage examples. Refer to [**/release**](https://github.com/ppeccin/javatari.js/tree/master/release) for stable release files and deployment examples. Atari, VCS and the Atari logo are shown here as a tribute. All trademarks are property of their respective owners. #### New in Version 5.0 - NetPlay! Connect several users on the same Virtual Atari Console over the internet - Enjoy multiplayer gaming sessions with your friends online - P2P connection with automatic network discovery, no worries with IPs and ports - User interface for selecting Cartridge Mapper type - Several improvements and fixes ### Features - Cross platform HTML5/JS. Runs in any Browser, tested in Chrome/Firefox/Safari - Support for mobile iOS and Android devices - Finally enjoy Atari 2600 games on your iPhone/iPad - Customizable Touch Controls for mobile devices with Haptic feedback - Real Atari 2600 Console panel for a nostalgic feel! - Install as a WebApp on iOS/Android/Desktop, then run offline! - Put Atari 2600 games in webpages easily - Show games running with a single link to the Javatari page - Drag & Drop system for loading files - Open files from local storage, iCloud, Google Drive, Dropbox, web links - Savestates support. Export and share Savestate files - Fully customizable Joysticks, Joykeys and Touch controllers - Adjustable speed, Pause and Frame-by-frame advance - Screen Capture and Debug modes - Resizable Screen, Full Screen mode - Javascript API for loading ROMs and Console control ## About the NetPlay! feature Javatari 5.0 brings NetPlay!, in which any number of users may connect and control the same virtual Atari Console. To access the feature, open the NetPlay! control dialog available on the System Menu (Power button). One user must be the "Server" and start a NetPlay! Session. Just choose a name for the Session, or let the emulator generate it randomly, then hit "HOST". Once the Session is started and active, other users may join the Session simply by entering the same Session name and hitting "JOIN". All users connected have complete control over the machine, except that only the Server user may load/change media files (ROMs). All features of the emulator work during NetPlay! Any Client user may leave the Session at any time, but only the Server user may end the Session completely. Be careful not to make your Session name public! Anyone that knows your Session name will be able to join it while its active. Send the session name only to people you want to invite. Another way of sharing your Session to users is sending them a link that will open the emulator and join the session automatically. In the NetPlay! dialog, once you are Hosting a Session, there will be a link button on the upper right, that will generate the link and copy it to your clipboard. **IMPORTANT:** NetPlay! performance is completely dependent on the network quality. The lower the network latency between users, the better. Higher bandwidths with higher latencies won't help much. It uses a specialized P2P protocol, and tries to use STUN to traverse NATs/routers so users don't have to worry about IPs and opening ports. Use at your own risk! :-) To make all this work seamlessly, Javatari uses modern Web technologies including WebRTC, which are supported by all major browsers and platforms. Unfortunately, those technologies are still not available on Apple iOS, so NetPlay! will not work on iOS devices. Sorry but there is not much we can do about it, until Apple feels it should allow its customers to access those technologies. ## Javatari Configuration and Launch Options Several parameters are available for customizing the emulator. They can be changed either directly in Javascript if you are hosting the emulator in your own page, or via URL Query Parameters if you are creating links or bookmarks to open the emulator, or just using it in your browser. All parameters are in the form of properties in the global object `Javatari`. Just set these object properties in Javascript, or use URL Query parameter/value pairs. For example: ``` Javatari.CARTRIDGE_URL = "files/Game.rom"; is the same as https://javatari.org?ROM=files/Game.rom ``` **IMPORTANT:** Any parameter setting via Javascript must be done AFTER importing the `javatari.js` file. ## Media Loading The emulator can be set to automatically load files like ROMs images and Savestate files. Files may be compressed in ZIP or GZIP formats. Available parameters: | Parameter | Function | Shortcut for URL form | --- | --- | --- | `CARTRIDGE_URL` | URL of ROM image file to load | `ROM`, `CART` | `CARTRIDGE_FORMAT` | Force a specific ROM Format | `FORMAT` | `STATE_URL` | URL of SaveState file to load | `STATE`, `SAVESTATE` | `AUTODETECT_URL` | URL of file to load with media auto-detection | `AUTODETECT`, `AUTO`, `ANY` ### ROM Format (or Mapper Type) The ROM Format is auto-detected. To force a format, use the `CARTRIDGE_FORMAT` parameter. You can also put the format specification in the ROM file name, between brackets. Example: `Robotank [FE].rom` #### Valid Formats `4K`, `CV`, `E0`, `F0`, `FE`, `E7`, `F4`, `F6`, `F8`, `FA`, `FA2`, `FA2cu`, `EF`, `DPC`, `3F`, `3E`, `X07`, `0840`, `UA`, `SB`, `AR` ## Launch URL Examples Javatari is great for displaying Atari 2600 games in the web. With a simple URL, you can launch the emulator and automatically load and run anything. You may combine several settings and media loading options in a single link. Here are some examples: - To load a game in ROM format: ``` https://javatari.org?ROM=https://gamesarchive.org/Pitfall.rom ``` - To load a game in a ZIPped ROM Image and force the ROM Format to `FA2` ``` https://javatari.org?ROM=https://gamesarchive.org/StarCastle.zip&FORMAT=FA2 ``` ## Parameters Reference | Parameter | Default | Description | --- | :---: | --- | `CARTRIDGE_URL` | -- | URL of ROM image file to load | `CARTRIDGE_FORMAT` | -- | ROM Format to use. Leave unset for autodetection | `STATE_URL` | -- | URL of SaveState file to load | `AUTODETECT_URL` | -- | URL of file to load with media auto-detection | `SCREEN_ELEMENT_ID` | "javatari-screen" | HTML Element ID to place the Emulator Screen | `SCREEN_CONSOLE_PANEL_DISABLED` | false | Hide the Console Panel controls | `CARTRIDGE_SHOW_RECENT` | true | Show a list of recent loaded ROMs at startup | `CARTRIDGE_LABEL_COLORS` | "" | Space-separated colors for customised Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults | `ALLOW_URL_PARAMETERS` | true | Allows overriding any parameters via URL query parameters | `AUTO_START` | true | Auto-Start the emulator as soon as ready | `AUTO_POWER_ON_DELAY` | 1200 | Auto-Power-ON after specified msecs. -1: no Auto-Power-ON | `CARTRIDGE_CHANGE_DISABLED` | false | Block user from changing Cartridges | `SCREEN_RESIZE_DISABLED` | false | Block user from changing Screen size | `SCREEN_FULLSCREEN_MODE` | -1 | FullScreen mode. -2: disabled; -1: auto; 0: off; 1: on | `SCREEN_FILTER_MODE` | -3 | Screen CRT Filter level. -3: user set (default auto); -2: browser default; -1: auto; 0..3: smoothing level | `SCREEN_CRT_MODE` | 0 | Screen CRT Phosphor Effect. -1: auto; 0: off; 1: on | `SCREEN_DEFAULT_SCALE` | -1 | Screen size. -1: auto; 0.5..N in 0.1 steps | `SCREEN_DEFAULT_ASPECT` | 1 | Screen aspect ratio (width) in 0.1 steps | `SCREEN_CANVAS_SIZE` | 2 | Internal canvas size factor. Don't change! :-) | `SCREEN_CONTROL_BAR` | 1 | Screen Bottom Bar controls. 0: on hover; 1: always | `SCREEN_FORCE_HOST_NATIVE_FPS` | -1 | Force host native video frequency. -1: auto-detect. Don't change! :-) | `SCREEN_VSYNCH_MODE` | -2 | V-Synch mode. -2: user set (default on); -1: disabled; 0: off; 1: on | `AUDIO_MONITOR_BUFFER_BASE` | -3 | Audio buffer base size. -3: user set (default auto); -2: disable audio; -1: auto; 0: browser default; 1..6: base value. More buffer = more delay | `AUDIO_MONITOR_BUFFER_SIZE` | -1 | Audio buffer size. -1: auto; 256, 512, 1024, 2048, 4096, 8192, 16384: buffer size. More buffer = more delay. Don't change! :-) | `AUDIO_SIGNAL_BUFFER_RATIO` | 2 | Internal Audio Signal buffer based on Monitor buffer | `AUDIO_SIGNAL_ADD_FRAMES` | 3 | Additional frames in internal Audio Signal buffer based on Monitor buffer | `PADDLES_MODE` | -1 | Paddle controls. -1: auto; 0: off; 1: on | `TOUCH_MODE` | -1 | Touch controls. -1: auto; 0: disabled; 1: enabled; 2: enabled (swapped) | `RESET` | 0 | If value = 1 clear all saved data on the client | `PAGE_BACK_CSS` | -- | CSS to modify page background color. Applied to the body element ================================================ FILE: gruntfile.js ================================================ module.exports = function (grunt) { grunt.initConfig({ pkg: grunt.file.readJSON("package.json"), clean: { init: ["temp", "release/stable/5.0"], finish: ["temp"] }, concat: { emuPart: { src: [ "src/main/room/screen/FullScreenSetup.js", "src/main/util/Util.js", "src/main/util/MD5.js", "src/main/util/ZIP.js", "src/main/util/EmbeddedFiles.js", "src/main/util/MultiDownloader.js", "src/main/util/MultiFileReader.js", "src/main/atari/video/VideoStandard.js", "src/main/atari/video/VideoSignal.js", "src/main/atari/audio/AudioSignal.js", "src/main/atari/cpu/M6502.js", "src/main/atari/pia/Ram.js", "src/main/atari/pia/Pia.js", "src/main/atari/tia/TiaPalettes.js", "src/main/atari/tia/TiaAudio.js", "src/main/atari/tia/TiaAudioChannel.js", "src/main/atari/tia/Tia.js", "src/main/atari/console/Bus.js", "src/main/atari/console/AtariConsole.js", "src/main/atari/controls/JoystickButtons.js", "src/main/atari/controls/ConsoleControls.js", "src/main/atari/cartridge/ROM.js", "src/main/atari/cartridge/CartridgeDatabase.js", "src/main/atari/cartridge/Cartridge.js", "src/main/atari/cartridge/formats/Cartridge4K.js", "src/main/atari/cartridge/formats/Cartridge2K_CV.js", "src/main/atari/cartridge/formats/CartridgeBankedByMaskedRange.js", "src/main/atari/cartridge/formats/Cartridge8K_E0.js", "src/main/atari/cartridge/formats/Cartridge64K_F0.js", "src/main/atari/cartridge/formats/Cartridge8K_FE.js", "src/main/atari/cartridge/formats/Cartridge16K_E7.js", "src/main/atari/cartridge/formats/Cartridge10K_DPCa.js", "src/main/atari/cartridge/formats/Cartridge24K_28K_32K_FA2.js", "src/main/atari/cartridge/formats/CartridgeBankedByBusMonitoring.js", "src/main/atari/cartridge/formats/Cartridge8K_512K_3F.js", "src/main/atari/cartridge/formats/Cartridge8K_512K_3E.js", "src/main/atari/cartridge/formats/Cartridge8K_256K_SB.js", "src/main/atari/cartridge/formats/Cartridge8K_64K_AR.js", "src/main/atari/cartridge/formats/Cartridge64K_X07.js", "src/main/atari/cartridge/formats/Cartridge8K_0840.js", "src/main/atari/cartridge/formats/Cartridge8K_UA.js", "src/main/atari/cartridge/CartridgeFormats.js", "src/main/atari/cartridge/CartridgeCreator.js", "src/main/images/Images.js", "src/main/room/clock/Clock.js", "src/main/room/files/RecentStoredROMs.js", "src/main/room/files/FileLoader.js", "src/main/room/files/FileDownloader.js", "src/main/room/controls/DOMKeys.js", "src/main/room/controls/GamepadButtons.js", "src/main/room/controls/TouchControls.js", "src/main/room/controls/GamepadConsoleControls.js", "src/main/room/controls/DOMTouchControls.js", "src/main/room/controls/DOMConsoleControls.js", "src/main/room/screen/ScreenGUI.es5.js", "src/main/room/screen/Monitor.js", "src/main/room/screen/ConsolePanel.js", "src/main/room/screen/CanvasDisplay.js", "src/main/room/screen/dialogs/RecentROMsDialog.js", "src/main/room/screen/dialogs/SaveStateDialog.js", "src/main/room/screen/dialogs/QuickOptionsDialog.js", "src/main/room/screen/dialogs/NetPlayDialog.js", "src/main/room/screen/dialogs/CartridgeFormatDialog.js", "src/main/room/screen/settings/SettingsGUI.es5.js", "src/main/room/screen/settings/Settings.js", "src/main/room/speaker/WebAudioSpeaker.js", "src/main/room/savestate/LocalStorageSaveStateMedia.js", "src/main/room/controls/PeripheralControls.js", "src/main/room/controls/DOMPeripheralControls.js", "src/main/room/netplay/NetServer.js", "src/main/room/netplay/NetClient.js", "src/main/room/Room.js", "src/main/userprefs/UserPreferences.js", "src/main/userprefs/UserROMFormats.js", "src/runtime/images/EmbeddedImages.js", "src/main/Configurator.js", "src/main/Launcher.js" ], dest: "temp/javatari.part.js" }, emuFinal: { src: [ "src/main/Javatari.js", "temp/javatari.part.min.js" ], dest: "temp/javatari.js" }, standalone: { src: [ "src/runtime/standalone/index.part1.html", "temp/javatari.js", "src/runtime/standalone/index.part2.html" ], dest: "temp/index.html" } }, uglify: { emuPart: { options: { maxLineLen: 7900, mangle: { toplevel: true, screw_ie8: true }, compress: { screw_ie8: true, sequences: true, dead_code: true, drop_debugger: true, comparisons: true, conditionals: true, evaluate: true, booleans: true, loops: true, unused: true, if_return: true, hoist_funs: true, join_vars: true, cascade: true, unsafe: false } }, files: { "temp/javatari.part.min.js": ["temp/javatari.part.js"] } } }, copy: { standalone: { files: [ {src: "temp/index.html", dest: "release/stable/5.0/standalone", expand: true, flatten: true, filter: "isFile"}, {src: "src/runtime/standalone/cache.manifest", dest: "release/stable/5.0/standalone", expand: true, flatten: true, filter: "isFile"}, {src: "src/runtime/standalone/manifest.webapp", dest: "release/stable/5.0/standalone", expand: true, flatten: true, filter: "isFile"}, {src: "src/runtime/images/files/logo-icon192.png", dest: "release/stable/5.0/standalone/images", expand: true, flatten: true, filter: "isFile"}, {src: "src/runtime/images/files/logo-icon512.png", dest: "release/stable/5.0/standalone/images", expand: true, flatten: true, filter: "isFile"} ] }, embedded: { files: [ {src: "src/runtime/embedded/index.html", dest: "release/stable/5.0/embedded", expand: true, flatten: true, filter: "isFile"}, {src: "temp/javatari.js", dest: "release/stable/5.0/embedded", expand: true, flatten: true, filter: "isFile"} ] } } }); grunt.loadNpmTasks("grunt-contrib-clean"); grunt.loadNpmTasks("grunt-contrib-concat"); grunt.loadNpmTasks("grunt-contrib-uglify"); grunt.loadNpmTasks("grunt-contrib-copy"); grunt.registerTask("default", [ "clean:init", "concat:emuPart", "uglify:emuPart", "concat:emuFinal", "concat:standalone", "copy:standalone", "copy:embedded", "clean:finish" ]); }; ================================================ FILE: license.txt ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: package.json ================================================ { "name": "Javatari", "title": "Javatari - The online Atari 2600 emulator", "version": "5.0.4", "devDependencies": { "grunt": "", "grunt-contrib-clean": "", "grunt-contrib-concat": "", "grunt-contrib-uglify": "2.3.0", "grunt-contrib-copy": "" } } ================================================ FILE: release/stable/4.0/embedded/index.html ================================================ Javatari
================================================ FILE: release/stable/4.0/embedded/javatari.js ================================================ // Javatari version 4.0 // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Main Emulator parameters. // May be overridden dynamically by URL query parameters, if ALLOW_URL_PARAMETERS = true. Javatari = { PRESETS: "", // Configuration Presets to apply. See Presets Configuration // Full or relative URL of Media files to load CARTRIDGE_URL: "", AUTODETECT_URL: "", STATE_URL: "", // Forcing ROM formats CARTRIDGE_FORMAT: "", // 4K, F8, F4, FE, AR, etc... // General configuration AUTO_START: true, AUTO_POWER_ON_DELAY: 1200, // -1: no auto Power-ON; >= 0: wait specified milliseconds before Power-ON CARTRIDGE_SHOW_RECENT: true, CARTRIDGE_CHANGE_DISABLED: false, CARTRIDGE_LABEL_COLORS: "", // Space-separated colors for Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults SCREEN_RESIZE_DISABLED: false, SCREEN_CONSOLE_PANEL_DISABLED: false, SCREEN_ELEMENT_ID: "javatari-screen", CONSOLE_PANEL_ELEMENT_ID: -1, // -1: auto. Don't change! :-) SCREEN_FULLSCREEN_MODE: -1, // -2: disabled; -1: auto; 0: off; 1: on SCREEN_CRT_MODE: -1, // -1: auto; 0: off; 1: on SCREEN_FILTER_MODE: -1, // -2: browser default; -1: auto; 0..3: smoothing level SCREEN_DEFAULT_SCALE: -1, // -1: auto; 0.5..N in 0.1 steps: scale SCREEN_DEFAULT_ASPECT: 1, // in 0.1 steps SCREEN_CANVAS_SIZE: 2, // Internal canvas size factor. Don't change! :-) SCREEN_CONTROL_BAR: 1, // 0: on hover; 1: always SCREEN_FORCE_HOST_NATIVE_FPS: -1, // -1: auto. Don't change! :-) SCREEN_VSYNCH_MODE: 1, // -1: disabled; 0: off; 1: on AUDIO_MONITOR_BUFFER_BASE: -3, // -3: user set value; -2: disable audio; -1: auto; 0: browser default; 1..6: base value. More buffer = more delay AUDIO_MONITOR_BUFFER_SIZE: -1, // -1: auto; 256, 512, 1024, 2048, 4096, 8192, 16384: buffer size. More buffer = more delay. Don't change! :-) AUDIO_SIGNAL_BUFFER_RATIO: 2, // Internal Audio Signal buffer based on Monitor buffer AUDIO_SIGNAL_ADD_FRAMES: 3, // Additional frames in internal Audio Signal buffer based on Monitor buffer PADDLES_MODE: -1, // -1: auto; 0: off; 1: on TOUCH_MODE: -1, // -1: auto; 0: disabled; 1: enabled; 2: enabled (swapped) IMAGES_PATH: window.JAVATARI_IMAGES_PATH || "images/", RESET: 0, // if value = 1 clear all saved data on the client ALLOW_URL_PARAMETERS: true // Allows user to override any of these parameters via URL query parameters }; Javatari.PRESETS_CONFIG = { }; // No built-in Presets for now jt = window.jt || {}; // Namespace for all classes and objects function onUpdateReady(){alert("A new version is available!\nJavatari will restart..."),window.applicationCache.swapCache(),window.location.reload()}JavatariFullScreenSetup={apply:function(){if(!this.cssApplied){var a=document.createElement("style");a.type="text/css",a.innerHTML=this.css,document.head.appendChild(a),this.cssApplied=!0}document.documentElement.classList.toggle("jt-full-screen",this.shouldStartInFullScreen())},shouldStartInFullScreen:function(){return window.Javatari?1===Javatari.SCREEN_FULLSCREEN_MODE||Javatari.SCREEN_FULLSCREEN_MODE===-1&&this.isBrowserStandaloneMode():this.isBrowserStandaloneMode()},isBrowserStandaloneMode:function(){return navigator.standalone||window.matchMedia("(display-mode: standalone)").matches},css:"html.jt-full-screen, html.jt-full-screen body { background: black;}html.jt-full-screen .jt-full-screen-hidden { display: none;}html:not(.jt-full-screen) .jt-full-screen-only { display: none;}"},JavatariFullScreenSetup.apply(),jt.Util=new function(){"use strict";function a(a,b){return a.nameb.name?1:0}function b(a){return a.stopPropagation(),a.cancelable&&a.preventDefault(),!1}this.log=function(a){console.log(">> jt: "+a)},this.warning=function(a){console.warn(">> jt Warning: "+a)},this.error=function(a){console.error(">> jt Error: "+a)},this.message=function(a){console.info(a),alert(a)},this.asNormalArray=function(a){return a instanceof Array?a:this.arrayCopy(a,0,new Array(a.length))},this.arrayFill=function(a,b,c,d){if(a.fill)return a.fill(b,c,d);void 0===c&&(c=0);for(var e=(void 0===d?a.length:d)-1;e>=c;e-=1)a[e]=b;return a},this.arrayFillSegment=function(a,b,c,d){for(var e=c;e-- >b;)a[e]=d;return a},this.arrayCopy=function(a,b,c,d,e){d=d||0;for(var f=e?b+e:a.length;b=0;)a.splice(c,1);return a},this.arraysConcatAll=function(a){for(var b=0,c=0;c>1|(32&a)>>3|(64&a)>>5|(128&a)>>7},this.int8BitArrayToByteString=function(a,b,c){if(null===a||void 0==a)return a;void 0===b&&(b=0),void 0===c&&(c=a.length-b);for(var d="",e=b,f=b+c;e>8&255)+String.fromCharCode(a[e]>>16&255)+String.fromCharCode(a[e]>>24&255);return d},this.byteStringToInt32BitArray=function(a,b){if(null===a||void 0===a)return a;if("null"==a)return null;if("undefined"!=a){for(var c=a.length/4|0,d=b&&b.length===c?b:new(b?b.constructor:Array)(c),e=0,f=0;e=0&&b.length%2?"0"+b:b},this.toHex4=function(a){if(null===a||void 0===a)return a;var b=a.toString(16).toUpperCase();if(a<0)return b;switch(b.length){case 4:return b;case 3:return"0"+b;case 2:return"00"+b;case 1:return"000"+b;default:return b}},this.escapeHtml=function(a){return a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/").replace(/\?/g,"?").replace(/\-/g,"-").replace(/\|/g,"|")},this.arrayFind=function(a,b){if(a.find)return a.find(b);for(var c=0,d=a.length;c=0&&h=0?a.split("/").pop():a)||"").trim()},this.leafFilenameNoExtension=function(a){var b=this.leafFilename(a),c=b.lastIndexOf(".");return c<=0?b:b.substr(0,c).trim()},this.leafFilenameOnlyExtension=function(a){var b=this.leafFilename(a),c=b.lastIndexOf(".");return c<=0?"":b.substr(c+1).trim()},this.dump=function(a,b,c,d){var e="",f=b||0;d=d||1;for(var g=0;g0||navigator.msMaxTouchPoints>0},this.isMobileDevice=function(){return this.isTouchDevice()&&/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)},this.isIOSDevice=function(){return/ipad|iphone|ipod/i.test(navigator.userAgent)},this.isBrowserStandaloneMode=function(){return navigator.standalone||window.matchMedia("(display-mode: standalone)").matches},this.onTapOrMouseDown=function(a,b){this.addEventsListener(a,this.isTouchDevice()?"touchstart mousedown":"mousedown",b)},this.onTapOrMouseDownWithBlock=function(a,c){function d(a){return c(a),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart mousedown":"mousedown",d)},this.onTapOrMouseUpWithBlock=function(a,c){function d(a){return c(a),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart mouseup":"mouseup",d)},this.onTapOrMouseDownWithBlockUIG=function(a,c){function d(a){if(("touchstart"!==a.type||!a.target.jtNeedsUIG)&&("touchend"!==a.type||a.target.jtNeedsUIG))return c(a),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart touchend mousedown":"mousedown",d)},this.blockEvent=b,this.addEventsListener=function(a,b,c,d){b=b.split(" ");for(var e=0;e>>0).toString(16);return"00000000".substr(0,8-b.length)+b}function c(a){for(var b=[],c=0;c>>=8;return b}function e(a,b){return a<>>32-b}function f(a,b,c){return a&b|~a&c}function g(a,b,c){return c&a|~c&b}function h(a,b,c){return a^b^c}function i(a,b,c){return b^(a|~c)}function j(a,b){return a[b+3]<<24|a[b+2]<<16|a[b+1]<<8|a[b]}function k(a){for(var b=[],c=0;c=0;i--)h=arguments[i],g=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=h,f+=b(g);return f}function m(a){for(var b=new Array(a.length),c=0;c56){for(var k=0;k<64-c;k++)p.push(0);c=p.length%64}for(k=0;k<56-c;k++)p.push(0);p=p.concat(d(8*b));var m=1732584193,o=4023233417,q=2562383102,r=271733878,s=0,t=0,u=0,v=0;for(k=0;k>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i, j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\0\0",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b^=-1;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\0",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;gc;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b&&b,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\0",w+=p||q?"\0\b":"\0\0",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\0"+w+s(o.length,2)+"\0\0\0\0"+(j===!0?"\0\0\0":"\0\0\0\0")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(k(e.uint8array?a.subarray(c,h):a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(a){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d!==m||(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n)},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37, "./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d!==i.Z_FINISH||(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK)},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(a){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(a){g=!1}for(var h=new e.Buf8(256),i=0;256>i;i++)h[i]=i>=252?6:i>=248?5:i>=240?4:i>=224?3:i>=192?2:1;h[254]=h[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,i=b||a.length,j=new Array(2*i);for(e=0,c=0;i>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=h[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&i>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+h[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a^=-1;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-ja?a.strstart-(a.w_size-ja):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ia,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ia-(m-f),f=m-ia,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-ja)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=ha)for(f=a.strstart-a.insert, a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sa;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sa;if(a.strstart-a.block_start>=a.w_size-ja&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sa:sa}function o(a,b){for(var c,d;;){if(a.lookahead=ha&&(a.ins_h=(a.ins_h<=ha)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-ha),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=ha){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<=ha&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=ha-1)),a.prev_length>=ha&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-ha,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-ha),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<=ha&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ia;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ia-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=ha?(c=D._tr_tally(a,1,a.match_length-ha),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sa:ta}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sa;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sa:ta}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=ha-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fa),this.dyn_dtree=new C.Buf16(2*(2*da+1)),this.bl_tree=new C.Buf16(2*(2*ea+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(ga+1),this.heap=new C.Buf16(2*ca+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*ca+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?la:qa,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===ra&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===la)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=ma):(i(h,0),i(h,0),i(h,0), i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wa),h.status=qa);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=ka),m+=31-m%31,h.status=qa,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===ma)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=na)}else h.status=na;if(h.status===na)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=oa)}else h.status=oa;if(h.status===oa)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pa)}else h.status=pa;if(h.status===pa&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qa)):h.status=qa),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===ra&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==ra){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ua||o===va)&&(h.status=ra),o===sa||o===ua)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===ta&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==la&&b!==ma&&b!==na&&b!==oa&&b!==pa&&b!==qa&&b!==ra?d(a,O):(a.state=null,b===qa?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,aa=29,ba=256,ca=ba+1+aa,da=30,ea=19,fa=2*ca+1,ga=15,ha=3,ia=258,ja=ia+ha+1,ka=32,la=42,ma=69,na=73,oa=91,pa=103,qa=113,ra=666,sa=1,ta=2,ua=3,va=4,wa=3,xa=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xa(0,0,0,0,n),new xa(4,4,8,4,o),new xa(4,5,16,8,o),new xa(4,6,32,32,o),new xa(4,4,16,16,p),new xa(8,16,32,32,p),new xa(8,16,128,128,p),new xa(8,32,128,256,p),new xa(32,128,258,1024,p),new xa(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<q&&(p+=B[f++]<>>=w,q-=w),15>q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<q&&(p+=B[f++]<q&&(p+=B[f++]<k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(oa),b.distcode=b.distdyn=new r.Buf32(pa),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,ra)}function k(a){if(sa){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sa=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=la;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=la;break}if(m>>>=4,n-=4,wa=(15&m)+8,0===c.wbits)c.wbits=wa;else if(wa>c.wbits){a.msg="invalid window size",c.mode=la;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Ba[2]=m>>>16&255,Ba[3]=m>>>24&255,c.check=t(c.check,Ba,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wa=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wa)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.name+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.comment+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ia;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=ba,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=la}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=la;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=la;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Ca[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,ya={bits:c.lenbits},xa=v(w,c.lens,0,19,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid code lengths set",c.mode=la;break}c.have=0,c.mode=aa;case aa:for(;c.have>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<sa)m>>>=qa,n-=qa,c.lens[c.have++]=sa;else{if(16===sa){for(za=qa+2;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,0===c.have){a.msg="invalid bit length repeat",c.mode=la;break}wa=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sa){for(za=qa+3;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=3+(7&m),m>>>=3,n-=3}else{for(za=qa+7;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=la;break}for(;q--;)c.lens[c.have++]=wa}}if(c.mode===la)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=la;break}if(c.lenbits=9,ya={bits:c.lenbits},xa=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid literal/lengths set",c.mode=la;break}if(c.distbits=6,c.distcode=c.distdyn,ya={bits:c.distbits},xa=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,ya),c.distbits=ya.bits,xa){a.msg="invalid distances set",c.mode=la;break}if(c.mode=ba,b===B)break a;case ba:c.mode=ca;case ca:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Aa=c.lencode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,c.length=sa,0===ra){c.mode=ha;break}if(32&ra){c.back=-1,c.mode=V;break}if(64&ra){a.msg="invalid literal/length code",c.mode=la;break}c.extra=15&ra,c.mode=da;case da:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=ea;case ea:for(;Aa=c.distcode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,64&ra){a.msg="invalid distance code",c.mode=la;break}c.offset=sa,c.extra=15&ra,c.mode=fa;case fa:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=la;break}c.mode=ga;case ga:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=la;break}q>c.wnext?(q-=c.wnext,oa=c.wsize-q):oa=c.wnext-q,q>c.length&&(q=c.length),pa=c.window}else pa=f,oa=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pa[oa++];while(--q);0===c.length&&(c.mode=ca);break;case ha:if(0===j)break a;f[h++]=c.length,j--,c.mode=ca;break;case ia:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?ga[a]:ga[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ia[d]=c,a=0;a<1<<_[d];a++)ha[c++]=d;for(ha[c-1]=d,e=0,d=0;16>d;d++)for(ja[d]=e,a=0;a<1<>=7;R>d;d++)for(ja[d]=e<<7,a=0;a<1<=b;b++)f[b]=0;for(a=0;143>=a;)ea[2*a+1]=8,a++,f[8]++;for(;255>=a;)ea[2*a+1]=9,a++,f[9]++;for(;279>=a;)ea[2*a+1]=7,a++,f[7]++;for(;287>=a;)ea[2*a+1]=8,a++,f[8]++;for(l(ea,Q+1,f),a=0;R>a;a++)fa[2*a+1]=5,fa[2*a]=i(a,5);ka=new na(ea,_,P+1,Q,U),la=new na(fa,aa,0,R,U),ma=new na(new Array(0),ba,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++jj){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code), t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*ca[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*ca[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pa||(m(),pa=!0),a.l_desc=new oa(a.dyn_ltree,ka),a.d_desc=new oa(a.dyn_dtree,la),a.bl_desc=new oa(a.bl_tree,ma),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,ea),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,ea,fa)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(ha[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],aa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],ba=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],ca=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],da=512,ea=new Array(2*(Q+2));d(ea);var fa=new Array(2*R);d(fa);var ga=new Array(da);d(ga);var ha=new Array(N-M+1);d(ha);var ia=new Array(O);d(ia);var ja=new Array(R);d(ja);var ka,la,ma,na=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},oa=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pa=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}),jt.EmbeddedFiles={get:function(a){var b=this.compressedContent[a];if(void 0!==b)return{name:a,content:jt.Util.uncompressStringBase64ToInt8BitArray(b)};var c=this.diffsContent[a];if(void 0!==c){var d=this.get(c.based);if(void 0!==d){var e=d.content;for(var f in c.diffs)for(var g=c.diffs[f],h=0;h0||(a.success=!0,a.content=jt.Util.arraysConcatAll(a.filesContent),a.onSuccess&&a.onSuccess(a),j())}function i(a,b){a.success=!1,a.error=b;var d="Could not load file: "+a.url+"\nError: "+b;a.onError?(jt.Util.error(d),a.onError(a)):c||jt.Util.message(d),j()}function j(){if(!q){for(var d=0;dd){var j="Maximum total size limit exceeded: "+(d/1024|0)+"KB";return void(c&&c(a,j,!0))}for(i=0;i0){if(p<=0)return void(n=0);g(),--n,--p}}function f(){var a=s*Javatari.AUDIO_SIGNAL_BUFFER_RATIO+k*Javatari.AUDIO_SIGNAL_ADD_FRAMES|0;r.length=a,a>o&&jt.Util.arrayFill(r,0,o,a),o=a,t.bufferSize=o,q=o-2,j.flush()}function g(){r[l]=b.nextSample()*d,++l>=o&&(l=0)}function h(){r[l]=0,++l>=o&&(l=0)}function i(a,b){if(b)for(var c=a;c>0;c-=1)h();else for(var d=a;d>0;d-=1)g();p-=a}var j=this;this.flush=function(){l=0,m=0,p=q},this.setFps=function(a){k=c/a|0,f()},this.audioFinishFrame=function(){if(n>0)for(;n>0;)e();n=k},this.retrieveSamples=function(a,b){ var c=q-p,d=a-c;d>0&&(d>p&&(d=p),i(d,b)),t.start=m;var e=c+d;return p+=e,m+=e,m>=o&&(m-=o),t},this.audioClockPulse=e,this.getSampleRate=function(){return c},this.toString=function(){return"AudioSignal "+a},this.setAudioMonitorBufferSize=function(a){s=a,f()},this.name=a;var k,l=0,m=0,n=0,o=0,p=0,q=0,r=jt.Util.arrayFill(new Array(o),0),s=0,t={buffer:r,bufferSize:o,start:0}},jt.M6502=function(){"use strict";function a(){return Jb(function(){Cb(Ba>127),Ba=Ba<<1&255,zb(Ba),Ab(Ba)})}function b(){return Jb(function(){Ja=0})}function c(){return Jb(function(){Ga=0})}function d(){return Jb(function(){Ha=0})}function e(){return Jb(function(){Fa=0})}function f(){return Jb(function(){Ca=Ca-1&255,zb(Ca),Ab(Ca)})}function g(){return Jb(function(){Da=Da-1&255,zb(Da),Ab(Da)})}function h(){return Jb(function(){Ca=Ca+1&255,zb(Ca),Ab(Ca)})}function i(){return Jb(function(){Da=Da+1&255,zb(Da),Ab(Da)})}function j(){return Jb(function(){Ja=1&Ba,Ba>>>=1,zb(Ba),Ea=0})}function k(){return Jb(function(){})}function l(){return Jb(function(){var a=Ba>127;Ba=255&(Ba<<1|Ja),Cb(a),zb(Ba),Ab(Ba)})}function m(){return Jb(function(){var a=1&Ba;Ba=Ba>>>1|Ja<<7,Cb(a),zb(Ba),Ab(Ba)})}function n(){return Jb(function(){Ja=1})}function o(){return Jb(function(){Ga=1})}function p(){return Jb(function(){Ha=1})}function q(){return Jb(function(){Ca=Ba,zb(Ca),Ab(Ca)})}function r(){return Jb(function(){Da=Ba,zb(Da),Ab(Da)})}function s(){return Jb(function(){Ca=Aa,zb(Ca),Ab(Ca)})}function t(){return Jb(function(){Ba=Ca,zb(Ba),Ab(Ba)})}function u(){return Jb(function(){Aa=Ca})}function v(){return Jb(function(){Ba=Da,zb(Ba),Ab(Ba)})}function w(){return[_a,function(){Ib("KIL/HLT/JAM")},function(){Ka--}]}function x(a){return a(function(){Ib("NOP/DOP")})}function y(a){return a(function(){if(Ga){var a=Ma,b=(15&Ba)+(15&a)+Ja;b>9&&(b+=6);var c=(Ba>>4)+(a>>4)+(b>15)<<4;zb(Ba+a+Ja&255),Ab(c),Bb((Ba^c)&~(Ba^a)&128),c>159&&(c+=96),Cb(c>255),Ba=255&(c|15&b)}else{var d=Ba+Ma+Ja;Cb(d>255),Bb((Ba^d)&(Ma^d)&128),Ba=255&d,zb(Ba),Ab(Ba)}})}function z(a){return a(function(){Ba&=Ma,zb(Ba),Ab(Ba)})}function A(a){return a(function(){var a=Ma;zb(Ba&a),Bb(64&a),Ab(a)})}function B(a){return a(function(){var a=Ba-Ma&255;Cb(Ba>=Ma),zb(a),Ab(a)})}function C(a){return a(function(){var a=Ca-Ma&255;Cb(Ca>=Ma),zb(a),Ab(a)})}function D(a){return a(function(){var a=Da-Ma&255;Cb(Da>=Ma),zb(a),Ab(a)})}function E(a){return a(function(){Ba^=Ma,zb(Ba),Ab(Ba)})}function F(a){return a(function(){Ba=Ma,zb(Ba),Ab(Ba)})}function G(a){return a(function(){Ca=Ma,zb(Ca),Ab(Ca)})}function H(a){return a(function(){Da=Ma,zb(Da),Ab(Da)})}function I(a){return a(function(){Ba|=Ma,zb(Ba),Ab(Ba)})}function J(a){return a(function(){if(Ga){var a=Ma,b=(15&Ba)-(15&a)-(1-Ja),c=(Ba>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=Ba-a-(1-Ja);Cb(256&~d),Bb((Ba^a)&(Ba^d)&128),zb(255&d),Ab(d),Ba=255&(c<<4|15&b)}else a=255&~Ma,d=Ba+a+Ja,Cb(d>255),Bb((Ba^d)&(a^d)&128),Ba=255&d,zb(Ba),Ab(Ba)})}function K(a){return a(function(){Ib("ANC"),Ba&=Ma,zb(Ba),Ea=Ja=128&Ba?1:0})}function L(a){return a(function(){Ib("ANE")})}function M(a){return a(function(){Ib("ARR");var a=Ba&Ma,b=Ja?128:0;a=a>>>1|b,Ba=a,zb(a),Ab(a);var c=96&Ba;96==c?(Ja=1,Fa=0):0==c?(Ja=0,Fa=0):32==c?(Ja=0,Fa=1):64==c&&(Ja=1,Fa=1)})}function N(a){return a(function(){Ib("ASR");var a=Ba&Ma;Ja=1&a,a>>>=1,Ba=a,zb(a),Ea=0})}function O(a){return a(function(){Ib("LAS");var a=Aa&Ma;Ba=a,Ca=a,Aa=a,zb(a),Ab(a)})}function P(a){return a(function(){Ib("LAX");var a=Ma;Ba=a,Ca=a,zb(a),Ab(a)})}function Q(a){return a(function(){Ib("LXA");var a=Ba&Ma;Ba=a,Ca=a,zb(a),Ab(a)})}function R(a){return a(function(){Ib("SBX");var a=Ba&Ca,b=Ma,c=a-b&255;Ca=c,Cb(a>=b),zb(c),Ab(c)})}function S(a){return a(function(){Ma=Ba})}function T(a){return a(function(){Ma=Ca})}function U(a){return a(function(){Ma=Da})}function V(a){return a(function(){Ib("SAX"),Ma=Ba&Ca})}function W(a){return a(function(){Ib("SHA"),Ma=Ba&Ca&(Oa>>>8)+1&255})}function X(a){return a(function(){Ib("SHS");var a=Ba&Ca;Aa=a,Ma=a&(Oa>>>8)+1&255})}function Y(a){return a(function(){Ib("SHX"),Ma=Ca&(Oa>>>8)+1&255})}function Z(a){return a(function(){Ib("SHY"),Ma=Da&(Oa>>>8)+1&255})}function $(a){return a(function(){Cb(Ma>127);var a=Ma<<1&255;Ma=a,zb(a),Ab(a)})}function _(a){return a(function(){var a=Ma-1&255;Ma=a,zb(a),Ab(a)})}function aa(a){return a(function(){var a=Ma+1&255;Ma=a,zb(a),Ab(a)})}function ba(a){return a(function(){Ja=1&Ma,Ma>>>=1,zb(Ma),Ea=0})}function ca(a){return a(function(){var a=Ma>127,b=255&(Ma<<1|Ja);Ma=b,Cb(a),zb(b),Ab(b)})}function da(a){return a(function(){var a=1&Ma,b=Ma>>>1|Ja<<7;Ma=b,Cb(a),zb(b),Ab(b)})}function ea(a){return a(function(){Ib("DCP");var a=Ma-1&255;Ma=a,a=Ba-a,Cb(a>=0),zb(a),Ab(a)})}function fa(a){return a(function(){if(Ib("ISB"),Ma=Ma+1&255,Ga){var a=Ma,b=(15&Ba)-(15&a)-(1-Ja),c=(Ba>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=Ba-a-(1-Ja);Cb(256&~d),Bb((Ba^a)&(Ba^d)&128),zb(255&d),Ab(d),Ba=255&(c<<4|15&b)}else a=255&~Ma,d=Ba+a+Ja,Cb(d>255),Bb((Ba^d)&(a^d)&128),Ba=255&d,zb(Ba),Ab(Ba)})}function ga(a){return a(function(){Ib("RLA");var a=Ma,b=Ja;Cb(128&a),a=255&(a<<1|b),Ma=a,Ba&=a,zb(a),Ab(a)})}function ha(a){return a(function(){Ib("RRA");var a=Ma,b=Ja?128:0;if(Cb(1&a),a=a>>>1|b,Ma=a,Ga){var c=Ma,d=(15&Ba)+(15&c)+Ja;d>9&&(d+=6);var e=(Ba>>4)+(c>>4)+(d>15)<<4;zb(Ba+c+Ja&255),Ab(e),Bb((Ba^e)&~(Ba^c)&128),e>159&&(e+=96),Cb(e>255),Ba=255&(e|15&d)}else{var f=Ba+Ma+Ja;Cb(f>255),Bb((Ba^f)&(Ma^f)&128),Ba=255&f,zb(Ba),Ab(Ba)}})}function ia(a){return a(function(){Ib("SLO");var a=Ma;Cb(128&a),a=a<<1&255,Ma=a,a|=Ba,Ba=a,zb(a),Ab(a)})}function ja(a){return a(function(){Ib("SRE");var a=Ma;Cb(1&a),a>>>=1,Ma=a,a=255&(Ba^a),Ba=a,zb(a),Ab(a)})}function ka(){return[_a,bb,function(){Fb(Ba)},ab]}function la(){return[_a,bb,function(){Fb(Gb())},ab]}function ma(){return[_a,bb,Eb,function(){Ba=Db(),zb(Ba),Ab(Ba)},ab]}function na(){return[_a,bb,Eb,function(){Hb(Db())},ab]}function oa(){return[_a,db,Eb,function(){Fb(za>>>8&255)},function(){Fb(255&za)},eb,function(){za=Na,ab()}]}function pa(){return[_a,sb,function(){va.debug&&va.breakpoint("BRK "+Ma),Fb(za>>>8&255)},function(){Fb(255&za)},function(){Fb(Gb())},function(){Na=wa.read(Ua)},function(){Na|=wa.read(Ua+1)<<8},function(){za=Na,ab()}]}function qa(){return[_a,bb,Eb,function(){Hb(Db())},function(){Na=Db()},function(){Na|=Db()<<8},function(){za=Na,ab()}]}function ra(){return[_a,bb,Eb,function(){Na=Db()},function(){Na|=Db()<<8},function(){za=Na,sb()},ab]}function sa(){return[_a,db,eb,function(){za=Na,ab()}]}function ta(){return[_a,pb,qb,jb,function(){rb(),kb()},function(){za=Oa,ab()}]}function ua(a,b){var c;return c=a===Za?function(){return Ia===b}:a===Xa?function(){return Ea===b}:a===$a?function(){return Ja===b}:function(){return Fa===b},[_a,cb,function(){c()?(bb(),xb()):ab()},function(){Sa?(bb(),yb()):ab()},ab]}var va=this;this.powerOn=function(){this.reset()},this.powerOff=function(){},this.clockPulse=function(){ya&&(Ka++,xa[Ka]())},this.connectBus=function(a){wa=a},this.setRDY=function(a){ya=a},this.reset=function(){Ha=1,Ka=-1,xa=[_a],za=wa.read(Ta)|wa.read(Ta+1)<<8,this.setRDY(!0)};var wa,xa,ya=!1,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=-1,La=-1,Ma=0,Na=0,Oa=0,Pa=!1,Qa=0,Ra=0,Sa=0,Ta=65532,Ua=65534,Va=0,Wa=1,Xa=7,Ya=6,Za=1,$a=0;this.debug=!1,this.trace=!1;var _a=function(){La=wa.read(za),xa=cc[La],Ka=0,za++},ab=_a,bb=function(){wa.read(za)},cb=function(){Ra=wa.read(za),za++},db=function(){Na=wa.read(za),za++},eb=function(){Na|=wa.read(za)<<8,za++},fb=function(){Na=wa.read(Oa)},gb=function(){Na|=wa.read(Oa)<<8},hb=function(){Oa=wa.read(za),za++},ib=function(){Oa|=wa.read(za)<<8,za++},jb=function(){Oa=wa.read(Qa)},kb=function(){Oa|=wa.read(Qa)<<8},lb=function(){var a=(255&Oa)+Ca;Pa=a>255,Oa=65280&Oa|255&a},mb=function(){var a=(255&Oa)+Da;Pa=a>255,Oa=65280&Oa|255&a},nb=function(){var a=(255&Oa)+1;Pa=a>255,Oa=65280&Oa|255&a},ob=function(){Pa&&(Oa=Oa+256&65535)},pb=function(){Qa=wa.read(za),za++},qb=function(){ Qa|=wa.read(za)<<8,za++},rb=function(){var a=(255&Qa)+1;Qa=65280&Qa|255&a},sb=function(){Ma=wa.read(za),za++},tb=function(){Ma=wa.read(Na)},ub=function(){Ma=wa.read(Oa)},vb=function(){wa.write(Na,Ma)},wb=function(){wa.write(Oa,Ma)},xb=function(){var a=255&za,b=a+Ra&255;Sa=Ra>127?b>a?-256:0:b>>7,Fa=a>>>6&1,Ga=a>>>3&1,Ha=a>>>2&1,Ia=a>>>1&1,Ja=1&a},Ib=function(a){va.debug&&va.breakpoint("Illegal Opcode: "+a)},Jb=function(a){return[_a,bb,function(){a(),ab()}]},Kb=function(a){return[_a,sb,function(){a(),ab()}]},Lb=function(a){return[_a,db,tb,function(){a(),ab()}]},Mb=function(a){return[_a,db,eb,tb,function(){a(),ab()}]},Nb=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},tb,function(){a(),ab()}]},Ob=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},function(){Pa?ub():(a(),ab())},function(){a(),ab()}]}},Pb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),ub()},function(){a(),ab()}]}},Qb=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},function(){Pa?ub():(a(),ab())},function(){a(),ab()}]},Rb=function(a){return[_a,db,function(){a(),vb()},ab]},Sb=function(a){return[_a,db,eb,function(){a(),vb()},ab]},Tb=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},function(){a(),vb()},ab]},Ub=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},function(){a(),wb()},ab]}},Vb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),a(),wb()},ab]}},Wb=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},function(){a(),wb()},ab]},Xb=function(a){return[_a,db,tb,vb,function(){a(),vb()},ab]},Yb=function(a){return[_a,db,eb,tb,vb,function(){a(),vb()},ab]},Zb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),ub()},wb,function(){a(),wb()},ab]}},$b=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},ub,wb,function(){a(),wb()},ab]}},_b=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},tb,vb,function(){a(),vb()},ab]},ac=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},ub,wb,function(){a(),wb()},ab]},bc=new Array(256),cc=new Array(256);bc[0]="BRK",cc[0]=pa(),bc[1]="ORA",cc[1]=I(Nb),bc[2]="uKIL",cc[2]=w(),bc[3]="uSLO",cc[3]=ia(_b),bc[4]="uNOP",cc[4]=x(Lb),bc[5]="ORA",cc[5]=I(Lb),bc[6]="ASL",cc[6]=$(Xb),bc[7]="uSLO",cc[7]=ia(Xb),bc[8]="PHP",cc[8]=la(),bc[9]="ORA",cc[9]=I(Kb),bc[10]="ASL",cc[10]=a(),bc[11]="uANC",cc[11]=K(Kb),bc[12]="uNOP",cc[12]=x(Mb),bc[13]="ORA",cc[13]=I(Mb),bc[14]="ASL",cc[14]=$(Yb),bc[15]="uSLO",cc[15]=ia(Yb),bc[16]="BPL",cc[16]=ua(Xa,0),bc[17]="ORA",cc[17]=I(Qb),bc[18]="uKIL",cc[18]=w(),bc[19]="uSLO",cc[19]=ia(ac),bc[20]="uNOP",cc[20]=x(Pb(Va)),bc[21]="ORA",cc[21]=I(Pb(Va)),bc[22]="ASL",cc[22]=$(Zb(Va)),bc[23]="uSLO",cc[23]=ia(Zb(Va)),bc[24]="CLC",cc[24]=b(),bc[25]="ORA",cc[25]=I(Ob(Wa)),bc[26]="uNOP",cc[26]=x(Jb),bc[27]="uSLO",cc[27]=ia($b(Wa)),bc[28]="uNOP",cc[28]=x(Ob(Va)),bc[29]="ORA",cc[29]=I(Ob(Va)),bc[30]="ASL",cc[30]=$($b(Va)),bc[31]="uSLO",cc[31]=ia($b(Va)),bc[32]="JSR",cc[32]=oa(),bc[33]="AND",cc[33]=z(Nb),bc[34]="uKIL",cc[34]=w(),bc[35]="uRLA",cc[35]=ga(_b),bc[36]="BIT",cc[36]=A(Lb),bc[37]="AND",cc[37]=z(Lb),bc[38]="ROL",cc[38]=ca(Xb),bc[39]="uRLA",cc[39]=ga(Xb),bc[40]="PLP",cc[40]=na(),bc[41]="AND",cc[41]=z(Kb),bc[42]="ROL",cc[42]=l(),bc[43]="uANC",cc[43]=K(Kb),bc[44]="BIT",cc[44]=A(Mb),bc[45]="AND",cc[45]=z(Mb),bc[46]="ROL",cc[46]=ca(Yb),bc[47]="uRLA",cc[47]=ga(Yb),bc[48]="BMI",cc[48]=ua(Xa,1),bc[49]="AND",cc[49]=z(Qb),bc[50]="uKIL",cc[50]=w(),bc[51]="uRLA",cc[51]=ga(ac),bc[52]="uNOP",cc[52]=x(Pb(Va)),bc[53]="AND",cc[53]=z(Pb(Va)),bc[54]="ROL",cc[54]=ca(Zb(Va)),bc[55]="uRLA",cc[55]=ga(Zb(Va)),bc[56]="SEC",cc[56]=n(),bc[57]="AND",cc[57]=z(Ob(Wa)),bc[58]="uNOP",cc[58]=x(Jb),bc[59]="uRLA",cc[59]=ga($b(Wa)),bc[60]="uNOP",cc[60]=x(Ob(Va)),bc[61]="AND",cc[61]=z(Ob(Va)),bc[62]="ROL",cc[62]=ca($b(Va)),bc[63]="uRLA",cc[63]=ga($b(Va)),bc[64]="RTI",cc[64]=qa(),bc[65]="EOR",cc[65]=E(Nb),bc[66]="uKIL",cc[66]=w(),bc[67]="uSRE",cc[67]=ja(_b),bc[68]="uNOP",cc[68]=x(Lb),bc[69]="EOR",cc[69]=E(Lb),bc[70]="LSR",cc[70]=ba(Xb),bc[71]="uSRE",cc[71]=ja(Xb),bc[72]="PHA",cc[72]=ka(),bc[73]="EOR",cc[73]=E(Kb),bc[74]="LSR",cc[74]=j(),bc[75]="uASR",cc[75]=N(Kb),bc[76]="JMP",cc[76]=sa(),bc[77]="EOR",cc[77]=E(Mb),bc[78]="LSR",cc[78]=ba(Yb),bc[79]="uSRE",cc[79]=ja(Yb),bc[80]="BVC",cc[80]=ua(Ya,0),bc[81]="EOR",cc[81]=E(Qb),bc[82]="uKIL",cc[82]=w(),bc[83]="uSRE",cc[83]=ja(ac),bc[84]="uNOP",cc[84]=x(Pb(Va)),bc[85]="EOR",cc[85]=E(Pb(Va)),bc[86]="LSR",cc[86]=ba(Zb(Va)),bc[87]="uSRE",cc[87]=ja(Zb(Va)),bc[88]="CLI",cc[88]=d(),bc[89]="EOR",cc[89]=E(Ob(Wa)),bc[90]="uNOP",cc[90]=x(Jb),bc[91]="uSRE",cc[91]=ja($b(Wa)),bc[92]="uNOP",cc[92]=x(Ob(Va)),bc[93]="EOR",cc[93]=E(Ob(Va)),bc[94]="LSR",cc[94]=ba($b(Va)),bc[95]="uSRE",cc[95]=ja($b(Va)),bc[96]="RTS",cc[96]=ra(),bc[97]="ADC",cc[97]=y(Nb),bc[98]="uKIL",cc[98]=w(),bc[99]="uRRA",cc[99]=ha(_b);bc[100]="uNOP";cc[100]=x(Lb),bc[101]="ADC",cc[101]=y(Lb),bc[102]="ROR",cc[102]=da(Xb),bc[103]="uRRA",cc[103]=ha(Xb),bc[104]="PLA",cc[104]=ma(),bc[105]="ADC",cc[105]=y(Kb),bc[106]="ROR",cc[106]=m(),bc[107]="uARR",cc[107]=M(Kb),bc[108]="JMP",cc[108]=ta(),bc[109]="ADC",cc[109]=y(Mb),bc[110]="ROR",cc[110]=da(Yb),bc[111]="uRRA",cc[111]=ha(Yb),bc[112]="BVS",cc[112]=ua(Ya,1),bc[113]="ADC",cc[113]=y(Qb),bc[114]="uKIL",cc[114]=w(),bc[115]="uRRA",cc[115]=ha(ac),bc[116]="uNOP",cc[116]=x(Pb(Va)),bc[117]="ADC",cc[117]=y(Pb(Va)),bc[118]="ROR",cc[118]=da(Zb(Va)),bc[119]="uRRA",cc[119]=ha(Zb(Va)),bc[120]="SEI",cc[120]=p(),bc[121]="ADC",cc[121]=y(Ob(Wa)),bc[122]="uNOP",cc[122]=x(Jb),bc[123]="uRRA",cc[123]=ha($b(Wa)),bc[124]="uNOP",cc[124]=x(Ob(Va)),bc[125]="ADC",cc[125]=y(Ob(Va)),bc[126]="ROR",cc[126]=da($b(Va)),bc[127]="uRRA",cc[127]=ha($b(Va)),bc[128]="uNOP",cc[128]=x(Kb),bc[129]="STA",cc[129]=S(Tb),bc[130]="uNOP",cc[130]=x(Kb),bc[131]="uSAX",cc[131]=V(Tb),bc[132]="STY",cc[132]=U(Rb),bc[133]="STA",cc[133]=S(Rb),bc[134]="STX",cc[134]=T(Rb),bc[135]="uSAX",cc[135]=V(Rb),bc[136]="DEY",cc[136]=g(),bc[137]="uNOP",cc[137]=x(Kb),bc[138]="TXA",cc[138]=t(),bc[139]="uANE",cc[139]=L(Kb),bc[140]="STY",cc[140]=U(Sb),bc[141]="STA",cc[141]=S(Sb),bc[142]="STX",cc[142]=T(Sb),bc[143]="uSAX",cc[143]=V(Sb),bc[144]="BCC",cc[144]=ua($a,0),bc[145]="STA",cc[145]=S(Wb),bc[146]="uKIL",cc[146]=w(),bc[147]="uSHA",cc[147]=W(Wb),bc[148]="STY",cc[148]=U(Vb(Va)),bc[149]="STA",cc[149]=S(Vb(Va)),bc[150]="STX",cc[150]=T(Vb(Wa)),bc[151]="uSAX",cc[151]=V(Vb(Wa)),bc[152]="TYA",cc[152]=v(),bc[153]="STA",cc[153]=S(Ub(Wa)),bc[154]="TXS",cc[154]=u(),bc[155]="uSHS",cc[155]=X(Ub(Wa)),bc[156]="uSHY",cc[156]=Z(Ub(Va)),bc[157]="STA",cc[157]=S(Ub(Va)),bc[158]="uSHX",cc[158]=Y(Ub(Wa)),bc[159]="uSHA",cc[159]=W(Ub(Wa)),bc[160]="LDY",cc[160]=H(Kb),bc[161]="LDA",cc[161]=F(Nb),bc[162]="LDX",cc[162]=G(Kb),bc[163]="uLAX",cc[163]=P(Nb),bc[164]="LDY",cc[164]=H(Lb),bc[165]="LDA",cc[165]=F(Lb),bc[166]="LDX",cc[166]=G(Lb),bc[167]="uLAX",cc[167]=P(Lb),bc[168]="TAY",cc[168]=r(),bc[169]="LDA",cc[169]=F(Kb),bc[170]="TAX",cc[170]=q(),bc[171]="uLXA",cc[171]=Q(Kb),bc[172]="LDY",cc[172]=H(Mb),bc[173]="LDA",cc[173]=F(Mb),bc[174]="LDX",cc[174]=G(Mb),bc[175]="uLAX",cc[175]=P(Mb),bc[176]="BCS",cc[176]=ua($a,1),bc[177]="LDA",cc[177]=F(Qb),bc[178]="uKIL",cc[178]=w(),bc[179]="uLAX",cc[179]=P(Qb),bc[180]="LDY",cc[180]=H(Pb(Va)),bc[181]="LDA",cc[181]=F(Pb(Va)),bc[182]="LDX",cc[182]=G(Pb(Wa)),bc[183]="uLAX",cc[183]=P(Pb(Wa)),bc[184]="CLV", cc[184]=e(),bc[185]="LDA",cc[185]=F(Ob(Wa)),bc[186]="TSX",cc[186]=s(),bc[187]="uLAS",cc[187]=O(Ob(Wa)),bc[188]="LDY",cc[188]=H(Ob(Va)),bc[189]="LDA",cc[189]=F(Ob(Va)),bc[190]="LDX",cc[190]=G(Ob(Wa)),bc[191]="uLAX",cc[191]=P(Ob(Wa)),bc[192]="CPY",cc[192]=D(Kb),bc[193]="CMP",cc[193]=B(Nb),bc[194]="uNOP",cc[194]=x(Kb),bc[195]="uDCP",cc[195]=ea(_b),bc[196]="CPY",cc[196]=D(Lb),bc[197]="CMP",cc[197]=B(Lb),bc[198]="DEC",cc[198]=_(Xb),bc[199]="uDCP",cc[199]=ea(Xb),bc[200]="INY";cc[200]=i();bc[201]="CMP",cc[201]=B(Kb),bc[202]="DEX",cc[202]=f(),bc[203]="uSBX",cc[203]=R(Kb),bc[204]="CPY",cc[204]=D(Mb),bc[205]="CMP",cc[205]=B(Mb),bc[206]="DEC",cc[206]=_(Yb),bc[207]="uDCP",cc[207]=ea(Yb),bc[208]="BNE",cc[208]=ua(Za,0),bc[209]="CMP",cc[209]=B(Qb),bc[210]="uKIL",cc[210]=w(),bc[211]="uDCP",cc[211]=ea(ac),bc[212]="uNOP",cc[212]=x(Pb(Va)),bc[213]="CMP",cc[213]=B(Pb(Va)),bc[214]="DEC",cc[214]=_(Zb(Va)),bc[215]="uDCP",cc[215]=ea(Zb(Va)),bc[216]="CLD",cc[216]=c(),bc[217]="CMP",cc[217]=B(Ob(Wa)),bc[218]="uNOP",cc[218]=x(Jb),bc[219]="uDCP",cc[219]=ea($b(Wa)),bc[220]="uNOP",cc[220]=x(Ob(Va)),bc[221]="CMP",cc[221]=B(Ob(Va)),bc[222]="DEC",cc[222]=_($b(Va)),bc[223]="uDCP",cc[223]=ea($b(Va)),bc[224]="CPX",cc[224]=C(Kb),bc[225]="SBC",cc[225]=J(Nb),bc[226]="uNOP",cc[226]=x(Kb),bc[227]="uISB",cc[227]=fa(_b),bc[228]="CPX",cc[228]=C(Lb),bc[229]="SBC",cc[229]=J(Lb),bc[230]="INC",cc[230]=aa(Xb),bc[231]="uISB",cc[231]=fa(Xb),bc[232]="newINX",cc[232]=h(),bc[233]="SBC",cc[233]=J(Kb),bc[234]="NOP",cc[234]=k(),bc[235]="SBC",cc[235]=J(Kb),bc[236]="CPX",cc[236]=C(Mb),bc[237]="SBC",cc[237]=J(Mb),bc[238]="INC",cc[238]=aa(Yb),bc[239]="uISB",cc[239]=fa(Yb),bc[240]="BEQ",cc[240]=ua(Za,1),bc[241]="SBC",cc[241]=J(Qb),bc[242]="uKIL",cc[242]=w(),bc[243]="uISB",cc[243]=fa(ac),bc[244]="uNOP",cc[244]=x(Pb(Va)),bc[245]="SBC",cc[245]=J(Pb(Va)),bc[246]="INC",cc[246]=aa(Zb(Va)),bc[247]="uISB",cc[247]=fa(Zb(Va)),bc[248]="SED",cc[248]=o(),bc[249]="SBC",cc[249]=J(Ob(Wa)),bc[250]="uNOP",cc[250]=x(Jb),bc[251]="uISB",cc[251]=fa($b(Wa)),bc[252]="uNOP",cc[252]=x(Ob(Va)),bc[253]="SBC",cc[253]=J(Ob(Va)),bc[254]="INC",cc[254]=aa($b(Va)),bc[255]="uISB",cc[255]=fa($b(Va)),this.saveState=function(){return{PC:za,A:Ba,X:Ca,Y:Da,SP:Aa,N:Ea,V:Fa,D:Ga,I:Ha,Z:Ia,C:Ja,T:Ka,o:La,R:0|ya,d:Ma,AD:Na,BA:Oa,BC:0|Pa,IA:Qa,bo:Ra,boa:Sa}},this.loadState=function(a){za=a.PC,Ba=a.A,Ca=a.X,Da=a.Y,Aa=a.SP,Ea=a.N,Fa=a.V,Ga=a.D,Ha=a.I,Ia=a.Z,Ja=a.C,Ka=a.T,La=a.o,ya=!!a.R,Ma=a.d,Na=a.AD,Oa=a.BA,Pa=!!a.BC,Qa=a.IA,Ra=a.bo,Sa=a.boa,xa=cc[La]},this.toString=function(){return"CPU PC: "+za.toString(16)+" op: "+La.toString()+" T: "+Ka+" data: "+Ma+"\n A: "+Ba.toString(16)+" X: "+Ca.toString(16)+" Y: "+Da.toString(16)+" SP: "+Aa.toString(16)+" N"+Ea+" V"+Fa+" D"+Ga+" I"+Ha+" Z"+Ia+" C"+Ja+" "},this.breakpoint=function(a){if(jt.Util.log(a),this.trace){var b="CPU Breakpoint! "+(a?"("+a+")":"")+"\n\n"+this.toString();jt.Util.message(b)}},this.runCycles=function(a){for(var b=performance.now(),c=0;c=0;a--)b[a]=256*Math.random()|0}this.powerOn=function(){},this.powerOff=function(){},this.read=function(a){return b[a&c]},this.write=function(a,d){b[a&c]=d},this.powerFry=function(){for(var a=1-f+2*Math.random()*f,c=a*d,g=0;g>>> Ineffective Write to PIA SWBCNT: "+c)):0===f?void e(">>>> Unsupported Write to PIA SWCHA: "+c):1===f?void e(">>>> Unsupported Write to PIA SWACNT "+c):0};var a=function(){--o<0?(p|=192,o=255,h=i=1):h=i},b=function(b,c){o=b,p&=63,h=i=j=c,a()},c=function(){p&=191,1===i&&(h=i=j)},d=function(a){m=203&m|34&a},e=function(a){self.debug&&jt.Util.log(a)},f=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case f.JOY0_UP:return void(b?k&=239:k|=16);case f.JOY0_DOWN:return void(b?k&=223:k|=32);case f.PADDLE1_BUTTON:case f.JOY0_LEFT:return void(b?k&=191:k|=64);case f.PADDLE0_BUTTON:case f.JOY0_RIGHT:return void(b?k&=127:k|=128);case f.JOY1_UP:return void(b?k&=254:k|=1);case f.JOY1_DOWN:return void(b?k&=253:k|=2);case f.JOY1_LEFT:return void(b?k&=251:k|=4);case f.JOY1_RIGHT:return void(b?k&=247:k|=8);case f.RESET:return void(b?m&=254:m|=1);case f.SELECT:return void(b?m&=253:m|=2)}if(b)switch(a){case f.BLACK_WHITE:return 0==(8&m)?m|=8:m&=247,void g.getTia().getVideoOutput().showOSD(0!=(8&m)?"COLOR":"B/W",!0);case f.DIFFICULTY0:return 0==(64&m)?m|=64:m&=191,void g.getTia().getVideoOutput().showOSD(0!=(64&m)?"P1 Expert":"P1 Novice",!0);case f.DIFFICULTY1:return 0==(128&m)?m|=128:m&=127,void g.getTia().getVideoOutput().showOSD(0!=(128&m)?"P2 Expert":"P2 Novice",!0)}},this.controlsStateReport=function(a){a[f.BLACK_WHITE]=0===(8&m),a[f.DIFFICULTY0]=0!==(64&m),a[f.DIFFICULTY1]=0!==(128&m),a[f.SELECT]=0===(2&m),a[f.RESET]=0===(1&m)},this.saveState=function(){return{t:h,c:i,l:j,SA:k,SAC:l,SB:m,SBC:n,IT:o,IS:p,T1:q,T8:r,T6:s,T2:t}},this.loadState=function(a){h=a.t,i=a.c,j=a.l,l=a.SAC,m=a.SB,n=a.SBC,o=a.IT,p=a.IS,q=a.T1,r=a.T8,s=a.T6,t=a.T2},this.debug=!1;var g,h=1024,i=1024,j=1024,k=255,l=0,m=11,n=0,o=256*Math.random()|0,p=0,q=0,r=0,s=0,t=0,u=7},function(){"use strict";for(var a=[0,4210752,7105644,9474192,11579568,13158600,14474460,16053492,17476,1074276,2393220,3448992,4241592,5296336,6088936,6880508,10352,1328260,2645144,3963052,5016764,6070476,6862044,7915756,6276,1586328,3166380,4745408,6062288,7378144,8431852,9747708,136,2105500,3947696,5789888,7368912,8947936,10526956,11842812,6029432,7610508,8928416,10246320,11563200,12616912,13671644,14725356,7864392,9445472,10763384,12081292,13398176,14451892,15506628,16560340,8650772,9969712,11287628,12605544,13660284,14715028,15507624,16561340,8912896,10231836,11550776,12606544,13661288,14716028,15508624,16562340,8132608,9451548,11031608,12349520,13404264,14457980,15512720,16566436,6040576,7883804,9463864,11306064,12622952,13939836,15256720,16572580,2898944,4742172,6585400,8428624,9745512,11325564,12641424,13958308,15360,2120736,4226112,6069340,7648372,9228428,10806436,12123320,14356,1858612,3701840,5281900,6861956,8178844,9495732,10812616,12332,1855564,3436648,5016708,6596764,7913652,8967372,10284256,10308,1591396,3172484,4490400,5807288,7124176,8178920,9232636],b=[0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,22656,2125972,3966120,5807292,7384268,8700124,10277100,11591932,23620,2127964,3969140,5811340,7389344,8705200,10283204,11599060,13424,2117768,3958944,5801140,7379144,8695004,10273004,11588860,1336320,3440672,5281852,7123032,8701040,10279044,11856028,13171888,1310832,3416200,5258400,7100596,8679624,10257628,11836652,13152508,6052864,7631904,9210940,10789976,12105840,13158532,14474396,15527088,6029424,7610500,8928404,10246312,11563188,12616900,13671632,14725344,7355392,8935452,10515512,11832400,13149288,14465148,15518864,16572580,7340120,8921196,10501248,11819156,13136036,14451892,15506628,16560340,7348224,8928284,10508344,11826256,13142120,14459004,15512720,16566436,8388668,9707604,11025516,12343424,13398164,14451880,15506616,16560328,8912896,10231840,11549756,12605528,13660272,14713988,15506588,16560304,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113],c=new Uint32Array(256),d=new Uint32Array(256),e=0,f=a.length;e>4^a);return x>>>=1,0===b?x&=255:x|=256,a},f=function(){return 1===r?1:u=u?0:1},g=function(){return v},h=function(){return 0===--w&&(w=3,v=v?0:1),v},i=function(){return D[C]},j=function(){return 31===++C&&(C=0),D[C]},k=function(){return i()!==j()?c():b()},l=function(){return d()?c():b()},m=function(){return i()!=j()?h():g()},n=function(){return d()?h():g()},o=a,p=0,q=0,r=1,s=1,t=0,u=1,v=1,w=3,x=511,y=14,z=[1,1,1,1,0,0,0,1,0,0,1,1,0,1,0],A=30,B=[1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0],C=30,D=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0],E=15},jt.Tia=function(pCpu,pPia,audioSocket){"use strict";function init(){generateObjectsLineSprites(),generateObjectsCopiesOffsets()}function renderLineTo(a){var b,c=a>LINE_WIDTH?LINE_WIDTH:a;if(vBlankOn)for(var d=renderClock;d>(f>>2):playfieldPatternR>>(f-80>>2))?h=playfieldColor:i&=PFC),ballEnabled&&(b=f-ballPixel,b<0&&(b+=160),missileBallLineSprites[ballLineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=ballColor):i&=BLC)),player0Enabled&&(b=f-player0Pixel,b<0&&(b+=160),playerLineSprites[player0LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=player0Color):i&=P0C),missile0Enabled&&(b=f-missile0Pixel,b<0&&(b+=160),missileBallLineSprites[missile0LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=missile0Color):i&=M0C),player1Enabled&&(b=f-player1Pixel,b<0&&(b+=160),playerLineSprites[player1LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=player1Color):i&=P1C),missile1Enabled&&(b=f-missile1Pixel,b<0&&(b+=160),missileBallLineSprites[missile1LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=missile1Color):i&=M1C),playfieldPriority||(playfieldEnabled&&(f<80?playfieldPatternL>>(f>>2)&1?h||(h=playfieldLeftColor):i&=PFC:playfieldPatternR>>(f-80>>2)&1?h||(h=playfieldRightColor):i&=PFC),ballEnabled&&(b=f-ballPixel,b<0&&(b+=160),missileBallLineSprites[ballLineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=ballColor):i&=BLC)),linePixels[f+HBLANK_DURATION]=h||playfieldBackground,e|=i}debugNoCollisions||(collisions=e)}}function changeAt(a){vBlankOn||(a>renderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(a),renderClock=a),changeClock=renderClock)}function changeAtClock(){changeAt(clock)}function changeAtClockPlus(a){changeAt(clock+a)}function changePlayfieldAtClock(){if(debug&&debugPixel(DEBUG_PF_GR_COLOR),clockrenderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(a),renderClock=a),changeClock=renderClock}function updateToClock(){vBlankOn||clock>renderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(clock),renderClock=clock)}function augmentCollisionsPossible(){collisionsPossible=65534,player0Enabled||(collisionsPossible&=P0C),player1Enabled||(collisionsPossible&=P1C),missile0Enabled||(collisionsPossible&=M0C),missile1Enabled||(collisionsPossible&=M1C),playfieldEnabled||(collisionsPossible&=PFC),ballEnabled||(collisionsPossible&=BLC)}function playfieldUpdateSprite(){playfieldPatternL=PF2<<12|jt.Util.reverseInt8(PF1)<<4|(240&PF0)>>4,playfieldUpdateSpriteR()}function playfieldUpdateSpriteR(){playfieldPatternR=playfieldReflected?jt.Util.reverseInt8(PF0)<<16|PF1<<8|jt.Util.reverseInt8(PF2):playfieldPatternL,0!==playfieldPatternL||0!==playfieldPatternR?(playfieldEnabled=!0,augmentCollisionsPossible()):(playfieldEnabled=!1,collisionsPossible&=PFC)}function ballSetEnabled(a){a?(ballEnabled=!0,augmentCollisionsPossible()):(ballEnabled=!1,collisionsPossible&=BLC)}function player0SetShape(a){if(NUSIZ0!==a){var b=NUSIZ0^a,c=NUSIZ0;NUSIZ0=a;var d=7&a,e=clock=160&&(f-=160);var g=playerScanOffsetsShape[160*(7&c)+f],h=playerScanOffsetsShape[160*d+f];if(h!==g)if(player0Enabled&&changeAtClockPlus(2),player0Alt=player0Pixel>=80?1:2,player0LineSpritePointer+=20,player0AltFrom=f,player0AltLength=playerCopyLengthPerShape[d],192&g)player0AltCopyOffset=191&g;else if(clock=160&&(f-=160),g=missileScanOffsetsShape[160*((48&c)>>1|7&c)+f],h=missileScanOffsetsShape[160*((48&a)>>1|d)+f],h!==g)){missile0Enabled&&changeAtClockPlus(2),missile0Alt=missile0Pixel>=80?1:2,missile0LineSpritePointer+=20,missile0AltFrom=f;var j=(48&a)>>4;missile0AltLength=4+(1<=160&&(f-=160);var g=playerScanOffsetsShape[160*(7&c)+f],h=playerScanOffsetsShape[160*d+f];h!==g&&(player1Enabled&&changeAtClockPlus(2),player1Alt=player1Pixel>=80?1:2,player1LineSpritePointer+=40,player1AltFrom=f,player1AltLength=playerCopyLengthPerShape[d],192&g?player1AltCopyOffset=191&g:clock=160&&(f-=160),g=missileScanOffsetsShape[160*((48&c)>>1|7&c)+f],h=missileScanOffsetsShape[160*((48&a)>>1|d)+f],h!==g)){missile1Enabled&&changeAtClockPlus(2),missile1Alt=missile1Pixel>=80?1:2,missile1LineSpritePointer+=40,missile1AltFrom=f;var i=(48&a)>>4; missile1AltLength=4+(1<>1|7&NUSIZ0)<<6)+(missile0Alt?20:0);missile0LineSpritePointer!==b&&(missile0Enabled?(changeAtClockPlus(a),missile0LineSpritePointer=b,missile0Alt&&missile0DefineAlt()):missile0LineSpritePointer=b)}function missile0SetEnabled(a){a?(missile0Enabled=!0,augmentCollisionsPossible(),missile0Alt&&missile0DefineAlt()):(missile0Enabled=!1,collisionsPossible&=M0C)}function missile0SetResetToPlayer(a){RESMP0!==(2&a)&&(ENAM0?(changeAtClock(),missile0SetEnabled(!(RESMP0=2&a))):RESMP0=2&a,RESMP0||(missile0Pixel=player0Pixel+missileCenterOffsetsPerPlayerSize[7&NUSIZ0],missile0Pixel>=160&&(missile0Pixel-=160)))}function missile1UpdateSprite(a){var b=(((48&NUSIZ1)>>1|7&NUSIZ1)<<6)+(missile1Alt?40:0);missile1LineSpritePointer!==b&&(missile1Enabled?(changeAtClockPlus(a),missile1LineSpritePointer=b,missile1Alt&&missile1DefineAlt()):missile1LineSpritePointer=b)}function missile1SetEnabled(a){a?(missile1Enabled=!0,augmentCollisionsPossible(),missile1Alt&&missile1DefineAlt()):(missile1Enabled=!1,collisionsPossible&=M1C)}function missile1SetResetToPlayer(a){RESMP1!==(2&a)&&(ENAM1?(changeAtClock(),missile1SetEnabled(!(RESMP1=2&a))):RESMP1=2&a,RESMP1||(missile1Pixel=player1Pixel+missileCenterOffsetsPerPlayerSize[7&NUSIZ1],missile1Pixel>=160&&(missile1Pixel-=160)))}function player0DefineAlt(){var a=player0AltFrom<<16|player0AltLength<<8|player0AltCopyOffset,b=player0LineSpritePointer-20>>6;if(player0AltControl[b]!==a){for(var c=player0LineSpritePointer-20,d=0;d<20;++d)playerLineSprites[player0LineSpritePointer+d]=playerLineSprites[c+d];var e=player0AltFrom;if(128&player0AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ0];for(var g=player0AltCopyOffset,h=player0AltCopyOffset+player0AltLength;g>3)]>>(7&g)&1?playerLineSprites[player0LineSpritePointer+(e>>3)]|=1<<(7&e):playerLineSprites[player0LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}player0AltControl[b]=a}}function player1DefineAlt(){var a=player1AltFrom<<16|player1AltLength<<8|player1AltCopyOffset,b=player1LineSpritePointer-40>>6;if(player1AltControl[b]!==a){for(var c=player1LineSpritePointer-40,d=0;d<20;++d)playerLineSprites[player1LineSpritePointer+d]=playerLineSprites[c+d];var e=player1AltFrom;if(128&player1AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ1];for(var g=player1AltCopyOffset,h=player1AltCopyOffset+player1AltLength;g>3)]>>(7&g)&1?playerLineSprites[player1LineSpritePointer+(e>>3)]|=1<<(7&e):playerLineSprites[player1LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}player1AltControl[b]=a}}function missile0DefineAlt(){var a=missile0AltFrom<<16|missile0AltLength<<8|missile0AltCopyOffset,b=missile0LineSpritePointer-20>>6;if(missile0AltControl[b]!==a){for(var c=missile0LineSpritePointer-20,d=0;d<20;++d)missileBallLineSprites[missile0LineSpritePointer+d]=missileBallLineSprites[c+d];var e=missile0AltFrom;if(128&missile0AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ0];for(var g=missile0AltCopyOffset,h=missile0AltCopyOffset+missile0AltLength;g>3)]>>(7&g)&1?missileBallLineSprites[missile0LineSpritePointer+(e>>3)]|=1<<(7&e):missileBallLineSprites[missile0LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}missile0AltControl[b]=a}}function missile1DefineAlt(){var a=missile1AltFrom<<16|missile1AltLength<<8|missile1AltCopyOffset,b=missile1LineSpritePointer-40>>6;if(missile1AltControl[b]!==a){for(var c=missile1LineSpritePointer-40,d=0;d<20;++d)missileBallLineSprites[missile1LineSpritePointer+d]=missileBallLineSprites[c+d];var e=missile1AltFrom;if(128&missile1AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ1];for(var g=missile1AltCopyOffset,h=missile1AltCopyOffset+missile1AltLength;g>3)]>>(7&g)&1?missileBallLineSprites[missile1LineSpritePointer+(e>>3)]|=1<<(7&e):missileBallLineSprites[missile1LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}missile1AltControl[b]=a}}function getRESxPixel(){if(clock>=HBLANK_DURATION+(hMoveHitBlank?7:0))return clock-HBLANK_DURATION;if(hMoveHitBlank){if(clock>=HBLANK_DURATION)return-6;var a=clock-hMoveHitClock-4>>2;return a>8?-6:a>1?-(a-2):-(158+a)}return-158}function checkLateHMOVE(){hMoveLateHit?(hMoveLateHit=!1,hMoveHitBlank=hMoveLateHitBlank,performHMOVE()):hMoveHitBlank=!1}function updateExtendedHBLANK(){hMoveHitBlank!==(linePixels[HBLANK_DURATION]===hBlankColor)&&(hMoveHitBlank?linePixels[HBLANK_DURATION]=linePixels[HBLANK_DURATION+1]=linePixels[HBLANK_DURATION+2]=linePixels[HBLANK_DURATION+3]=linePixels[HBLANK_DURATION+4]=linePixels[HBLANK_DURATION+5]=linePixels[HBLANK_DURATION+6]=linePixels[HBLANK_DURATION+7]=hBlankColor:changeClock=HBLANK_DURATION),hMoveHitBlank&&(renderClock=HBLANK_DURATION+8)}function endObjectsAltStatusMidLine(){1===player0Alt&&(player0Enabled&&changeAtClock(),player0Alt=0,player0LineSpritePointer-=20),1===player1Alt&&(player1Enabled&&changeAtClock(),player1Alt=0,player1LineSpritePointer-=40),1===missile0Alt&&(missile0Enabled&&changeAtClock(),missile0Alt=0,missile0LineSpritePointer-=20),1===missile1Alt&&(missile1Enabled&&changeAtClock(),missile1Alt=0,missile1LineSpritePointer-=40)}function endObjectsAltStatusEndOfLine(){2===player0Alt&&(player0Alt=0,player0LineSpritePointer-=20),2===player1Alt&&(player1Alt=0,player1LineSpritePointer-=40),2===missile0Alt&&(missile0Alt=0,missile0LineSpritePointer-=20),2===missile1Alt&&(missile1Alt=0,missile1LineSpritePointer-=40)}function vSyncSet(a){debug?(debugPixel(VSYNC_COLOR),changeAtClock(),vSyncOn=0!==(2&a),vBlankColor=vSyncOn?VSYNC_COLOR:DEBUG_VBLANK_COLOR):vSyncOn=0!==(2&a)}function generateObjectsLineSprites(){function a(a,b,c){for(var d=0;d<8;++d)a[c+d]=b>>d&1}function b(a,b,c){for(var d=0;d<8;++d)a[c+2*d]=a[c+2*d+1]=b>>d&1}function c(a,b,c){for(var d=0;d<8;++d)a[c+4*d]=a[c+4*d+1]=a[c+4*d+2]=a[c+4*d+3]=b>>d&1}function d(a,b,c,d,e){for(var f=((a<<11|b<<3|c)<<6)+20*d,g=0;g<20;++g)for(var h=0;h<8;++h)e[8*g+h]&&(playerLineSprites[f+g]|=1<>1,playerScanOffsetsShape[800+b]=c;for(b=0;b<38;b++)c=b-a[b],playerCopyOffsetsReset[1120+b]=c,c=b<6?64|b:b-6>>2,playerScanOffsetsShape[1120+b]=c;jt.Util.arrayFill(missileCopyOffsetsReset,128),jt.Util.arrayFill(missileScanOffsetsShape,128);for(var d=0;d<=3;++d){var e=4+(1<>d,missileScanOffsetsShape[8*d*160+0+b]=c,missileScanOffsetsShape[8*d*160+160+b]=c,missileScanOffsetsShape[8*d+160+b+16]=c,missileScanOffsetsShape[8*d*160+320+b]=c,missileScanOffsetsShape[8*d+320+b+32]=c,missileScanOffsetsShape[8*d*160+480+b]=c,missileScanOffsetsShape[8*d+480+b+16]=c,missileScanOffsetsShape[8*d*160+480+b+32]=c,missileScanOffsetsShape[8*d*160+640+b]=c,missileScanOffsetsShape[8*d+640+b+64]=c,missileScanOffsetsShape[8*d*160+800+b]=c,missileScanOffsetsShape[8*d*160+960+b]=c,missileScanOffsetsShape[8*d+960+b+32]=c,missileScanOffsetsShape[8*d*160+960+b+64]=c,missileScanOffsetsShape[8*d*160+1120+b]=c}}var self=this;this.powerOn=function(){jt.Util.arrayFill(linePixels,VBLANK_COLOR),jt.Util.arrayFill(debugPixels,0),audioSignal.getChannel0().setVolume(0),audioSignal.getChannel1().setVolume(0),initLatchesAtPowerOn(),hMoveLateHit=!1,changeClock=changeClockPrevLine=-1,audioSignal.powerOn(),powerOn=!0},this.powerOff=function(){powerOn=!1,videoSignal.signalOff(),audioSignal.powerOff()},this.frame=function(){do{clock=0,changeClock=-1,renderClock=HBLANK_DURATION,debug&&(debugLevel>=4?jt.Util.arrayFill(linePixels,4278190080):debugLevel>=2&&debugLevel<4&&(changeClock=0)),checkLateHMOVE(),bus.clockPulse(),cpu.setRDY(!0);for(var a=0;a<22;++a)clock+=3,bus.clockPulse();updateExtendedHBLANK();for(var b=0;b<27;++b)clock+=3,bus.clockPulse();audioSignal.audioClockPulse(),endObjectsAltStatusMidLine();for(var c=0;c<26;++c)clock+=3,bus.clockPulse();audioSignal.audioClockPulse(),finishLine()}while(!videoSignal.nextLine(linePixels,vSyncOn));videoSignal.finishFrame()},this.connectBus=function(a){bus=a},this.getVideoOutput=function(){return videoSignal},this.getAudioOutput=function(){return audioSignal},this.setVideoStandard=function(a){videoSignal.setVideoStandard(a),palette=jt.TiaPalettes[a.name]},this.debug=function(a){debugLevel=a>4?0:a,debug=0!==debugLevel,videoSignal.showOSD(debug?"Debug Level "+debugLevel:"Debug OFF",!0),pia.debug=debug,debug?debugSetColors():debugRestoreColors()},this.getDebugNoCollisions=function(){return debugNoCollisions},this.read=function(a){switch(a&READ_ADDRESS_MASK){case 0:return updateToClock(),(1024&collisions)>>3|(16384&collisions)>>8;case 1:return updateToClock(),(8192&collisions)>>6|(512&collisions)>>3;case 2:return updateToClock(),(4096&collisions)>>5|(2048&collisions)>>5;case 3:return updateToClock(),(256&collisions)>>1|(128&collisions)>>1;case 4:return updateToClock(),(32&collisions)<<2|(16&collisions)<<2;case 5:return updateToClock(),(8&collisions)<<4|(4&collisions)<<4;case 6:return updateToClock(),(2&collisions)<<6;case 7:return updateToClock(),(32768&collisions)>>8|64&collisions;case 8:return INPT0;case 9:return INPT1;case 10:return INPT2;case 11:return INPT3;case 12:return INPT4;case 13:return INPT5;default:return 0}},this.write=function(a,b){switch(a&WRITE_ADDRESS_MASK){case 0:return void vSyncSet(b);case 1:return void vBlankSet(b);case 2:return cpu.setRDY(!1),void(debug&&debugPixel(DEBUG_WSYNC_COLOR));case 9:return void(COLUBK===b||debug||(changeAtClock(),COLUBK=b,playfieldBackground=palette[b]));case 13:return void(PF0!==(240&b)&&(changePlayfieldAtClock(),PF0=240&b,playfieldUpdateSprite()));case 14:return void(PF1!==b&&(changePlayfieldAtClock(),PF1=b,playfieldUpdateSprite()));case 15:return void(PF2!==b&&(changePlayfieldAtClock(),PF2=b,playfieldUpdateSprite()));case 8:return void(COLUPF===b||debug||((playfieldEnabled&&!playfieldScoreMode||ballEnabled)&&changeAtClock(),COLUPF=b,ballColor=palette[b],playfieldScoreMode||(playfieldColor=playfieldLeftColor=playfieldRightColor=ballColor)));case 10:return void(CTRLPF!==b&&playfieldSetShape(b));case 20:return void hitRESBL();case 31:return void(ENABLd!==(2&b)&&(ENABLd=2&b,VDELBL||(changeAtClock(),ballSetEnabled(ENABLd))));case 39:return void(VDELBL!==(1&b)&&(VDELBL=1&b,ENABL!==ENABLd&&(changeAtClock(),ballSetEnabled(VDELBL?ENABL:ENABLd))));case 4:return void player0SetShape(b);case 6:return void(COLUP0===b||debug||(COLUP0=b,(player0Enabled||missile0Enabled||playfieldEnabled&&playfieldScoreMode)&&changeAtClock(),player0Color=missile0Color=palette[b],playfieldScoreMode&&(playfieldLeftColor=player0Color)));case 11:return void(REFP0!==(b>>3&1)&&(REFP0=b>>3&1,player0UpdateSprite(0)));case 16:return void hitRESP0();case 27:return void player0SetSprite(b);case 37:return void(VDELP0!==(1&b)&&(VDELP0=1&b,GRP0!==GRP0d&&player0UpdateSprite(0)));case 5:return void player1SetShape(b);case 7:return void(COLUP1===b||debug||(COLUP1=b,(player1Enabled||missile1Enabled||playfieldEnabled&&playfieldScoreMode)&&changeAtClock(),player1Color=missile1Color=palette[b],playfieldScoreMode&&(playfieldRightColor=player1Color)));case 12:return void(REFP1!==(b>>3&1)&&(REFP1=b>>3&1,player1UpdateSprite(0)));case 17:return void hitRESP1();case 28:return void player1SetSprite(b);case 38:return void(VDELP1!==(1&b)&&(VDELP1=1&b,GRP1!==GRP1d&&player1UpdateSprite(0)));case 18:return void hitRESM0();case 29:return void(ENAM0!==(2&b)&&(ENAM0=2&b,RESMP0||(changeAtClock(),missile0SetEnabled(ENAM0))));case 40:return void missile0SetResetToPlayer(b);case 19:return void hitRESM1();case 30:return void(ENAM1!==(2&b)&&(ENAM1=2&b,RESMP1||(changeAtClock(),missile1SetEnabled(ENAM1))));case 41:return void missile1SetResetToPlayer(b);case 32:return void(HMP0=(b>127?-16:0)+(b>>4));case 33:return void(HMP1=(b>127?-16:0)+(b>>4));case 34:return void(HMM0=(b>127?-16:0)+(b>>4));case 35:return void(HMM1=(b>127?-16:0)+(b>>4));case 36:return void(HMBL=(b>127?-16:0)+(b>>4));case 42:return void hitHMOVE();case 43:return void(HMP0=HMP1=HMM0=HMM1=HMBL=0);case 44:return changeAtClock(),void(collisions=0);case 21:return void(AUDC0!==b&&(AUDC0=b, audioSignal.getChannel0().setControl(15&b)));case 22:return void(AUDC1!==b&&(AUDC1=b,audioSignal.getChannel1().setControl(15&b)));case 23:return void(AUDF0!==b&&(AUDF0=b,audioSignal.getChannel0().setDivider((31&b)+1)));case 24:return void(AUDF1!==b&&(AUDF1=b,audioSignal.getChannel1().setDivider((31&b)+1)));case 25:return void(AUDV0!==b&&(AUDV0=b,audioSignal.getChannel0().setVolume(15&b)));case 26:return void(AUDV1!==b&&(AUDV1=b,audioSignal.getChannel1().setVolume(15&b)))}};var finishLine=function(){changeClock>=0?(renderLineTo(LINE_WIDTH),changeClockPrevLine=changeClock):changeClockPrevLine>=0&&(renderLineTo(changeClockPrevLine),changeClockPrevLine=-1),endObjectsAltStatusEndOfLine(),paddle0Position>=0&&!paddleCapacitorsGrounded&&(INPT0<128&&++paddle0CapacitorCharge>=paddle0Position&&(INPT0|=128),INPT1<128&&++paddle1CapacitorCharge>=paddle1Position&&(INPT1|=128)),debugLevel>=1&&processDebugPixelsInLine()},playfieldSetShape=function(a){if(CTRLPF!==a){var b=7&a;b!==(7&CTRLPF)&&(playfieldEnabled&&changeAtClock(),b=0!==(1&a),playfieldReflected!==b&&(playfieldReflected=b,playfieldUpdateSpriteR()),b=0!==(2&a),playfieldScoreMode!==b&&(playfieldScoreMode=b,debug||(b?(playfieldLeftColor=player0Color,playfieldRightColor=player1Color):playfieldColor=playfieldLeftColor=playfieldRightColor=ballColor)),playfieldPriority=0!==(4&a)),b=48&a,b!==(48&CTRLPF)&&(ballEnabled&&changeAtClock(),ballLineSpritePointer=b>>1<<6),CTRLPF=a}},hitRESP0=function(){debug&&debugPixel(DEBUG_P0_RES_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(player0Pixel!==b){player0Enabled&&changeAtClock();var c=a>=0?b:0,d=c-player0Pixel;d<0&&(d+=160),player0Pixel=b;var e=7&NUSIZ0;if(player0Alt){if(d<=playerCopyLengthPerShape[e])return}else player0LineSpritePointer+=20;var f=c-b;f<-100&&(f+=160),player0Alt=b>=80?1:2,player0AltFrom=f>=0?f:160+f,player0AltLength=playerCopyLengthPerShape[e]-f,player0AltCopyOffset=playerCopyOffsetsReset[160*e+d],player0Enabled&&player0DefineAlt()}},hitRESP1=function(){debug&&debugPixel(DEBUG_P1_RES_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(player1Pixel!==b){player1Enabled&&changeAtClock();var c=a>=0?b:0,d=c-player1Pixel;d<0&&(d+=160),player1Pixel=b;var e=7&NUSIZ1;if(player1Alt){if(d<=playerCopyLengthPerShape[e])return}else player1LineSpritePointer+=40;var f=c-b;f<-100&&(f+=160),player1Alt=b>=80?1:2,player1AltFrom=f>=0?f:160+f,player1AltLength=playerCopyLengthPerShape[e]-f,player1AltCopyOffset=playerCopyOffsetsReset[160*e+d],player1Enabled&&player1DefineAlt()}},hitRESM0=function(){debug&&debugPixel(DEBUG_M0_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(missile0Pixel!==b){missile0Enabled&&changeAtClock();var c=a>=0?b:0,d=c-missile0Pixel;if(d<0&&(d+=160),missile0Pixel=b,missile0Alt){if(d<=4+(1<<((48&NUSIZ0)>>4)))return}else missile0LineSpritePointer+=20;var e=c-b;e<-100&&(e+=160),missile0Alt=b>=80?1:2,missile0AltFrom=e>=0?e:160+e,missile0AltLength=4+(1<<((48&NUSIZ0)>>4))-e,missile0AltCopyOffset=missileCopyOffsetsReset[160*((48&NUSIZ0)>>1|7&NUSIZ0)+d],missile0Enabled&&missile0DefineAlt()}},hitRESM1=function(){debug&&debugPixel(DEBUG_M1_COLOR);var a=getRESxPixel(),b=a>=1?a:-a;if(missile1Pixel!==b){missile1Enabled&&changeAtClock();var c=a>=0?b:0,d=c-missile1Pixel;if(d<0&&(d+=160),missile1Pixel=b,missile1Alt){if(d<=4+(1<<((48&NUSIZ1)>>4)))return}else missile1LineSpritePointer+=40;var e=c-b;e<-100&&(e+=160),missile1Alt=b>=80?1:2,missile1AltFrom=e>=0?e:160+e,missile1AltLength=4+(1<<((48&NUSIZ1)>>4))-e,missile1AltCopyOffset=missileCopyOffsetsReset[160*((48&NUSIZ1)>>1|7&NUSIZ1)+d],missile1Enabled&&missile1DefineAlt()}},hitRESBL=function(){debug&&debugPixel(DEBUG_BL_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;ballPixel!==b&&(ballEnabled&&changeAtClock(),ballPixel=b)},hitHMOVE=function(){return debug&&debugPixel(DEBUG_HMOVE_COLOR),clock=225))},performHMOVE=function(){var a,b=!1;a=hMoveHitBlank?HMP0:HMP0+8,0!==a&&(player0Pixel-=a,player0Pixel>=160?player0Pixel-=160:player0Pixel<0&&(player0Pixel+=160),player0Enabled&&(b=!0)),a=hMoveHitBlank?HMP1:HMP1+8,0!==a&&(player1Pixel-=a,player1Pixel>=160?player1Pixel-=160:player1Pixel<0&&(player1Pixel+=160),player1Enabled&&(b=!0)),a=hMoveHitBlank?HMM0:HMM0+8,0!==a&&(missile0Pixel-=a,missile0Pixel>=160?missile0Pixel-=160:missile0Pixel<0&&(missile0Pixel+=160),missile0Enabled&&(b=!0)),a=hMoveHitBlank?HMM1:HMM1+8,0!==a&&(missile1Pixel-=a,missile1Pixel>=160?missile1Pixel-=160:missile1Pixel<0&&(missile1Pixel+=160),missile1Enabled&&(b=!0)),a=hMoveHitBlank?HMBL:HMBL+8,0!==a&&(ballPixel-=a,ballPixel>=160?ballPixel-=160:ballPixel<0&&(ballPixel+=160),ballEnabled&&(b=!0)),b&&(changeClock=hMoveHitBlank?HBLANK_DURATION+8:HBLANK_DURATION)},vBlankSet=function(a){var b=0!==(2&a);vBlankOn!==b&&(changeVBlankAtClockPlus1(),vBlankOn=b),0!==(64&a)?controlsButtonsLatched=!0:(controlsButtonsLatched=!1,controlsJOY0ButtonPressed?INPT4&=127:INPT4|=128,controlsJOY1ButtonPressed?INPT5&=127:INPT5|=128),0!=(128&a)?(paddleCapacitorsGrounded=!0,paddle0CapacitorCharge=paddle1CapacitorCharge=0,INPT0&=127,INPT1&=127,INPT2&=127,INPT3&=127):paddleCapacitorsGrounded=!1},initLatchesAtPowerOn=function(){collisions=0,INPT0=INPT1=INPT2=INPT3=0,INPT4=INPT5=128},debugPixel=function(a){debugPixels[clock]=a},processDebugPixelsInLine=function(){if(jt.Util.arrayFillSegment(linePixels,0,HBLANK_DURATION+(hMoveHitBlank?8:0),hBlankColor),debugLevel>=3&&videoSignal.monitor.currentLine()%10==0)for(var a=0;a=2)for(a=0;a=1?DEBUG_HBLANK_COLOR:HBLANK_COLOR,vBlankColor=debugLevel>=1?DEBUG_VBLANK_COLOR:VBLANK_COLOR},debugRestoreColors=function(){hBlankColor=HBLANK_COLOR,vBlankColor=VBLANK_COLOR,playfieldBackground=palette[0],jt.Util.arrayFill(linePixels,hBlankColor),changeAtClock()},info=function(a){console.error("Line: "+videoSignal.monitor.currentLine()+", Pixel: "+clock+". "+a)},debugInfo=function(a){debug&&console.error("Line: "+videoSignal.monitor.currentLine()+", Pixel: "+clock+". "+a)},controls=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case controls.JOY0_BUTTON:return void(b?(controlsJOY0ButtonPressed=!0,INPT4&=127):(controlsJOY0ButtonPressed=!1,controlsButtonsLatched||(INPT4|=128)));case controls.JOY1_BUTTON:return void(b?(controlsJOY1ButtonPressed=!0,INPT5&=127):(controlsJOY1ButtonPressed=!1,controlsButtonsLatched||(INPT5|=128)))}if(b)switch(a){case controls.DEBUG:return void self.debug(debugLevel+1);case controls.SHOW_INFO:return void videoSignal.toggleShowInfo();case controls.NO_COLLISIONS:debugNoCollisions=!debugNoCollisions,videoSignal.showOSD(debugNoCollisions?"No Collisions: ON":"No Collisions: OFF",!0)}},this.controlValueChanged=function(a,b){switch(a){case controls.PADDLE0_POSITION:return void(paddle0Position=b);case controls.PADDLE1_POSITION:return void(paddle1Position=b)}},this.saveState=function(){return{ccp:changeClockPrevLine,lpx:jt.Util.storeInt32BitArrayToStringBase64(linePixels),vs:vSyncOn,vb:vBlankOn,pfe:playfieldEnabled,pfl:playfieldPatternL,pfr:playfieldPatternR,pfc:playfieldColor,pflc:playfieldLeftColor,pfrc:playfieldRightColor,pfb:playfieldBackground,pfrl:playfieldReflected,pfsc:playfieldScoreMode,pfp:playfieldPriority,be:ballEnabled,bx:ballPixel,blp:ballLineSpritePointer,bc:ballColor,p0e:player0Enabled,p0x:player0Pixel,p0lp:player0LineSpritePointer,p0a:player0Alt, p0af:player0AltFrom,p0al:player0AltLength,p0ao:player0AltCopyOffset,p0c:player0Color,p1e:player1Enabled,p1x:player1Pixel,p1lp:player1LineSpritePointer,p1a:player1Alt,p1af:player1AltFrom,p1al:player1AltLength,p1ao:player1AltCopyOffset,p1c:player1Color,m0e:missile0Enabled,m0x:missile0Pixel,m0lp:missile0LineSpritePointer,m0a:missile0Alt,m0af:missile0AltFrom,m0al:missile0AltLength,m0ao:missile0AltCopyOffset,m0c:missile0Color,m1e:missile1Enabled,m1x:missile1Pixel,m1lp:missile1LineSpritePointer,m1a:missile1Alt,m1af:missile1AltFrom,m1al:missile1AltLength,m1ao:missile1AltCopyOffset,m1c:missile1Color,hmh:hMoveHitBlank,hmc:hMoveHitClock,hmlh:hMoveLateHit,hmlb:hMoveLateHitBlank,co:collisions,cop:collisionsPossible,CTRLPF:CTRLPF,COLUPF:COLUPF,COLUBK:COLUBK,PF0:PF0,PF1:PF1,PF2:PF2,ENABL:ENABL,ENABLd:ENABLd,VDELBL:VDELBL,NUSIZ0:NUSIZ0,COLUP0:COLUP0,REFP0:REFP0,GRP0:GRP0,GRP0d:GRP0d,VDELP0:VDELP0,NUSIZ1:NUSIZ1,COLUP1:COLUP1,REFP1:REFP1,GRP1:GRP1,GRP1d:GRP1d,VDELP1:VDELP1,ENAM0:ENAM0,RESMP0:RESMP0,ENAM1:ENAM1,RESMP1:RESMP1,HMP0:HMP0,HMP1:HMP1,HMM0:HMM0,HMM1:HMM1,HMBL:HMBL,AUDC0:AUDC0,AUDC1:AUDC1,AUDF0:AUDF0,AUDF1:AUDF1,AUDV0:AUDV0,AUDV1:AUDV1}},this.loadState=function(a){changeClockPrevLine=a.ccp,jt.Util.restoreStringBase64ToInt32BitArray(a.lpx,linePixels),vSyncOn=a.vs,vBlankOn=a.vb,playfieldEnabled=a.pfe,playfieldPatternL=0|a.pfl,playfieldPatternR=0|a.pfr,playfieldColor=0|a.pfc,playfieldLeftColor=0|a.pflc,playfieldRightColor=0|a.pfrc,playfieldBackground=0|a.pfb,playfieldReflected=a.pfrl,playfieldScoreMode=a.pfsc,playfieldPriority=a.pfp,ballEnabled=a.be,ballPixel=0|a.bx,ballLineSpritePointer=0|a.blp,ballColor=0|a.bc,player0Enabled=a.p0e,player0Pixel=0|a.p0x,player0LineSpritePointer=0|a.p0lp,player0Alt=0|a.p0a,player0AltFrom=0|a.p0af,player0AltLength=0|a.p0al,player0AltCopyOffset=0|a.p0ao,jt.Util.arrayFill(player0AltControl,0),player0Color=0|a.p0c,player1Enabled=a.p1e,player1Pixel=0|a.p1x,player1LineSpritePointer=0|a.p1lp,player1Alt=0|a.p1a,player1AltFrom=0|a.p1af,player1AltLength=0|a.p1al,player1AltCopyOffset=0|a.p1ao,jt.Util.arrayFill(player1AltControl,0),player1Color=0|a.p1c,missile0Enabled=a.m0e,missile0Pixel=0|a.m0x,missile0LineSpritePointer=0|a.m0lp,missile0Alt=0|a.m0a,missile0AltFrom=0|a.m0af,missile0AltLength=0|a.m0al,missile0AltCopyOffset=0|a.m0ao,jt.Util.arrayFill(missile0AltControl,0),missile0Color=0|a.m0c,missile1Enabled=a.m1e,missile1Pixel=0|a.m1x,missile1LineSpritePointer=0|a.m1lp,missile1Alt=0|a.m1a,missile1AltFrom=0|a.m1af,missile1AltLength=0|a.m1al,missile1AltCopyOffset=0|a.m1ao,jt.Util.arrayFill(missile1AltControl,0),missile1Color=0|a.m1c,hMoveHitBlank=a.hmh,hMoveHitClock=0|a.hmc,hMoveLateHit=a.hmlh,hMoveLateHitBlank=a.hmlb,collisions=0|a.co,collisionsPossible=0|a.cop,CTRLPF=0|a.CTRLPF,COLUPF=0|a.COLUPF,COLUBK=0|a.COLUBK,PF0=0|a.PF0,PF1=0|a.PF1,PF2=0|a.PF2,ENABL=0|a.ENABL,ENABLd=0|a.ENABLd,VDELBL=0|a.VDELBL,NUSIZ0=0|a.NUSIZ0,COLUP0=0|a.COLUP0,REFP0=0|a.REFP0,GRP0=0|a.GRP0,GRP0d=0|a.GRP0d,VDELP0=0|a.VDELP0,NUSIZ1=0|a.NUSIZ1,COLUP1=0|a.COLUP1,REFP1=0|a.REFP1,GRP1=0|a.GRP1,GRP1d=0|a.GRP1d,VDELP1=0|a.VDELP1,ENAM0=0|a.ENAM0,RESMP0=0|a.RESMP0,ENAM1=0|a.ENAM1,RESMP1=0|a.RESMP1,HMP0=0|a.HMP0,HMP1=0|a.HMP1,HMM0=0|a.HMM0,HMM1=0|a.HMM1,HMBL=0|a.HMBL,AUDC0=0|a.AUDC0,audioSignal.getChannel0().setControl(15&AUDC0),AUDC1=0|a.AUDC1,audioSignal.getChannel1().setControl(15&AUDC1),AUDF0=0|a.AUDF0,audioSignal.getChannel0().setDivider((31&AUDF0)+1),AUDF1=0|a.AUDF1,audioSignal.getChannel1().setDivider((31&AUDF1)+1),AUDV0=0|a.AUDV0,audioSignal.getChannel0().setVolume(15&AUDV0),AUDV1=0|a.AUDV1,audioSignal.getChannel1().setVolume(15&AUDV1),debug&&debugSetColors()};var HBLANK_DURATION=68,LINE_WIDTH=228,VBLANK_COLOR=4278190080,HBLANK_COLOR=4261412864,VSYNC_COLOR=4292730333,DEBUG_P0_COLOR=4278190335,DEBUG_P0_RES_COLOR=4280427195,DEBUG_P0_GR_COLOR=4279308663,DEBUG_P1_COLOR=4294901760,DEBUG_P1_RES_COLOR=4290454050,DEBUG_P1_GR_COLOR=4285993233,DEBUG_M0_COLOR=4284901119,DEBUG_M1_COLOR=4294927974,DEBUG_PF_COLOR=4282681412,DEBUG_PF_GR_COLOR=4281589043,DEBUG_BK_COLOR=4281549875,DEBUG_BL_COLOR=4278255615,DEBUG_MARKS_COLOR=4280295456,DEBUG_HBLANK_COLOR=4282664004,DEBUG_VBLANK_COLOR=4280953386,DEBUG_WSYNC_COLOR=4287103112,DEBUG_HMOVE_COLOR=4294967295,DEBUG_ALT_COLOR=4289374720,READ_ADDRESS_MASK=15,WRITE_ADDRESS_MASK=63,P0C=-63489,P1C=-34689,M0C=-17521,M1C=-8781,PFC=-4395,BLC=-2199,cpu=pCpu,pia=pPia,bus,powerOn=!1,clock,changeClock,changeClockPrevLine,renderClock,linePixels=new Uint32Array(LINE_WIDTH),vSyncOn=!1,vBlankOn=!1,vBlankColor=VBLANK_COLOR,hBlankColor=HBLANK_COLOR,playfieldEnabled=!1,playfieldPatternL=0,playfieldPatternR=0,playfieldColor=4278190080,playfieldLeftColor=4278190080,playfieldRightColor=4278190080,playfieldBackground=4278190080,playfieldReflected=!1,playfieldScoreMode=!1,playfieldPriority=!1,ballEnabled=!1,ballPixel=0,ballLineSpritePointer=0,ballColor=4278190080,player0Enabled=!1,player0Pixel=0,player0LineSpritePointer=0,player0Alt=0,player0AltFrom=0,player0AltLength=0,player0AltCopyOffset=0,player0AltControl=new Uint32Array(4096),player0Color=4278190080,player1Enabled=!1,player1Pixel=0,player1LineSpritePointer=0,player1Alt=0,player1AltFrom=0,player1AltLength=0,player1AltCopyOffset=0,player1AltControl=new Uint32Array(4096),player1Color=4278190080,missile0Enabled=!1,missile0Pixel=0,missile0LineSpritePointer=0,missile0Alt=0,missile0AltFrom=0,missile0AltLength=0,missile0AltCopyOffset=0,missile0AltControl=new Uint32Array(32),missile0Color=4278190080,missile1Enabled=!1,missile1Pixel=0,missile1LineSpritePointer=0,missile1Alt=0,missile1AltFrom=0,missile1AltLength=0,missile1AltCopyOffset=0,missile1AltControl=new Uint32Array(32),missile1Color=4278190080,hMoveHitBlank=!1,hMoveHitClock=0,hMoveLateHit=!1,hMoveLateHitBlank=!1,collisions=0,collisionsPossible=0,debug=!1,debugLevel=0,debugNoCollisions=!1,debugPixels=new Uint32Array(LINE_WIDTH),controlsButtonsLatched=!1,controlsJOY0ButtonPressed=!1,controlsJOY1ButtonPressed=!1,paddleCapacitorsGrounded=!1,paddle0Position=-1,paddle0CapacitorCharge=0,paddle1Position=-1,paddle1CapacitorCharge=0,playerLineSprites=new Uint8Array(262144),missileBallLineSprites=new Uint8Array(2048),playerCopyLengthPerShape=new Uint8Array([13,13,13,13,13,22,13,38]),playerScanStartPerShape=new Uint8Array([5,5,5,5,5,6,5,6]),playerPixelSizePerShape=new Uint8Array([1,1,1,1,1,2,1,4]),playerCopyOffsetsReset=new Uint8Array(1280),playerScanOffsetsShape=new Uint8Array(1280),missileCopyOffsetsReset=new Uint8Array(5120),missileScanOffsetsShape=new Uint8Array(5120),objectsLineSpritePointerDeltaToSingleCopy=new Uint16Array([0,64,128,192,256,0,384,0]),missileCenterOffsetsPerPlayerSize=new Uint8Array([5,5,5,5,5,10,5,18]),videoSignal=new jt.VideoSignal,palette,audioSignal=new jt.TiaAudio(audioSocket),INPT0=0,INPT1=0,INPT2=0,INPT3=0,INPT4=0,INPT5=0,CTRLPF=0,COLUPF=0,COLUBK=0,PF0=0,PF1=0,PF2=0,ENABL=0,ENABLd=0,VDELBL=0,NUSIZ0=0,COLUP0=0,REFP0=0,GRP0=0,GRP0d=0,VDELP0=0,NUSIZ1=0,COLUP1=0,REFP1=0,GRP1=0,GRP1d=0,VDELP1=0,ENAM0=0,RESMP0=0,ENAM1=0,RESMP1=0,HMP0=0,HMP1=0,HMM0=0,HMM1=0,HMBL=0,AUDC0=0,AUDC1=0,AUDF0=0,AUDF1=0,AUDV0=0,AUDV1=0;init(),self.eval=function(code){return eval(code)}},jt.Clock=function(clockPulse){"use strict";this.go=function(){running||(useRequestAnimationFrame=vSynch&&cyclesPerSecond===jt.Clock.HOST_NATIVE_FPS,running=!0,useRequestAnimationFrame?animationFrame=requestAnimationFrame(pulse):interval=setInterval(pulse,cycleTimeMs))},this.pause=function(){running=!1,animationFrame&&(cancelAnimationFrame(animationFrame),animationFrame=null),interval&&(clearInterval(interval),interval=null)},this.isRunning=function(){return running},this.getFrequency=function(){return cyclesPerSecond},this.setFrequency=function(a){running?(this.pause(),internalSetFrequency(a),this.go()):internalSetFrequency(a)},this.setVSynch=function(a){running?(this.pause(),vSynch=a,this.go()):vSynch=a};var internalSetFrequency=function(a){cyclesPerSecond=a,cycleTimeMs=1e3/a},pulse=function(){animationFrame=null, clockPulse(),useRequestAnimationFrame&&!animationFrame&&(animationFrame=requestAnimationFrame(pulse))};this.eval=function(str){return eval(str)};var running=!1,cyclesPerSecond=1,cycleTimeMs=1e3,useRequestAnimationFrame,animationFrame=null,interval=null,vSynch=!0},jt.Clock.HOST_NATIVE_FPS=Javatari.SCREEN_FORCE_HOST_NATIVE_FPS,jt.Clock.detectHostNativeFPSAndCallback=function(a){if(Javatari.SCREEN_VSYNCH_MODE===-1)return jt.Util.warning("Video native V-Synch disabled in configuration"),void(a&&a(jt.Clock.HOST_NATIVE_FPS));if(jt.Clock.HOST_NATIVE_FPS!==-1)return jt.Util.warning("Host video frequency forced in configuration: "+jt.Clock.HOST_NATIVE_FPS),void(a&&a(jt.Clock.HOST_NATIVE_FPS));var b=0,c=[],d=0,e=0,f=0,g=0,h=0,i=.06,j=function(){if(e>=10||f>=10||g>=10||h>=10)return jt.Clock.HOST_NATIVE_FPS=e>=10?60:f>=10?50:g>=10?120:100,jt.Util.log("Video native frequency detected: "+jt.Clock.HOST_NATIVE_FPS+"Hz"),void(a&&a(jt.Clock.HOST_NATIVE_FPS));if(b++,b<=50){var k=jt.Util.performanceNow(),l=k-d;c[c.length]=l,d=k,l>=1e3/60*(1-i)&&l<=1e3/60*(1+i)&&e++,l>=20*(1-i)&&l<=20*(1+i)&&f++,l>=1e3/120*(1-i)&&l<=1e3/120*(1+i)&&g++,l>=10*(1-i)&&l<=10*(1+i)&&h++,requestAnimationFrame(j)}else jt.Clock.HOST_NATIVE_FPS=-1,jt.Util.warning("Could not detect video native frequency. V-Synch DISABLED!"),a&&a(jt.Clock.HOST_NATIVE_FPS)};j()},jt.Bus=function(a,b,c,d){"use strict";function e(e){f=a,g=b,h=c,i=d,f.connectBus(e),g.connectBus(e),h.connectBus(e)}this.powerOn=function(){l=0,j||(g.getVideoOutput().showOSD("NO CARTRIDGE INSERTED!",!0),l=256*Math.random()|0),null!=j&&j.powerOn(),i.powerOn(),h.powerOn(),f.powerOn(),g.powerOn()},this.powerOff=function(){g.powerOff(),f.powerOff(),h.powerOff(),i.powerOff()},this.setCartridge=function(a){j=a,j&&(l=0,j.connectBus(this)),k=j&&j.needsBusMonitoring()},this.getCartridge=function(){return j},this.getTia=function(){return g},this.clockPulse=function(){h.clockPulse(),f.clockPulse()},this.read=function(a){return k&&j.monitorBusBeforeRead(a,l),(a&m)===n?j?l=j.read(a):l:l=(a&o)===p?i.read(a):(a&s)===t?h.read(a):63&l|g.read(a)},this.write=function(a,b){k&&j.monitorBusBeforeWrite(a,b),l=b,(a&q)===r?g.write(a,b):(a&o)===p?i.write(a,b):(a&s)===t?h.write(a,b):j&&j.write(a,b)};var f,g,h,i,j,k=!1,l=0,m=4096,n=4096,o=4736,p=128,q=4224,r=0,s=4736,t=640;e(this)},jt.AtariConsole=function(){"use strict";function init(){mainComponentsCreate(),socketsCreate(),self.setDefaults()}function videoFrame(){userPaused&&userPauseMoreFrames--<=0||(videoStandardAutoDetectionInProgress&&videoStandardAutoDetectionTry(),tia.frame())}function vSynchToggleMode(){return vSynchMode===-1?void self.showOSD("V-Synch is DISABLED / UNSUPPORTED",!0,!0):(vSynchMode=vSynchMode?0:1,updateVideoSynchronization(),self.showOSD("V-Synch: "+(vSynchMode?"ON":"OFF"),!0),Javatari.userPreferences.current.vSynch=vSynchMode,Javatari.userPreferences.setDirty(),void Javatari.userPreferences.save())}function updateVideoSynchronization(){videoPulldown=1===vSynchMode?videoStandard.pulldowns[jt.Clock.HOST_NATIVE_FPS]||videoStandard.pulldowns.TIMER:videoStandard.pulldowns.TIMER,videoPulldownStep=videoPulldown.steps,mainVideoClockUpdateSpeed()}function mainVideoClockUpdateSpeed(){var a=videoPulldown.frequency;mainVideoClock.setVSynch(vSynchMode>0),mainVideoClock.setFrequency(a*(alternateSpeed||speedControl)|0),audioSocket.setFps(a)}function CartridgeSocket(){this.insert=function(a,b){b&&self.powerIsOn&&self.powerOff(),setCartridge(a),b&&!self.powerIsOn&&self.powerOn()},this.inserted=function(){return getCartridge()},this.cartridgeInserted=function(a,b){tia.getAudioOutput().cartridgeInserted(a,b),consoleControlsSocket.cartridgeInserted(a,b),saveStateSocket.cartridgeInserted(a,b),tia.getVideoOutput().monitor.cartridgeInserted(a,b)},this.loadCartridgeData=function(a,b,c){},this.saveCartridgeDataFile=function(a){}}function ConsoleControlsSocket(){this.setDefaults=function(){self.setDefaults()},this.connectControls=function(b){a=b},this.cartridgeInserted=function(b,c){a&&a.cartridgeInserted(b,c)},this.controlStateChanged=function(a,b){self.controlStateChanged(a,b),pia.controlStateChanged(a,b),tia.controlStateChanged(a,b),tia.getVideoOutput().monitor.controlStateChanged(a,b)},this.controlValueChanged=function(a,b){tia.controlValueChanged(a,b)},this.controlsStateReport=function(a){self.controlsStateReport(a),pia.controlsStateReport(a)},this.controlsStatesRedefined=function(){tia.getVideoOutput().monitor.controlsStatesRedefined()},this.firePowerAndUserPauseStateUpdate=function(){a.consolePowerAndUserPauseStateUpdate(self.powerIsOn,userPaused),tia.getVideoOutput().monitor.consolePowerAndUserPauseStateUpdate(self.powerIsOn,userPaused)},this.releaseControllers=function(){a.releaseControllers()},this.controlsClockPulse=function(){a.controlsClockPulse()},this.getControlReport=function(a){switch(a){case jt.ConsoleControls.VIDEO_STANDARD:return{label:videoStandardIsAuto?"Auto":videoStandard.name,active:!videoStandardIsAuto};case jt.ConsoleControls.VSYNCH:return{label:vSynchMode===-1?"DISABL":vSynchMode?"ON":"OFF",active:1===vSynchMode};case jt.ConsoleControls.NO_COLLISIONS:return{label:tia.getDebugNoCollisions()?"ON":"OFF",active:tia.getDebugNoCollisions()};default:return{label:"Unknown",active:!1}}};var a}function SaveStateSocket(){this.connectMedia=function(b){a=b},this.getMedia=function(){return a},this.cartridgeInserted=function(a){a&&a.connectSaveStateSocket(this)},this.externalStateChange=function(){},this.saveState=function(c){if(self.powerIsOn){var d=saveState();d.v=b,a.saveState(c,d)?self.showOSD("State "+c+" saved",!0):self.showOSD("State "+c+" save failed",!0)}},this.loadState=function(c){var d=a.loadState(c);return d?d.v!==b?void self.showOSD("State "+c+" load failed, wrong version",!0):(self.powerIsOn||self.powerOn(),loadState(d),void self.showOSD("State "+c+" loaded",!0)):void self.showOSD("State "+c+" not found",!0)},this.saveStateFile=function(){if(self.powerIsOn){var c=cartridgeSocket.inserted()&&cartridgeSocket.inserted().rom.info.l,d=saveState();d.v=b,a.saveStateFile(c,d)?self.showOSD("State Cartridge saved",!0):self.showOSD("State file save failed",!0)}},this.loadStateFile=function(c){var d=a.loadStateFile(c);if(d)return d.v!==b?(self.showOSD("State file load failed, wrong version",!0),!0):(self.powerIsOn||self.powerOn(),loadState(d),self.showOSD("State file loaded",!0),!0)};var a,b=2}function AudioSocket(){this.connectMonitor=function(b){a=b;for(var d=c.length-1;d>=0;d--)a.connectAudioSignal(c[d])},this.connectAudioSignal=function(d){c.indexOf(d)>=0||(jt.Util.arrayAdd(c,d),this.flushAllSignals(),d.setFps(b),a&&a.connectAudioSignal(d))},this.disconnectAudioSignal=function(b){jt.Util.arrayRemoveAllElement(c,b),a&&a.disconnectAudioSignal(b)},this.audioClockPulse=function(){for(var a=c.length-1;a>=0;--a)c[a].audioClockPulse()},this.audioFinishFrame=function(){for(var a=c.length-1;a>=0;--a)c[a].audioFinishFrame()},this.muteAudio=function(){a&&a.mute()},this.unMuteAudio=function(){a&&a.unMute()},this.setFps=function(a){b=a;for(var d=c.length-1;d>=0;--d)c[d].setFps(b)},this.pauseAudio=function(){a&&a.pause()},this.unpauseAudio=function(){a&&a.unpause()},this.flushAllSignals=function(){for(var a=c.length-1;a>=0;--a)c[a].flush()};var a,b,c=[]}var self=this;this.powerOn=function(){this.powerIsOn&&this.powerOff(),bus.powerOn(),this.powerIsOn=!0,consoleControlsSocket.controlsStatesRedefined(),updateVideoSynchronization(),videoStandardAutoDetectionStart(),consoleControlsSocket.firePowerAndUserPauseStateUpdate(),mainVideoClock.isRunning()||mainVideoClock.go()},this.powerOff=function(){bus.powerOff(),this.powerIsOn=!1,consoleControlsSocket.releaseControllers(),consoleControlsSocket.controlsStatesRedefined(),userPaused?this.userPause(!1):consoleControlsSocket.firePowerAndUserPauseStateUpdate()},this.userPowerOn=function(){isLoading||this.powerOn()},this.setLoading=function(a){isLoading=a},this.userPause=function(a,b){ var c=userPaused;return userPaused!==a&&(userPaused=!!a,userPauseMoreFrames=-1,userPaused&&!b?audioSocket.muteAudio():audioSocket.unMuteAudio(),consoleControlsSocket.firePowerAndUserPauseStateUpdate()),c},this.systemPause=function(a){var b=systemPaused;return systemPaused!==a&&(systemPaused=!!a,systemPaused?audioSocket.pauseAudio():audioSocket.unpauseAudio()),b},this.isSystemPaused=function(){return systemPaused},this.videoClockPulse=function(){if(!systemPaused&&(consoleControlsSocket.controlsClockPulse(),self.powerIsOn)){if(1===videoPulldown.steps)videoFrame();else{var a=videoPulldown.cadence[--videoPulldownStep];for(0===videoPulldownStep&&(videoPulldownStep=videoPulldown.steps);a>0;)a--,videoFrame()}audioSocket.audioFinishFrame()}},this.getCartridgeSocket=function(){return cartridgeSocket},this.getConsoleControlsSocket=function(){return consoleControlsSocket},this.getVideoOutput=function(){return tia.getVideoOutput()},this.getAudioOutput=function(){return tia.getAudioOutput()},this.getSavestateSocket=function(){return saveStateSocket},this.getAudioSocket=function(){return audioSocket},this.showOSD=function(a,b){this.getVideoOutput().showOSD(a,b)},this.vSynchSetSupported=function(a){vSynchMode=a?null===Javatari.userPreferences.current.vSynch?Javatari.SCREEN_VSYNCH_MODE:Javatari.userPreferences.current.vSynch:-1};var setCartridge=function(a){Javatari.cartridge=a;var b=getCartridge();bus.setCartridge(a),cartridgeSocket.cartridgeInserted(a,b)},getCartridge=function(){return bus.getCartridge()},setVideoStandard=function(a){videoStandard!==a&&(videoStandard=a,tia.setVideoStandard(videoStandard),updateVideoSynchronization()),self.showOSD((videoStandardIsAuto?"AUTO: ":"")+videoStandard.name,!1)},setVideoStandardAuto=function(){videoStandardIsAuto=!0,self.powerIsOn?videoStandardAutoDetectionStart():setVideoStandard(jt.VideoStandard.NTSC)},videoStandardAutoDetectionStart=function(){if(videoStandardIsAuto&&!videoStandardAutoDetectionInProgress)return bus.getCartridge()?void(tia.getVideoOutput().monitor&&(videoStandardAutoDetectionInProgress=!0,videoStandardAutoDetectionTries=0,tia.getVideoOutput().monitor.videoStandardDetectionStart())):void setVideoStandard(jt.VideoStandard.NTSC)},videoStandardAutoDetectionTry=function(){videoStandardAutoDetectionTries++;var a=tia.getVideoOutput().monitor.getVideoStandardDetected();!a&&videoStandardAutoDetectionTries0?--c:a===controls.MIN_SPEED?c=0:a===controls.NORMAL_SPEED&&(c=SPEEDS.indexOf(1)),speedControl=SPEEDS[c],self.showOSD("Speed: "+(100*speedControl|0)+"%",!0),mainVideoClockUpdateSpeed();break;case controls.SAVE_STATE_0:case controls.SAVE_STATE_1:case controls.SAVE_STATE_2:case controls.SAVE_STATE_3:case controls.SAVE_STATE_4:case controls.SAVE_STATE_5:case controls.SAVE_STATE_6:case controls.SAVE_STATE_7:case controls.SAVE_STATE_8:case controls.SAVE_STATE_9:case controls.SAVE_STATE_10:case controls.SAVE_STATE_11:case controls.SAVE_STATE_12:var d=self.systemPause(!0);saveStateSocket.saveState(a.to),d||self.systemPause(!1);break;case controls.SAVE_STATE_FILE:d=self.systemPause(!0),saveStateSocket.saveStateFile(),d||self.systemPause(!1);break;case controls.LOAD_STATE_0:case controls.LOAD_STATE_1:case controls.LOAD_STATE_2:case controls.LOAD_STATE_3:case controls.LOAD_STATE_4:case controls.LOAD_STATE_5:case controls.LOAD_STATE_6:case controls.LOAD_STATE_7:case controls.LOAD_STATE_8:case controls.LOAD_STATE_9:case controls.LOAD_STATE_10:case controls.LOAD_STATE_11:case controls.LOAD_STATE_12:d=self.systemPause(!0),saveStateSocket.loadState(a.from),d||self.systemPause(!1);break;case controls.VIDEO_STANDARD:self.showOSD(null,!0),videoStandardIsAuto?setVideoStandardForced(jt.VideoStandard.NTSC):videoStandard==jt.VideoStandard.NTSC?setVideoStandardForced(jt.VideoStandard.PAL):setVideoStandardAuto();break;case controls.VSYNCH:vSynchToggleMode();break;case controls.CARTRIDGE_FORMAT:cycleCartridgeFormat()}},this.controlsStateReport=function(a){a[controls.POWER]=self.powerIsOn},this.runFramesAtTopSpeed=function(a){mainVideoClock.pause();for(var b=jt.Util.performanceNow(),c=0;c=1024&&c<=2047&&(f[c-1024]=b)};var d=function(a){return a&g};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),ra:jt.Util.compressInt8BitArrayToStringBase64(f)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),f=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,f)};var e,f=jt.Util.arrayFill(new Array(1024),0),g=4095;a&&c(this)},jt.Cartridge2K_CV.prototype=jt.Cartridge.base,jt.Cartridge2K_CV.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge2K_CV;return c.loadState(a),c},jt.CartridgeBankedByMaskedRange=function(a,b,c,d,e){"use strict";function f(f){f.rom=a,f.format=b,h=a.content;var g=h.length/q;i=c,j=i+g-1,l=e,null==d||void 0==d?(o=!1,k=!0):(o=!!d,k=!1),m=d!==!1?jt.Util.arrayFill(new Array(l),0):null}this.read=function(a){var b=g(a);return o&&b>=l&&b<2*l?m[b-l]:h[n+b]},this.write=function(a,b){var c=g(a);c=i&&b<=j&&(n=q*(b-i)),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(h),bo:n,bb:i,es:l,tb:j,s:0|o,sa:0|k,e:m&&jt.Util.compressInt8BitArrayToStringBase64(m)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),h=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,h),n=a.bo,i=a.bb,l=a.es,j=a.tb,o=!!a.s,k=!!a.sa,m=a.e&&jt.Util.uncompressStringBase64ToInt8BitArray(a.e,m)};var h,i,j,k,l,m,n=0,o=!1,p=4095,q=4096;a&&f(this)},jt.CartridgeBankedByMaskedRange.prototype=jt.Cartridge.base,jt.CartridgeBankedByMaskedRange.recreateFromSaveState=function(a,b){var c=b||new jt.CartridgeBankedByMaskedRange;return c.loadState(a),c},jt.Cartridge8K_E0=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return b<1024?e[f+b]:b<2048?e[g+b-1024]:b<3072?e[h+b-2048]:e[4096+b]},this.write=function(a,b){d(a)};var d=function(a){var b=a&i;return b>=4064&&b<=4087&&(b<=4071?f=1024*(b-4064):b<=4079?g=1024*(b-4072):b<=4087&&(h=1024*(b-4080))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),s0:f,s1:g,s2:h}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),f=a.s0,g=a.s1,h=a.s2};var e,f=0,g=0,h=0,i=4095;a&&c(this)},jt.Cartridge8K_E0.prototype=jt.Cartridge.base,jt.Cartridge8K_E0.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_E0;return c.loadState(a),c},jt.Cartridge64K_F0=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return e[f+b]},this.write=function(a,b){d(a)};var d=function(a){var b=a&g;return b==j&&(f+=i,f>=h&&(f=0)),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),bo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),f=a.bo};var e,f=0,g=4095,h=65536,i=4096,j=4080;a&&c(this)},jt.Cartridge64K_F0.prototype=jt.Cartridge.base,jt.Cartridge64K_F0.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge64K_F0;return c.loadState(a),c},jt.Cartridge8K_FE=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return e[f+b]},this.write=function(a,b){d(a)};var d=function(a){return 0!==(8192&a)?0!==f&&(f=0):f!=h&&(f=h),a&g};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),bo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),f=a.bo};var e,f=0,g=4095,h=4096;a&&c(this)},jt.Cartridge8K_FE.prototype=jt.Cartridge.base,jt.Cartridge8K_FE.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_FE;return c.loadState(a),c},jt.Cartridge16K_E7=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return b>=2304&&b<=2559?h[j+b-2304]:i&&b>=1024&&b<=2047?h[b-1024]:b=2048&&c<=2303?h[j+c-2048]=b:i&&c<=1023&&(h[c]=b)};var d=function(a){var b=a&k;return b>=4064&&b<=4075&&(b<=4070?f=m*(b-4064):4071==b?i=!0:b<=4075&&(j=g+p*(b-4072))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),bo:f,rs:i,ro:j,ra:jt.Util.compressInt8BitArrayToStringBase64(h)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),f=a.bo,i=a.rs,j=a.ro,h=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,h)};var e,f=0,g=1024,h=jt.Util.arrayFill(new Array(2048),0),i=!1,j=g,k=4095,l=16384,m=2048,n=2048,o=l-m-n,p=256;a&&c(this)},jt.Cartridge16K_E7.prototype=jt.Cartridge.base,jt.Cartridge16K_E7.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge16K_E7;return c.loadState(a),c},jt.Cartridge10K_DPCa=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,m=a.content}this.powerOn=function(){y=p,z=0},this.connectBus=function(a){l=a.getTia().getAudioOutput().getChannel0()},this.needsAudioClock=function(){return!0},this.read=function(a){var b=d(a);return b<=63||b>=2048&&b<=2111?f(255&b):m[r+b]},this.write=function(a,b){var c=d(a);(c>=64&&c<=127||c>=2112&&c<=2175)&&g(255&c,b)},this.audioClockPulse=function(){if((z+y|0)>(0|z))for(var a=5;a<=7;a++)x[a]&&(t[a]--,255==(255&t[a])&&h(a,65280&t[a]|u[a]),j(a),A||(A=!0));z+=y,A&&(e(),l.setVolume(B))};var d=function(a){var b=a&o;return 4088===b?r=0:4089===b&&(r=4096),b},e=function(){B=n[(x[5]?4&w[5]:0)|(x[6]?2&w[6]:0)|(x[7]?1&w[7]:0)],A=!1},f=function(a){var b;return a>=0&&a<=3?(k(),s):a>=4&&a<=7?(A&&e(),B):a>=8&&a<=15?(b=m[q-t[a-8]],i(a-8),b):a>=16&&a<=23?(b=m[q-t[a-16]]&w[a-16],i(a-16),b):a>=24&&a<=31?(b=m[q-t[a-24]]&w[a-24],i(a-24),b=240&b|15&b):a>=32&&a<=39?(b=m[q-t[a-32]]&w[a-32],i(a-32),b=128&b|64&b|32&b|16&b|8&b|4&b|2&b|1&b):a>=40&&a<=47?(b=m[q-t[a-40]]&w[a-40],i(a-40),b=255&(b>>>1|b<<7)):a>=48&&a<=55?(b=m[q-t[a-48]]&w[a-48],i(a-48),b=255&(b<<1|b>>7&1)):a>=56&&a<=63?w[a-56]:0},g=function(a,b){ if(a>=64&&a<=71){var c=a-64;return u[c]=b,void((255&t[c])===u[c]&&(w[c]=255))}return a>=72&&a<=79?(v[a-72]=b,void(w[a-72]=0)):a>=80&&a<=87?void h(a-80,65280&t[a-80]|255&b):a>=88&&a<=91?void h(a-88,255&t[a-88]|(7&b)<<8):92==a?void h(4,255&t[4]|(7&b)<<8):a>=93&&a<=95?(h(a-88,(255&t[a-88])+((7&b)<<8)),void(x[a-88]=(16&b)>>>4)):void(a>=96&&a<=103||a>=112&&a<=119&&(s=0))},h=function(a,b){t[a]=b},i=function(a){var b=t[a]-1;b<0&&(b=2047),h(a,b),j(a)},j=function(a){var b=255&t[a];b==u[a]?w[a]=255:b==v[a]&&(w[a]=0)},k=function(){s=255&(s<<1|1&~(s>>7^s>>5^s>>4^s>>3)),255===s&&(s=0)};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(m),bo:r,rn:s,fp:jt.Util.compressInt8BitArrayToStringBase64(t),fs:jt.Util.compressInt8BitArrayToStringBase64(u),fe:jt.Util.compressInt8BitArrayToStringBase64(v),fm:jt.Util.compressInt8BitArrayToStringBase64(w),a:jt.Util.compressInt8BitArrayToStringBase64(x)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),m=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,m),r=a.bo,s=a.rn,t=jt.Util.uncompressStringBase64ToInt8BitArray(a.fp,t),u=jt.Util.uncompressStringBase64ToInt8BitArray(a.fs,u),v=jt.Util.uncompressStringBase64ToInt8BitArray(a.fe,v),w=jt.Util.uncompressStringBase64ToInt8BitArray(a.fm,w),x=jt.Util.uncompressStringBase64ToInt8BitArray(a.a,x)};var l,m,n=[0,5,5,10,5,10,10,15],o=4095,p=.62,q=10239,r=0,s=0,t=jt.Util.arrayFill(new Array(8),0),u=jt.Util.arrayFill(new Array(8),0),v=jt.Util.arrayFill(new Array(8),0),w=jt.Util.arrayFill(new Array(8),0),x=jt.Util.arrayFill(new Array(8),0),y=p,z=0,A=!0,B=0;a&&c(this)},jt.Cartridge10K_DPCa.prototype=jt.Cartridge.base,jt.Cartridge10K_DPCa.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge10K_DPCa;return c.loadState(a),c},jt.Cartridge24K_28K_32K_FA2=function(a,b,c){"use strict";function d(d){d.rom=a,d.format=b,n=a.content,p=c||0,q=p;var e=(n.length-p)/x;o=r+e-1}var e=this;this.connectBus=function(a){l=a},this.connectSaveStateSocket=function(a){m=a},this.read=function(a){var b,c=f(a);if(b=c>=256&&c<512?s[c-256]:n[q+c],c!==y)return b;if(0===u){var d=s[z];if(1===d||2===d)return g(d),64|b}return 0===u?191&b:(j(),0!==u?64|b:191&b)},this.write=function(a,b){var c=f(a);c<256&&(s[c]=b)};var f=function(a){var b=a&w;return b>=r&&b<=o&&(q=p+x*(b-r)),b},g=function(a){u=a,t=Date.now(),1===a?h():2===a&&i()},h=function(){if(l.getTia().getVideoOutput().showOSD("Reading from Cartridge Flash Memory...",!0),m){var a=m.getMedia().loadResource(k());a&&(v=jt.Util.uncompressStringBase64ToInt8BitArray(a,v))}jt.Util.arrayCopy(v,0,s)},i=function(){l.getTia().getVideoOutput().showOSD("Writing to Cartridge Flash Memory...",!0),jt.Util.arrayCopy(s,0,v),m&&m.getMedia().saveResource(k(),jt.Util.compressInt8BitArrayToStringBase64(v))},j=function(){Date.now()-t>1100&&(t=Date.now(),u=0,s[z]=0,l.getTia().getVideoOutput().showOSD("Done.",!0),m&&m.externalStateChange())},k=function(){return"hfm"+e.rom.info.h};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(n),rs:p,bo:q,tb:o,e:jt.Util.compressInt8BitArrayToStringBase64(s),ho:u,ht:t}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),n=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,n),p=a.rs||0,q=a.bo,o=a.tb,s=jt.Util.uncompressStringBase64ToInt8BitArray(a.e,s),u=a.ho||0,t=Date.now()};var l,m,n,o,p=0,q=0,r=4085,s=jt.Util.arrayFill(new Array(256),0),t=Date.now(),u=0,v=jt.Util.arrayFill(new Array(256),0),w=4095,x=4096,y=4084,z=255;a&&d(this)},jt.Cartridge24K_28K_32K_FA2.prototype=jt.Cartridge.base,jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge24K_28K_32K_FA2;return c.loadState(a),c},jt.CartridgeBankedByBusMonitoring=function(a,b){"use strict";this.needsBusMonitoring=function(){return!0},this.monitorBusBeforeRead=function(a,b){this.performBankSwitchOnMonitoredAccess(a)},this.monitorBusBeforeWrite=function(a,b){this.performBankSwitchOnMonitoredAccess(a)},this.performBankSwitchOnMonitoredAccess=function(a){}},jt.CartridgeBankedByBusMonitoring.prototype=jt.Cartridge.base,jt.CartridgeBankedByBusMonitoring.base=new jt.CartridgeBankedByBusMonitoring,jt.Cartridge8K_512K_3F=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,d=a.content,e=(d.length-i)/i-1,f=d.length-2*i}this.read=function(a){var b=a&h;return b>=j?d[f+b]:d[g+b]},this.monitorBusBeforeWrite=function(a,b){if(a<=63){var c=255&b;c<=e&&(g=c*i)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:g,sm:e,fo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),g=a.bo,e=a.sm,f=a.fo};var d,e,f,g=0,h=4095,i=2048,j=2048;a&&c(this)},jt.Cartridge8K_512K_3F.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3F.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_512K_3F;return c.loadState(a),c},jt.Cartridge8K_512K_3E=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=a.content,f=(e.length-m)/m-1,g=e.length-2*m}this.read=function(a){var b=d(a);return b>=n?e[g+b]:j>=0&&b<1024?k[j+b]||0:e[i+b]},this.write=function(a,b){if(!(j<0)){var c=d(a);c>=1024&&c<=2047&&(k[j+c-1024]=b)}};var d=function(a){return a&l};this.monitorBusBeforeWrite=function(a,b){if(63===a){var c=255&b;return void(c<=f&&(i=c*m,j=-1))}if(62===a){var d=255&b;j=d*h}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e),bo:i,sm:f,fo:g,ro:j,ra:jt.Util.compressInt8BitArrayToStringBase64(k)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e),i=a.bo,f=a.sm,g=a.fo,j=a.ro,k=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,k)};var e,f,g,h=1024,i=0,j=-1,k=jt.Util.arrayFill(new Array(h),0),l=4095,m=2048,n=2048;a&&c(this)},jt.Cartridge8K_512K_3E.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3E.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_512K_3E;return c.loadState(a),c},jt.Cartridge8K_256K_SB=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,d=a.content,e=d.length/h-1}this.read=function(a){return d[f+(a&g)]},this.performBankSwitchOnMonitoredAccess=function(a){if(2048===(6144&a)){var b=127&a;b>e||(f=b*h)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:f,m:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),f=a.bo,e=a.m};var d,e,f=0,g=4095,h=4096;a&&c(this)},jt.Cartridge8K_256K_SB.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_256K_SB.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_256K_SB;return c.loadState(a),c},jt.Cartridge8K_64K_AR=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,e=jt.Util.arrayFill(new Array(4*M)),o()}this.powerOn=function(){h(0),E=0},this.connectBus=function(a){d=a},this.read=function(a){return f=K&&f0?void(a!==v&&(v=a,0===--w&&(a&R)===S&&(f>2&7;switch(b){case 0:q=2*M,r=N;break;case 1:q=0*M,r=N;break;case 2:q=2*M,r=0*M;break;case 3:q=0*M,r=2*M;break;case 4:q=2*M,r=N;break;case 5:q=1*M,r=N;break;case 6:q=2*M,r=1*M;break;case 7:q=1*M,r=2*M;break;default:throw new Error("Invalid bank configuration")}w=0,u=0!==(2&a),x=0===(1&a)},i=function(b){for(var c=!1;;){if(E>a.content.length-1){ if(c)return 0===b?d.getTia().getVideoOutput().showOSD("Could not load Tape from Start. Not a Start Tape ROM!",!0):d.getTia().getVideoOutput().showOSD("Could not find next Part to load in Tape!",!0),void n(!1);E=0,c=!0}if(jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,E)===b)return 0===b?d.getTia().getVideoOutput().showOSD("Loaded Tape from Start",!0):d.getTia().getVideoOutput().showOSD("Loaded next Part from Tape",!0),void j();E+=O}},j=function(){k(),l(),m()},k=function(){jt.Util.arrayCopy(a.content,E+4*M,s,0,s.length),y=s[1]<<8|255&s[0],z=s[2],A=s[3],B=s[4],C=s[5],D=s[7]<<8|255&s[6],g=jt.Util.arrayFill(new Array(A),0),jt.Util.arrayCopy(s,16,g,0,A)},l=function(){jt.Util.arrayFillSegment(e,7*L,8*L-1,0);for(var b=E,c=0,d=g.length;c>2)*L;h+i+255>8&255,n(!0)},n=function(a){e[N+J-63488]=a?1:0},o=function(){var a=jt.Util.uncompressStringBase64ToInt8BitArray(P);jt.Util.arrayCopy(a,0,e,N,M)},p=256,q=0,r=0,s=jt.Util.arrayFill(new Array(p),0),t=0,u=!1,v=-1,w=0,x=!1,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=64256,G=64257,H=64258,I=64260,J=64261,K=3072,L=256,M=8*L,N=3*M,O=4*M+p,P="7dSxCsIwEAbgv6niGkeddPVZ8kCOXc43yCIokkGIUN+gLxAoZHTxHRxjYq2xk7vSIPS75bb7uYNTuOJWu/bod3iU42BzUTiBe9sTzSjToBnNBVxfQz/nQ+2NhA2a05KYmhhjmxhoQZymxGil8gpeesOdyioW5DN25yxsiri3chQOUO1WeCSI/hPx9AJ/m/576KROMUhlfdE4dQ+AfJoPNBikgOZdLw==",Q=4095,R=4096,S=4096;this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(e)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,e)},a&&c(this)},jt.Cartridge8K_64K_AR.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_64K_AR.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_64K_AR;return c.loadState(a),c},jt.Cartridge8K_64K_AR.HEADER_SIZE=256,jt.Cartridge8K_64K_AR.PAGE_SIZE=256,jt.Cartridge8K_64K_AR.BANK_SIZE=8*jt.Cartridge8K_64K_AR.PAGE_SIZE,jt.Cartridge8K_64K_AR.PART_SIZE=4*jt.Cartridge8K_64K_AR.BANK_SIZE+jt.Cartridge8K_64K_AR.HEADER_SIZE,jt.Cartridge8K_64K_AR.peekPartNoOnTape=function(a,b){return a[b+4*jt.Cartridge8K_64K_AR.BANK_SIZE+5]},jt.Cartridge8K_64K_AR.checkTape=function(a){return 0===jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,0)||(jt.Util.warning("Wrong Supercharger Tape Part ROM! Please load a Full Tape ROM file"),!1)},jt.Cartridge64K_X07=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){2061===(6159&a)?e=((240&a)>>4)*g:e>=h&&0===(6272&a)&&(e=(0===(64&a)?14:15)*g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),e=a.bo};var d,e=0,f=4095,g=4096,h=14*g;a&&c(this)},jt.Cartridge64K_X07.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge64K_X07.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge64K_X07;return c.loadState(a),c},jt.Cartridge8K_0840=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){var b=6208&a;2048===b?0!==e&&(e=0):2112===b&&e!==g&&(e=g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),e=a.bo};var d,e=0,f=4095,g=4096;a&&c(this)},jt.Cartridge8K_0840.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_0840.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_0840;return c.loadState(a),c},jt.Cartridge8K_UA=function(a,b){"use strict";function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){544===a?0!==e&&(e=0):576===a&&e!==g&&(e=g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),e=a.bo};var d,e=0,f=4095,g=4096;a&&c(this)},jt.Cartridge8K_UA.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_UA.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_UA;return c.loadState(a),c},jt.CartridgeFormats={"4K":{name:"4K",desc:"4K Atari",priority:101,tryFormat:function(a){if(a.content.length>=8&&a.content.length<=4096&&4096%a.content.length===0)return this},createCartridgeFromRom:function(a){return new jt.Cartridge4K(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge4K.recreateFromSaveState(a,b)}},CV:{name:"CV",desc:"2K Commavid +RAM",priority:102,tryFormat:function(a){if(2048===a.content.length||4096===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge2K_CV(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge2K_CV.recreateFromSaveState(a,b)}},E0:{name:"E0",desc:"8K Parker Bros.",priority:102,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_E0(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_E0.recreateFromSaveState(a,b)}},F0:{name:"F0",desc:"64K Dynacom Megaboy",priority:101,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_F0(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge64K_F0.recreateFromSaveState(a,b)}},FE:{name:"FE",desc:"8K Robotank/Decathlon",priority:103,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_FE(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_FE.recreateFromSaveState(a,b)}},E7:{name:"E7",desc:"16K M-Network",priority:102,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge16K_E7(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge16K_E7.recreateFromSaveState(a,b)}},F8:{name:"F8",desc:"8K Atari (+RAM)",priority:101,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},F6:{name:"F6",desc:"16K Atari (+RAM)",priority:101,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4086,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},F4:{name:"F4",desc:"32K Atari (+RAM)",priority:101,tryFormat:function(a){if(32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4084,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},FA2cu:{name:"FA2cu",desc:"32K CBS RAM Plus CU Image",priority:103,tryFormat:function(a){if(32768===a.content.length){var b=jt.Util.arraysEqual(a.content.slice(32,36),this.cuMagicWord);return this.priority=103-(b?30:0),this}},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this,1024)},recreateCartridgeFromSaveState:function(a,b){ return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(a,b)},cuMagicWord:[30,171,173,16]},FA2:{name:"FA2",desc:"24K/28K/32K CBS RAM Plus",priority:102,tryFormat:function(a){if(24576===a.content.length||28672===a.content.length||32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(a,b)}},FA:{name:"FA",desc:"12K CBS RAM Plus",priority:101,tryFormat:function(a){if(12288===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,!0,256)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},EF:{name:"EF",desc:"8K-64K H. Runner (+RAM)",priority:114,tryFormat:function(a){if(a.content.length%4096===0&&a.content.length>=8192&&a.content.length<=65536)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4064,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},DPC:{name:"DPC",desc:"10K DPC Pitfall 2 (Enhanced Audio)",priority:101,tryFormat:function(a){if(a.content.length>=10240&&a.content.length<=10496)return this},createCartridgeFromRom:function(a){return new jt.Cartridge10K_DPCa(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge10K_DPCa.recreateFromSaveState(a,b)}},"3F":{name:"3F",desc:"8K-512K Tigervision",priority:112,tryFormat:function(a){if(a.content.length%2048===0&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3F(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_512K_3F.recreateFromSaveState(a,b)}},"3E":{name:"3E",desc:"8K-512K Tigervision (+RAM)",priority:111,tryFormat:function(a){if(a.content.length%2048===0&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3E(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_512K_3E.recreateFromSaveState(a,b)}},X07:{name:"X07",desc:"64K AtariAge",priority:102,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_X07(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge64K_X07.recreateFromSaveState(a,b)}},"0840":{name:"0840",desc:"8K Econobanking",priority:116,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_0840(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_0840.recreateFromSaveState(a,b)}},UA:{name:"UA",desc:"8K UA Limited",priority:115,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_UA(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_UA.recreateFromSaveState(a,b)}},SB:{name:"SB",desc:"8K-256K Superbanking",priority:113,tryFormat:function(a){if(a.content.length%4096===0&&a.content.length>=8192&&a.content.length<=262144)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_256K_SB(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_256K_SB.recreateFromSaveState(a,b)}},AR:{name:"AR",desc:"8K-64K Arcadia/Starpath/Supercharger",priority:101,tryFormat:function(a){if(a.content.length%jt.Cartridge8K_64K_AR.PART_SIZE===0&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE>=1&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE<=8&&jt.Cartridge8K_64K_AR.checkTape(a))return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_64K_AR(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_64K_AR.recreateFromSaveState(a,b)}}},jt.CartridgeCreatorImpl=function(){"use strict";this.createCartridgeFromRom=function(b){var c=a(b);if(0!==c.length){var d=c[0];return jt.Util.log(""+d.name+": "+d.desc+", priority: "+d.priority+(d.priorityBoosted?" ("+d.priorityBoosted+")":"")),d.createCartridgeFromRom(b)}},this.recreateCartridgeFromSaveState=function(a,b){var c=jt.CartridgeFormats[a.f];if(!c)throw new Error("Unsupported ROM Format: "+a.f);return b&&b.format!==c&&(b=null),c.recreateCartridgeFromSaveState(a,b)},this.produceInfo=function(a,d){var e=a.content.length,f=jt.MD5(a.content);a.content.length>e&&a.content.splice(e);var g=jt.CartridgeDatabase[f];return g?jt.Util.log(""+g.n+" ("+f+")"):(g=b(a.source),jt.Util.log("Unknown ROM: "+g.n+" ("+f+")")),c(g,a.source,f,d),g};var a=function(a){var b,c,e=[];for(var f in jt.CartridgeFormats)try{if(b=jt.CartridgeFormats[f].tryFormat(a),!b)continue;d(b,a.info),e.push(b)}catch(a){if(!a.formatDenial)throw a;c||(c=a)}return e.sort(function(a,b){return(a.priorityBoosted||a.priority)-(b.priorityBoosted||b.priority)}),e},b=function(a){var b={n:"Unknown"};if(!a||!a.trim())return b;var c=a,d=c.lastIndexOf("/"),e=c.lastIndexOf("\\"),f=c.lastIndexOf("?"),g=Math.max(d,Math.max(e,f));g>=0&&g=0&&(c=c.substring(0,h)),b.n=c.trim()||"Unknown",b},c=function(a,b,c,d){a.h=c,a.l||(a.l=e(a.n));var m=a.n.toUpperCase();a:if(!a.p&&(a.p=0,!m.match(k+"JOYSTICK(S)?"+l)))if(m.match(k+"PADDLE(S)?"+l))a.p=1;else for(var n=0;n=f&&(d=d.slice(0,f-1),e=e.slice(0,f-1));d.unshift({n:b.info.l,h:b.info.h,f:b.info.f});for(var h=0;h0&&(1===b.length?j.readFromFile(b[0],p,q,r,s,d):j.readFromFiles(b,p,q,r,s,d)),!1}}function f(a){a.returnValue=!1,a.preventDefault(),a.stopPropagation(),a.dataTransfer&&(Javatari.CARTRIDGE_CHANGE_DISABLED?a.dataTransfer.dropEffect="none":a.ctrlKey?a.dataTransfer.dropEffect="copy":a.altKey&&(a.dataTransfer.dropEffect="link")),t=a.buttons>0?a.buttons:u}function g(a){if(a.returnValue=!1,a.preventDefault(),a.stopPropagation(),a.target.focus(),!Javatari.CARTRIDGE_CHANGE_DISABLED&&a.dataTransfer){var b=k.systemPause(!0),c=a.shiftKey?1:0,d=t&v,e=a.ctrlKey,f=w.AUTO,g=a.dataTransfer&&a.dataTransfer.files,h=function(a){b||k.systemPause(!1)};if(g&&g.length>0)1===g.length?j.readFromFile(g[0],f,c,d,e,h):j.readFromFiles(g,f,c,d,e,h);else{var i=a.dataTransfer.getData("text");i&&i.length>0?j.readFromURL(i,f,c,d,e,h):h()}}}function h(a){jt.Util.message("Could not load file(s):\n\n"+a+"\n")}function i(){n=document.createElement("input"),n.id="jt-file-loader-input",n.type="file",n.multiple=!0,n.accept=x.AUTO,n.style.display="none",n.addEventListener("change",e),o.appendChild(n)}var j=this;this.connect=function(a){k=a,l=k.getCartridgeSocket(),m=k.getSavestateSocket()},this.registerForDnD=function(a){a.addEventListener("dragover",f,!1),a.addEventListener("drop",g,!1)},this.registerForFileInputElement=function(a){o=a},this.openFileChooserDialog=function(a,b,c,d){n||i(),n.multiple=y[w[a]||w.AUTO],n.accept=x[w[a]||w.AUTO],p=a,q=c?1:0,r=b,s=d,n.click()},this.openURLChooserDialog=function(a,b,c,d){var e,f=c?1:0;try{e=localStorage&&localStorage[A]}catch(a){}var g=k.systemPause(!0);if(e=prompt("Load file from URL:",e||""),e=e&&e.toString().trim()){try{localStorage[A]=e}catch(a){}this.readFromURL(e,a,f,b,d,function(){g||k.systemPause(!1)})}else g||k.systemPause(!1)},this.readFromFile=function(a,b,c,d,e,f){jt.Util.log("Reading file: "+a.name);var g=new FileReader;g.onload=function(g){var h=new Uint8Array(g.target.result),i={name:a.name,content:h,lastModifiedDate:a.lastModified?new Date(a.lastModified):a.lastModifiedDate};j.loadFromFile(i,b,c,d,e),f&&f(!0)},g.onerror=function(a){h("File reading error: "+a.target.error.name+B),f&&f(!1)},g.readAsArrayBuffer(a)},this.readFromURL=function(a,b,c,d,e,f){new jt.MultiDownloader([{url:a}],function(g){var h={name:a,content:g[0].content,lastModifiedDate:null};j.loadFromFile(h,b,c,d,e),f&&f(!0)},function(a){h("URL reading error: "+a[0].error),f&&f(!1)}).start()},this.readFromFiles=function(a,b,c,d,e,f){var g=new jt.MultiFileReader(a,function(a){j.loadFromFiles(a,b,c,d,e),f&&f(!0)},function(a,b,c){c||(b+=B),h("File reading error: "+b),f&&f(!1)});g.start()},this.loadFromContent=function(a,b,c,d,e,f,g){return this.loadFromFile({name:a,content:b},c,d,e,f,g)},this.loadFromFile=function(a,c,d,e,f,g){var i;if(i=jt.Util.checkContentIsZIP(a.content))try{var j=jt.Util.getZIPFilesSorted(i);if(b(j,c,d,e,f,g,!0))return}catch(a){jt.Util.error(a)}else if(b([a],c,d,e,f,g,!1))return;h("No valid "+z[c]+" found.")},this.loadFromFiles=function(a,c,d,e,f){a=jt.Util.asNormalArray(a).slice(0),a.sort(function(a,b){return a.nameb.name?1:0}),b(a,c,d,e,f,null,!1)||h("No valid "+z[c]+" found.")},this.loadROM=function(b,c,d,e){var f=jt.CartridgeCreator.createCartridgeFromRom(b);return!!f&&(l.insert(f,!d),a.storeROM(b),!0)};var k,l,m,n,o,p,q=0,r=!1,s=!1,t=1,u=1,v=2,w=jt.FileLoader.OPEN_TYPE;this.OPEN_TYPE=w;var x={ROM:".bin,.BIN,.rom,.ROM,.a26,.A26,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP",STATE:".jst,.JST",CART_DATA:".dat,.DAT,.sram,.SRAM",AUTO:".bin,.BIN,.rom,.ROM,.a26,.A26,.jst,.JST,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP"},y={ROM:!1,STATE:!1,CART_DATA:!1,AUTO:!1},z={ROM:"ROM",STATE:"Savestate",CART_DATA:"Cartridge Data",AUTO:"ROM"},A="javatarilasturl",B="\n\nIMPORTANT: Directories are not supported for loading!";Javatari.fileLoader=this},jt.FileLoader.OPEN_TYPE={AUTO:"AUTO",ROM:"ROM",STATE:"STATE",CART_DATA:"CART_DATA"},jt.FileDownloader=function(){"use strict";function a(){if("NONE"===c)return alert("Unfortunately file saving in WebApps is broken in this version of iOS. The file could not be saved. If you really need to save a file, you must run Javatari on the official homepage."),!0}function b(){c=jt.Util.isIOSDevice()?jt.Util.isBrowserStandaloneMode()?"NONE":"DATA":"SAFARI"===jt.Util.browserInfo().name?"DATA":"BLOB","NONE"!==c&&(d=document.createElement("a"),d.style.display="none",d.target="_blank",d.href="#",e.appendChild(d))}this.connectPeripherals=function(a){f=a},this.registerForDownloadElement=function(a){e=a},this.startDownloadBinary=function(e,g,h){try{if(c||b(),a())return;var i;if("BLOB"===c){d.href&&(window.URL||window.webkitURL).revokeObjectURL(d.href);var j=new Blob([g],{type:"data:application/octet-stream"});i=(window.URL||window.webkitURL).createObjectURL(j)}else i="data:application/octet-stream;base64,"+btoa("string"==typeof g?g:jt.Util.int8BitArrayToByteString(g));d.download=e&&e.trim(),d.href=i,d.click(),f.showOSD(h+" saved",!0)}catch(a){f.showOSD(h+" save FAILED!",!0,!0),jt.Util.error(a)}},this.startDownloadURL=function(e,g,h){try{if(c||b(),a())return;"BLOB"===c&&d.href&&(window.URL||window.webkitURL).revokeObjectURL(d.href),d.download=e&&e.trim(), d.href=g,d.click(),f.showOSD(h+" saved",!0)}catch(a){f.showOSD(h+" save FAILED!",!0,!0),jt.Util.error(a)}};var c,d,e,f},jt.DOMKeys={},jt.DOMKeys.MOD_SHIFT=16,jt.DOMKeys.LOC_SHIFT=24,jt.DOMKeys.SHIFT=65536,jt.DOMKeys.CONTROL=131072,jt.DOMKeys.ALT=262144,jt.DOMKeys.META=524288,jt.DOMKeys.LOCNONE=0,jt.DOMKeys.LOCLEFT=16777216,jt.DOMKeys.LOCRIGHT=33554432,jt.DOMKeys.LOCNUM=50331648,jt.DOMKeys.IGNORE_ALL_MODIFIERS_MASK=~(jt.DOMKeys.SHIFT|jt.DOMKeys.CONTROL|jt.DOMKeys.ALT|jt.DOMKeys.META),function(a,b,c,d){a.VK_F1={c:112,n:"F1"},a.VK_F2={c:113,n:"F2"},a.VK_F3={c:114,n:"F3"},a.VK_F4={c:115,n:"F4"},a.VK_F5={c:116,n:"F5"},a.VK_F6={c:117,n:"F6"},a.VK_F7={c:118,n:"F7"},a.VK_F8={c:119,n:"F8"},a.VK_F9={c:120,n:"F9"},a.VK_F10={c:121,n:"F10"},a.VK_F11={c:122,n:"F11"},a.VK_F12={c:123,n:"F12"},a.VK_1={c:49,n:"1"},a.VK_2={c:50,n:"2"},a.VK_3={c:51,n:"3"},a.VK_4={c:52,n:"4"},a.VK_5={c:53,n:"5"},a.VK_6={c:54,n:"6"},a.VK_7={c:55,n:"7"},a.VK_8={c:56,n:"8"},a.VK_9={c:57,n:"9"},a.VK_0={c:48,n:"0"},a.VK_Q={c:81,n:"Q"},a.VK_W={c:87,n:"W"},a.VK_E={c:69,n:"E"},a.VK_R={c:82,n:"R"},a.VK_T={c:84,n:"T"},a.VK_Y={c:89,n:"Y"},a.VK_U={c:85,n:"U"},a.VK_I={c:73,n:"I"},a.VK_O={c:79,n:"O"},a.VK_P={c:80,n:"P"},a.VK_A={c:65,n:"A"},a.VK_S={c:83,n:"S"},a.VK_D={c:68,n:"D"},a.VK_F={c:70,n:"F"},a.VK_G={c:71,n:"G"},a.VK_H={c:72,n:"H"},a.VK_J={c:74,n:"J"},a.VK_K={c:75,n:"K"},a.VK_L={c:76,n:"L"},a.VK_Z={c:90,n:"Z"},a.VK_X={c:88,n:"X"},a.VK_C={c:67,n:"C"},a.VK_V={c:86,n:"V"},a.VK_B={c:66,n:"B"},a.VK_N={c:78,n:"N"},a.VK_M={c:77,n:"M"},a.VK_ESCAPE={c:27,n:"Esc"},a.VK_ENTER={c:13,n:"Enter"},a.VK_SPACE={c:32,n:"Space"},a.VK_TAB={c:9,n:"Tab"},a.VK_BACKSPACE={c:8,n:"BackSpc"},a.VK_CONTEXT={c:93,n:"Context"},a.VK_LSHIFT={c:16|b,n:"L-Shift"},a.VK_LCONTROL={c:17|b,n:"L-Control"},a.VK_LALT={c:18|b,n:"L-Alt"},a.VK_LMETA={c:91|b,n:"L-Meta"},a.VK_RSHIFT={c:16|c,n:"R-Shift"},a.VK_RCONTROL={c:17|c,n:"R-Control"},a.VK_RALT={c:18|c,n:"R-Alt"},a.VK_RMETA={c:91|c,n:"R-Meta"},a.VK_CAPS_LOCK={c:20,n:"CapsLock"},a.VK_PRINT_SCREEN={c:44,n:"PrtScr"},a.VK_SCROLL_LOCK={c:145,n:"ScrLck"},a.VK_PAUSE={c:19,n:"Pause"},a.VK_BREAK={c:3,n:"Break"},a.VK_INSERT={c:45,n:"Ins"},a.VK_DELETE={c:46,n:"Del"},a.VK_HOME={c:36,n:"Home"},a.VK_END={c:35,n:"End"},a.VK_PAGE_UP={c:33,n:"PgUp"},a.VK_PAGE_DOWN={c:34,n:"PgDown"},a.VK_NUM_INSERT={c:45|d,n:"Num Ins"},a.VK_NUM_DELETE={c:46|d,n:"Num Del"},a.VK_NUM_HOME={c:36|d,n:"Num Home"},a.VK_NUM_END={c:35|d,n:"Num End"},a.VK_NUM_PAGE_UP={c:33|d,n:"Num PgUp"},a.VK_NUM_PAGE_DOWN={c:34|d,n:"Num PgDown"},a.VK_UP={c:38,n:"Up"},a.VK_DOWN={c:40,n:"Down"},a.VK_LEFT={c:37,n:"Left"},a.VK_RIGHT={c:39,n:"Right"},a.VK_NUM_UP={c:38|d,n:"Num Up"},a.VK_NUM_DOWN={c:40|d,n:"Num Down"},a.VK_NUM_LEFT={c:37|d,n:"Num Left"},a.VK_NUM_RIGHT={c:39|d,n:"Num Right"},a.VK_NUMLOCK={c:144,n:"NumLock"},a.VK_NUM_COMMA={c:110|d,n:"Num ,"},a.VK_NUM_DIVIDE={c:111|d,n:"Num /"},a.VK_NUM_MULTIPLY={c:106|d,n:"Num *"},a.VK_NUM_MINUS={c:109|d,n:"Num -"},a.VK_NUM_PLUS={c:107|d,n:"Num +"},a.VK_NUM_PERIOD={c:194|d,n:"Num ."},a.VK_NUM_0={c:96|d,n:"Num 0"},a.VK_NUM_1={c:97|d,n:"Num 1"},a.VK_NUM_2={c:98|d,n:"Num 2"},a.VK_NUM_3={c:99|d,n:"Num 3"},a.VK_NUM_4={c:100|d,n:"Num 4"},a.VK_NUM_5={c:101|d,n:"Num 5"},a.VK_NUM_6={c:102|d,n:"Num 6"},a.VK_NUM_7={c:103|d,n:"Num 7"},a.VK_NUM_8={c:104|d,n:"Num 8"},a.VK_NUM_9={c:105|d,n:"Num 9"},a.VK_NUM_CLEAR={c:12|d,n:"Num Clear"},a.VK_NUM_ENTER={c:13|d,n:"Num Enter"},a.VK_QUOTE={c:222,n:"'"},a.VK_BACKQUOTE={c:192,n:"`"},a.VK_MINUS={c:189,n:"-"},a.VK_EQUALS={c:187,n:"="},a.VK_OPEN_BRACKET={c:219,n:"["},a.VK_CLOSE_BRACKET={c:221,n:"]"},a.VK_COMMA={c:188,n:","},a.VK_PERIOD={c:190,n:"."},a.VK_SEMICOLON={c:186,n:";"},a.VK_SLASH={c:191,n:"/"},a.VK_BACKSLASH={c:220,n:"\\"},a.VK_ALTERNATE_ESC={c:a.VK_F1.c|jt.DOMKeys.ALT,n:["Alt","F1"]},a.VK_FF_MINUS={c:173,n:"-"},a.VK_FF_EQUALS={c:61,n:"="},a.VK_FF_SEMICOLON={c:59,n:";"},a.VK_BR_QUOTE={c:192,n:"'"},a.VK_BR_OPEN_BRACKET={c:221,n:"["},a.VK_BR_CLOSE_BRACKET={c:220,n:"]"},a.VK_BR_SEMICOLON={c:191,n:";"},a.VK_BR_SLASH={c:193,n:"/"},a.VK_BR_BACKSLASH={c:226,n:"\\"},a.VK_BR_CEDILLA={c:186,n:"Ç"},a.VK_BR_TILDE={c:222,n:"~"},a.VK_BR_ACUTE={c:219,n:"´"},a.VK_FF_BR_TILDE={c:176,n:"~"},a.VK_VOID={c:-1,n:""}}(jt.DOMKeys,jt.DOMKeys.LOCLEFT,jt.DOMKeys.LOCRIGHT,jt.DOMKeys.LOCNUM),jt.DOMKeys.forcedNames={27:"Esc",13:"Enter",32:"Space",9:"Tab",8:"BkSpc",16:"Shift",17:"Ctrl",18:"Alt",91:"Meta",93:"Context",20:"Caps",44:"PrtScr",145:"ScrLck",19:"Pause",3:"Break",45:"Ins",46:"Del",36:"Home",35:"End",33:"PgUp",34:"PgDown",38:"Up",40:"Down",37:"Left",39:"Right"},jt.DOMKeys.isModifierKeyCode=function(a){return 16===a||17===a||18===a||91===a},jt.DOMKeys.codeForKeyboardEvent=function(a){var b=a.keyCode;return this.isModifierKeyCode(b)?b&this.IGNORE_ALL_MODIFIERS_MASK|a.location<12&&(c=c.substr(0,12)),a.location){case 1:c="L-"+c;break;case 2:c="R-"+c;break;case 3:c="Num "+c}return(a.shiftKey||a.ctrlKey||a.altKey||a.metaKey)&&(c=[c],a.metaKey&&c.unshift("Meta"),a.altKey&&c.unshift("Alt"),a.ctrlKey&&c.unshift("Ctrl"),a.shiftKey&&c.unshift("Shift")),c},jt.DOMKeys.nameForKeyboardEventSingle=function(a){var b=a.keyCode,c=this.forcedNames[b]||a.key,d=c&&c.toUpperCase();switch(d&&"UNIDENTIFIED"!==d&&"UNDEFINED"!==d&&"UNKNOWN"!==d?"DEAD"===d&&(c="Dead#"+b):c="#"+b,1===c.length?c=c.toUpperCase():c.length>12&&(c=c.substr(0,12)),a.location){case 1:c="L-"+c;break;case 2:c="R-"+c;break;case 3:c="Num "+c}return c},jt.GamepadButtons={GB_1:{b:0,n:"1"},GB_2:{b:1,n:"2"},GB_3:{b:2,n:"3"},GB_4:{b:3,n:"4"},GB_L1:{b:4,n:"L1"},GB_R1:{b:5,n:"R1"},GB_L2:{b:6,n:"L2"},GB_R2:{b:7,n:"R2"},GB_BACK:{b:8,n:"BACK"},GB_START:{b:9,n:"START"},GB_S1:{b:10,n:"S1"},GB_S2:{b:11,n:"S2"},GB_UP:{b:12,n:"▲"},GB_DOWN:{b:13,n:"▼"},GB_LEFT:{b:14,n:"◄"},GB_RIGHT:{b:15,n:"►"},GB_LOGO:{b:16,n:"LOGO"},GB_VOID:{b:-1,n:"Unbound"}},jt.TouchControls={buttons:["T_B","T_A"]},jt.GamepadConsoleControls=function(a){"use strict";function b(a,b){this.index=a,this.update=function(b){return c=b[a],!!c},this.hasMoved=function(){var a=c.timestamp;return!a||a>m&&(m=a,!0)},this.getButtonDigital=function(a){var b=c.buttons[a];return"object"==typeof b?b.pressed||b.value>.5:b>.5},this.getDPadDirection=function(){return this.getButtonDigital(12)?this.getButtonDigital(15)?1:this.getButtonDigital(14)?7:0:this.getButtonDigital(13)?this.getButtonDigital(15)?3:this.getButtonDigital(14)?5:4:this.getButtonDigital(14)?6:this.getButtonDigital(15)?2:-1},this.getStickDirection=function(){var a=c.axes[d],b=c.axes[e];if((a<0?-a:a)=1&&(h-=1),8*h|0},this.getPaddlePosition=function(){var a=c.axes[h]*i*j+k|0;return a<0?a=0:a>380&&(a=380),a};var c,d=b.xAxis,e=b.yAxis,f=b.xAxisSig,g=b.yAxisSig,h=b.paddleAxis,i=b.paddleAxisSig,j=b.paddleSens*-190,k=b.paddleCenter*-190+190-5,l=b.deadzone,m=Number.MIN_VALUE}this.connect=function(a){h=a},this.connectScreen=function(a){i=a},this.powerOn=function(){r=!!navigator.getGamepads,r&&(this.applyPreferences(),e())},this.powerOff=function(){r=!1},this.toggleMode=function(){return r?(++u,u>0&&(u=-2),u===-2?j=k=null:u===-1&&(s=60,this.controlsClockPulse()),w=0===u,this.applyPreferences(),e(),void i.showOSD("Gamepads "+this.getModeDesc(),!0)):void i.showOSD("Joysticks unavailable (not supported by browser)",!0,!0)},this.setPaddleMode=function(a){r&&(v=a,l.xPosition=m.xPosition=-1)},this.setP1ControlsMode=function(a){x=a,this.applyPreferences()},this.controlsClockPulse=function(){if(r&&u!==-2&&(++s>=60&&(s=0),j||k||0===s)){var a=navigator.getGamepads(); j?j.update(a)?j.hasMoved()&&f(j,l,n,p):(j=null,c(!0,!1)):0===s&&(j=d(n,o,a),j&&c(!0,!0)),k?k.update(a)?k.hasMoved()&&f(k,m,o,q):(k=null,c(!1,!1)):0===s&&(k=d(o,n,a),k&&c(!1,!0))}};var c=function(a,b){i.showOSD((a^x^w?"P1":"P2")+" Gamepad "+(b?"connected":"disconnected"),a)},d=function(a,c,d){if(d&&0!==d.length){var e=a.device;if(e>=0)return d[e]&&d[e].buttons.length>0?new b(e,a):null;for(var f=0,g=d.length;f0&&!(f===c.device||j&&j.index===f||k&&k.index===f))return new b(f,a)}},e=function(){l=g(),m=g()},f=function(b,c,d,e){if(v&&0!==d.paddleSens){var f=b.getPaddlePosition();f!==c.xPosition&&(c.xPosition=f,h.controlValueChanged(d.player?t.PADDLE1_POSITION:t.PADDLE0_POSITION,f))}var g=b.getDPadDirection();if(g!==-1||v&&0!==d.paddleSens||(g=b.getStickDirection()),g!==c.direction){var i=!1,j=!1,k=!1,l=!1;switch(g){case 0:i=!0;break;case 1:i=j=!0;break;case 2:j=!0;break;case 3:k=j=!0;break;case 4:k=!0;break;case 5:k=l=!0;break;case 6:l=!0;break;case 7:i=l=!0}a.processKey(e.up.c,i),a.processKey(e.right.c,j),a.processKey(e.down.c,k),a.processKey(e.left.c,l),c.direction=g}var m=b.getButtonDigital(d.button);m!==c.button&&(a.processKey(e.button.c,m),c.button=m),m=b.getButtonDigital(d.buttonT),m!==c.buttonT&&(a.processKey(e.buttonT.c,m),c.buttonT=m);var n=b.getButtonDigital(d.select);n!==c.select&&(h.controlStateChanged(t.SELECT,n),c.select=n);var o=b.getButtonDigital(d.reset);o!==c.reset&&(h.controlStateChanged(t.RESET,o),c.reset=o);var p=b.getButtonDigital(d.pause);p!==c.pause&&(h.controlStateChanged(t.PAUSE,p),c.pause=p);var q=b.getButtonDigital(d.fastSpeed);q!==c.fastSpeed&&(h.controlStateChanged(t.FAST_SPEED,q),c.fastSpeed=q);var r=b.getButtonDigital(d.slowSpeed);r!==c.slowSpeed&&(h.controlStateChanged(t.SLOW_SPEED,r),c.slowSpeed=r)},g=function(){return{direction:-1,button:!1,buttonT:!1,select:!1,reset:!1,fastSpeed:!1,pause:!1,xPosition:-1}};this.getModeDesc=function(){switch(u){case-1:return"AUTO";case 0:return"AUTO (swapped)";default:return r?"DISABLED":"NOT SUPPORTED"}},this.applyPreferences=function(){var a=w?1:0,b=a?0:1;n=y.joystickGamepads[a],n.player=x^w?1:0,o=y.joystickGamepads[b],o.player=x^w?0:1,p=y.joystickKeys[a],q=y.joystickKeys[b]};var h,i,j,k,l,m,n,o,p,q,r=!1,s=-1,t=jt.ConsoleControls,u=-1,v=!1,w=!1,x=!1,y=Javatari.userPreferences.current},jt.DOMTouchControls=function(a){"use strict";function b(){v.classList.toggle("jt-poweroff",!I),v.classList.toggle("jt-paused",J)}function c(){var a=z>0;document.documentElement.classList.toggle("jt-touch-active",a),document.documentElement.classList.toggle("jt-dir-big",B),s.touchControlsActiveUpdate(a,B)}function d(a){if(jt.Util.blockEvent(a),null===D){void 0===t&&i();var b=a.changedTouches[0];D=b.identifier,g(b.pageX,b.pageY)}}function e(a){jt.Util.blockEvent(a),null!==D&&(D=null,h(-1))}function f(a){if(jt.Util.blockEvent(a),null!==D)for(var b=a.changedTouches,c=0;cF&&(c=(1-Math.atan2(d,e)/Math.PI)/2,c+=1/16,c>=1&&(c-=1),c=8*c|0),h(c)}function h(b){if(E!==b){b>=0&&a.hapticFeedback();var c=!1,d=!1,e=!1,f=!1;switch(b){case 0:c=!0;break;case 1:c=d=!0;break;case 2:d=!0;break;case 3:e=d=!0;break;case 4:e=!0;break;case 5:e=f=!0;break;case 6:f=!0;break;case 7:c=f=!0}a.processKey(w.up.c,c),a.processKey(w.right.c,d),a.processKey(w.down.c,e),a.processKey(w.left.c,f),E=b}}function i(){var a=C.getBoundingClientRect();F=.14*(a.right-a.left)|0,t=((a.left+a.right)/2|0)+window.pageXOffset,u=((a.top+a.bottom)/2|0)+window.pageYOffset}function j(a){jt.Util.blockEvent(a),l(a.target.jtControl,!0)}function k(a){jt.Util.blockEvent(a),l(a.target.jtControl,!1)}function l(b,c){b&&(c&&a.hapticFeedback(),a.processKey(w[b].c,c))}function m(b){jt.Util.blockEvent(b),a.hapticFeedback(),r.controlStateChanged(I?jt.ConsoleControls.PAUSE:jt.ConsoleControls.POWER,!0)}function n(b){jt.Util.blockEvent(b),a.hapticFeedback(),r.controlStateChanged(J?jt.ConsoleControls.FRAME:jt.ConsoleControls.FAST_SPEED,!0)}function o(b){jt.Util.blockEvent(b),J||(a.hapticFeedback(),r.controlStateChanged(J?jt.ConsoleControls.FRAME:jt.ConsoleControls.FAST_SPEED,!1))}function p(){H.reset(),t=u=void 0,D=null,h(-1)}function q(){this.reset=function(){this.portValue=63},this.reset()}this.connect=function(a){r=a},this.connectScreen=function(a){s=a},this.powerOn=function(){this.applyPreferences(),p(),c()},this.powerOff=function(){},this.releaseControllers=function(){p()},this.updateConsolePanelSize=function(a,b,c,d,e){if(v&&d){var f=!e&&(a-b-10)/22&&(z=0),p(),this.applyPreferences(),c(),void s.showOSD("Touch Controls "+this.getModeDesc(),!0)):void s.showOSD("Touch Controls unavailable. Not a touch device!",!0,!0)},this.setP1ControlsMode=function(a){A=a,this.applyPreferences()},this.getModeDesc=function(){switch(z){case-1:return"AUTO";case 0:return"DISABLED";case 1:return"ENABLED";case 2:return"ENABLED (swapped)"}},this.toggleTouchDirBig=function(){B=!B,K.touch.directionalBig=B,Javatari.userPreferences.setDirty(),c()},this.isDirBig=function(){return B},this.setupTouchControlsIfNeeded=function(a){function c(){function a(a){var c=document.createElement("div");c.classList.add("jt-touch-dir-"+a),b.appendChild(c);var d=document.createElement("div");d.classList.add("jt-arrow-"+a),b.appendChild(d)}var b=document.createElement("div");return b.classList.add("jt-touch-dir"),b.classList.add("jt-touch-dir-joy"),a("left"),a("right"),a("up"),a("down"),b}function g(a,b){var c=document.createElement("div");c.id="jt-touch-"+b,c.classList.add("jt-touch-button"),c.classList.add("jt-touch-button-joy"),c.classList.add("jt-touch-button-joy-"+b),c.jtControl=b,c.addEventListener("touchstart",j),c.addEventListener("touchmove",jt.Util.blockEvent),c.addEventListener("touchend",k),c.addEventListener("touchcancel",k),c.addEventListener("mousedown",j),c.addEventListener("mouseup",k),G[b]=c,a.appendChild(c)}if(!(C||z<=0)){v=document.createElement("div"),v.id="jt-touch-speed";var h=document.createElement("div");h.id="jt-touch-pause",h.addEventListener("touchstart",m),v.appendChild(h);var i=document.createElement("div");i.id="jt-touch-fast",i.addEventListener("touchstart",n),i.addEventListener("touchend",o),v.appendChild(i),a.appendChild(v);var l=document.createElement("div");l.id="jt-touch-left",C=c(),C.addEventListener("touchstart",d),C.addEventListener("touchmove",f),C.addEventListener("touchend",e),C.addEventListener("touchcancel",e),l.appendChild(C),a.appendChild(l),l=document.createElement("div"),l.id="jt-touch-right",g(l,"buttonT"),g(l,"button"),a.appendChild(l),b()}},this.consolePowerAndUserPauseStateUpdate=function(a,c){I=a,J=c,v&&b()},this.applyPreferences=function(){B=!!K.touch.directionalBig;var a=2===z?1:0;w=K.joystickKeys[a]};var r,s,t,u,v,w,x=jt.Util.isTouchDevice(),y=jt.Util.isMobileDevice(),z=Javatari.TOUCH_MODE>=0?Javatari.TOUCH_MODE:x&&y?1:0,A=!1,B=!1,C=null,D=null,E=-1,F=0,G={},H=new q,I=!1,J=!1,K=Javatari.userPreferences.current,L=84;this.saveState=function(){return{}},this.loadState=function(a){p()}},jt.DOMConsoleControls=function(a){"use strict";function b(){l=new jt.GamepadConsoleControls(g),m=new jt.DOMTouchControls(g),g.applyPreferences()}function c(a){B=a,C=B?60/F[B]|0:0,E=C/2|0,D=0}function d(a,b){a.returnValue=!1,a.preventDefault(),a.stopPropagation();var c=jt.DOMKeys.codeForKeyboardEvent(a);return g.processKey(c,b),!1}function e(a,b){y&&(a=o(a),p(a,b))||b!==u[a]&&(h.controlStateChanged(a,b),u[a]=b)}function f(){i.controlsModeStateUpdate()}var g=this;this.connect=function(a){h=a,h.connectControls(this),l.connect(a),m.connect(a)},this.connectPeripherals=function(a){i=a,l.connectScreen(a),m.connectScreen(a)},this.addKeyInputElement=function(a){a.addEventListener("keydown",this.keyDown), a.addEventListener("keyup",this.keyUp)},this.setupTouchControlsIfNeeded=function(a){m.setupTouchControlsIfNeeded(a)},this.powerOn=function(){n(),l.powerOn(),m.powerOn(),0===O?q(!1,!1):1===O&&q(!0,!1)},this.powerOff=function(){q(!1,!1),l.powerOff(),m.powerOff()},this.releaseControllers=function(){for(var a in u)u[a]&&(h.controlStateChanged(0|a,!1),u[a]=!1);I=J=M=N=!1,v[t.JOY0_BUTTON]=v[t.JOY1_BUTTON]=!1,m.releaseControllers()},this.getTouchControls=function(){return m},this.toggleP1ControlsMode=function(){this.setP1ControlsMode(!x),r(),f()},this.setP1ControlsMode=function(a){x=a,l.setP1ControlsMode(a),m.setP1ControlsMode(a),this.releaseControllers(),s()},this.isP1ControlsMode=function(){return x},this.togglePaddleMode=function(){q(!y,!0),f()},this.isPaddleMode=function(){return y},this.toggleGamepadMode=function(){l.toggleMode(),f()},this.getGamepadModeDesc=function(){return l.getModeDesc()},this.toggleTouchControlsMode=function(){m.toggleMode(),f()},this.toggleTouchDirBig=function(){m.toggleTouchDirBig()},this.toggleTurboFireSpeed=function(){c((B+1)%11),i.showOSD("Turbo Fire"+(B?" speed: "+this.getTurboFireSpeedDesc():": OFF"),!0),w.turboFireSpeed=B,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save()},this.getTurboFireSpeedDesc=function(){return B?B+"x":"OFF"},this.getControlReport=function(a){switch(a){case jt.PeripheralControls.PADDLES_TOGGLE_MODE:return{label:y?"ON":"OFF",active:y};case jt.PeripheralControls.TOUCH_TOGGLE_DIR_BIG:return{label:m.isDirBig()?"ON":"OFF",active:m.isDirBig()};case jt.PeripheralControls.HAPTIC_FEEDBACK_TOGGLE_MODE:return{label:A?"ON":"OFF",active:!!A};case jt.PeripheralControls.TURBO_FIRE_TOGGLE:return{label:this.getTurboFireSpeedDesc(),active:!!B}}return{label:"Unknown",active:!1}},this.consolePowerAndUserPauseStateUpdate=function(a,b){m.consolePowerAndUserPauseStateUpdate(a,b)},this.keyDown=function(a){return d(a,!0)},this.keyUp=function(a){return d(a,!1)},this.controlsClockPulse=function(){if(C){if(--D,D===E||0===D){var a=D>0;v[t.JOY0_BUTTON]&&e(t.JOY0_BUTTON,a),v[t.JOY1_BUTTON]&&e(t.JOY1_BUTTON,a)}D<=0&&(D=C)}l.controlsClockPulse(),y&&(J?I||(G-=H,G<0&&(G=0),h.controlValueChanged(t.PADDLE0_POSITION,G)):I&&(G+=H,G>380&&(G=380),h.controlValueChanged(t.PADDLE0_POSITION,G)),N?M||(K-=L,K<0&&(K=0),h.controlValueChanged(t.PADDLE1_POSITION,K)):M&&(K+=L,K>380&&(K=380),h.controlValueChanged(t.PADDLE1_POSITION,K)))},this.toggleHapticFeedback=function(){z?(A=!A,w.hapticFeedback=A,Javatari.userPreferences.setDirty()):i.showOSD("Haptic Feedback not available",!0,!0)},this.hapticFeedback=function(){A&&navigator.vibrate(8)},this.hapticFeedbackOnTouch=function(a){!A||"touchstart"!==a.type&&"touchend"!==a.type&&"touchmove"!==a.type||navigator.vibrate(8)},this.cartridgeInserted=function(a){if(a&&!(O>=0)){var b=1===a.rom.info.p;y!==b&&q(b,!1)}},this.processKey=function(b,c){var d=k[b];if(d){if(c===v[d])return;c&&(D=E),v[d]=c}else if(d=j[b],!d)return a.processKey(b,c);e(d,c)},this.applyPreferences=function(){s(),c(w.turboFireSpeed),m.applyPreferences(),l.applyPreferences()};var h,i,j,k,l,m,n=function(){window.onhelp=function(){return!1}},o=function(a){switch(a){case t.JOY0_BUTTON:return t.PADDLE0_BUTTON;case t.JOY1_BUTTON:return t.PADDLE1_BUTTON;default:return a}},p=function(a,b){if(b)switch(a){case t.JOY0_LEFT:return I=!0,!0;case t.JOY0_RIGHT:return J=!0,!0;case t.JOY0_UP:return H<10&&H++,i.showOSD("P1 Paddle speed: "+H,!0),!0;case t.JOY0_DOWN:return H>1&&H--,i.showOSD("P1 Paddle speed: "+H,!0),!0;case t.JOY1_LEFT:return M=!0,!0;case t.JOY1_RIGHT:return N=!0,!0;case t.JOY1_UP:return L<10&&L++,i.showOSD("P2 Paddle speed: "+L,!0),!0;case t.JOY1_DOWN:return L>1&&L--,i.showOSD("P2 Paddle speed: "+L,!0),!0}else switch(a){case t.JOY0_LEFT:return I=!1,!0;case t.JOY0_RIGHT:return J=!1,!0;case t.JOY1_LEFT:return M=!1,!0;case t.JOY1_RIGHT:return N=!1,!0}return!1},q=function(a,b){y!==a&&g.releaseControllers(),y=a,H=L=2,G=K=y?190:-1,h.controlValueChanged(t.PADDLE0_POSITION,G),h.controlValueChanged(t.PADDLE1_POSITION,K),l.setPaddleMode(y),b&&r()},r=function(){i.showOSD("Controllers: "+(y?"Paddles":"Joysticks")+(x?", Swapped":""),!0)},s=function(){var a=jt.DOMKeys;j={},k={},j[P]=t.POWER,j[P|a.ALT]=t.POWER,j[P|a.SHIFT]=t.POWER_FRY,j[P|a.SHIFT|a.ALT]=t.POWER_FRY,j[Q]=t.BLACK_WHITE,j[Q|a.ALT]=t.BLACK_WHITE,j[R]=t.SELECT,j[R|a.ALT]=t.SELECT,j[S]=t.RESET,j[S|a.ALT]=t.RESET,j[T]=t.DIFFICULTY0,j[T|a.ALT]=t.DIFFICULTY0,j[U]=t.DIFFICULTY1,j[U|a.ALT]=t.DIFFICULTY1,j[V]=t.FAST_SPEED,j[V|a.ALT]=t.FAST_SPEED,j[V|a.SHIFT]=t.SLOW_SPEED,j[V|a.SHIFT|a.ALT]=t.SLOW_SPEED,j[W|a.SHIFT|a.ALT]=t.INC_SPEED,j[X|a.SHIFT|a.ALT]=t.DEC_SPEED,j[Y|a.SHIFT|a.ALT]=t.NORMAL_SPEED,j[Z|a.SHIFT|a.ALT]=t.MIN_SPEED,j[$|a.ALT]=t.PAUSE,j[$|a.SHIFT|a.ALT]=t.PAUSE_AUDIO_ON,j[_|a.ALT]=t.FRAME,j[aa|a.ALT]=t.FRAME,j[ca|a.ALT]=t.TRACE,j[da|a.ALT]=t.SHOW_INFO,j[ba|a.ALT]=t.DEBUG,j[ea|a.ALT]=t.NO_COLLISIONS,j[fa|a.ALT]=t.VIDEO_STANDARD,j[ga|a.ALT]=t.VIDEO_STANDARD,j[ha|a.ALT]=t.VSYNCH,j[ia|a.CONTROL]=t.SAVE_STATE_0,j[ja|a.CONTROL]=t.SAVE_STATE_0,j[ia|a.CONTROL|a.ALT]=t.SAVE_STATE_0,j[ja|a.CONTROL|a.ALT]=t.SAVE_STATE_0,j[ka|a.CONTROL]=t.SAVE_STATE_1,j[ka|a.CONTROL|a.ALT]=t.SAVE_STATE_1,j[la|a.CONTROL]=t.SAVE_STATE_2,j[la|a.CONTROL|a.ALT]=t.SAVE_STATE_2,j[ma|a.CONTROL]=t.SAVE_STATE_3,j[ma|a.CONTROL|a.ALT]=t.SAVE_STATE_3,j[na|a.CONTROL]=t.SAVE_STATE_4,j[na|a.CONTROL|a.ALT]=t.SAVE_STATE_4,j[oa|a.CONTROL]=t.SAVE_STATE_5,j[oa|a.CONTROL|a.ALT]=t.SAVE_STATE_5,j[pa|a.CONTROL]=t.SAVE_STATE_6,j[pa|a.CONTROL|a.ALT]=t.SAVE_STATE_6,j[qa|a.CONTROL]=t.SAVE_STATE_7,j[qa|a.CONTROL|a.ALT]=t.SAVE_STATE_7,j[ra|a.CONTROL]=t.SAVE_STATE_8,j[ra|a.CONTROL|a.ALT]=t.SAVE_STATE_8,j[sa|a.CONTROL]=t.SAVE_STATE_9,j[sa|a.CONTROL|a.ALT]=t.SAVE_STATE_9,j[ta|a.CONTROL]=t.SAVE_STATE_10,j[ta|a.CONTROL|a.ALT]=t.SAVE_STATE_10,j[ua|a.CONTROL]=t.SAVE_STATE_11,j[va|a.CONTROL]=t.SAVE_STATE_11,j[ua|a.CONTROL|a.ALT]=t.SAVE_STATE_11,j[va|a.CONTROL|a.ALT]=t.SAVE_STATE_11,j[wa|a.CONTROL]=t.SAVE_STATE_12,j[xa|a.CONTROL]=t.SAVE_STATE_12,j[wa|a.CONTROL|a.ALT]=t.SAVE_STATE_12,j[xa|a.CONTROL|a.ALT]=t.SAVE_STATE_12,j[ia|a.ALT]=t.LOAD_STATE_0,j[ja|a.ALT]=t.LOAD_STATE_0,j[ka|a.ALT]=t.LOAD_STATE_1,j[la|a.ALT]=t.LOAD_STATE_2,j[ma|a.ALT]=t.LOAD_STATE_3,j[na|a.ALT]=t.LOAD_STATE_4,j[oa|a.ALT]=t.LOAD_STATE_5,j[pa|a.ALT]=t.LOAD_STATE_6,j[qa|a.ALT]=t.LOAD_STATE_7,j[ra|a.ALT]=t.LOAD_STATE_8,j[sa|a.ALT]=t.LOAD_STATE_9,j[ta|a.ALT]=t.LOAD_STATE_10,j[ua|a.ALT]=t.LOAD_STATE_11,j[va|a.ALT]=t.LOAD_STATE_11,j[wa|a.ALT]=t.LOAD_STATE_12,j[xa|a.ALT]=t.LOAD_STATE_12;var b=x?1:0,c=x?0:1;j[w.joystickKeys[b].left.c]=t.JOY0_LEFT,j[w.joystickKeys[b].up.c]=t.JOY0_UP,j[w.joystickKeys[b].right.c]=t.JOY0_RIGHT,j[w.joystickKeys[b].down.c]=t.JOY0_DOWN,j[w.joystickKeys[b].button.c]=t.JOY0_BUTTON,j[w.joystickKeys[c].left.c]=t.JOY1_LEFT,j[w.joystickKeys[c].up.c]=t.JOY1_UP,j[w.joystickKeys[c].right.c]=t.JOY1_RIGHT,j[w.joystickKeys[c].down.c]=t.JOY1_DOWN,j[w.joystickKeys[c].button.c]=t.JOY1_BUTTON,k[w.joystickKeys[b].buttonT.c]=t.JOY0_BUTTON,k[w.joystickKeys[c].buttonT.c]=t.JOY1_BUTTON},t=jt.ConsoleControls,u={},v={},w=Javatari.userPreferences.current,x=!1,y=!1,z=!!navigator.vibrate,A=z&&!!w.hapticFeedback,B=0,C=0,D=0,E=0,F=[0,1,2,2.4,3,4,5,6,7.5,10,12],G=0,H=3,I=!1,J=!1,K=0,L=3,M=!1,N=!1,O=Javatari.PADDLES_MODE,P=jt.DOMKeys.VK_F1.c,Q=jt.DOMKeys.VK_F2.c,R=jt.DOMKeys.VK_F11.c,S=jt.DOMKeys.VK_F12.c,T=jt.DOMKeys.VK_F4.c,U=jt.DOMKeys.VK_F9.c,V=jt.DOMKeys.VK_TAB.c,W=jt.DOMKeys.VK_UP.c,X=jt.DOMKeys.VK_DOWN.c,Y=jt.DOMKeys.VK_RIGHT.c,Z=jt.DOMKeys.VK_LEFT.c,$=jt.DOMKeys.VK_P.c,_=jt.DOMKeys.VK_O.c,aa=jt.DOMKeys.VK_F.c,ba=jt.DOMKeys.VK_D.c,ca=jt.DOMKeys.VK_VOID,da=jt.DOMKeys.VK_I.c,ea=jt.DOMKeys.VK_C.c,fa=jt.DOMKeys.VK_V.c,ga=jt.DOMKeys.VK_Q.c,ha=jt.DOMKeys.VK_W.c,ia=jt.DOMKeys.VK_QUOTE.c,ja=jt.DOMKeys.VK_BACKQUOTE.c,ka=jt.DOMKeys.VK_1.c,la=jt.DOMKeys.VK_2.c,ma=jt.DOMKeys.VK_3.c,na=jt.DOMKeys.VK_4.c,oa=jt.DOMKeys.VK_5.c,pa=jt.DOMKeys.VK_6.c,qa=jt.DOMKeys.VK_7.c,ra=jt.DOMKeys.VK_8.c,sa=jt.DOMKeys.VK_9.c,ta=jt.DOMKeys.VK_0.c,ua=jt.DOMKeys.VK_MINUS.c,va=jt.DOMKeys.VK_FF_MINUS.c,wa=jt.DOMKeys.VK_EQUALS.c,xa=jt.DOMKeys.VK_FF_EQUALS.c; b(),jt.DOMConsoleControls.hapticFeedback=this.hapticFeedback,jt.DOMConsoleControls.hapticFeedbackOnTouch=this.hapticFeedbackOnTouch},jt.ScreenGUI=jt.Util.isMobileDevice()?{BAR_HEIGHT:29,BAR_MENU_WIDTH:150,BAR_MENU_ITEM_HEIGHT:33,BAR_MENU_ITEM_FONT_SIZE:14,LOGO_SCREEN_WIDTH:618,LOGO_SCREEN_HEIGHT:455,TOUCH_CONTROLS_LEFT_WIDTH:119,TOUCH_CONTROLS_LEFT_WIDTH_BIG:143,TOUCH_CONTROLS_RIGHT_WIDTH:80}:{BAR_HEIGHT:29,BAR_MENU_WIDTH:140,BAR_MENU_ITEM_HEIGHT:29,BAR_MENU_ITEM_FONT_SIZE:13,LOGO_SCREEN_WIDTH:618,LOGO_SCREEN_HEIGHT:455,TOUCH_CONTROLS_LEFT_WIDTH:119,TOUCH_CONTROLS_LEFT_WIDTH_BIG:143,TOUCH_CONTROLS_RIGHT_WIDTH:80},jt.ScreenGUI.html=function(){return'
Swipe up/down on the Screen
to hide the browser bars!
'},jt.ScreenGUI.htmlConsolePanel='
',jt.ScreenGUI.css=function(){return"html.jt-full-screen-scroll-hack body { position: absolute; width: 100%; height: "+Math.max(1280,1.4*Math.max(screen.width,screen.height)|0)+"px; top: 0; left: 0; margin: 0; padding: 0; border: none; overflow-x: hidden; overflow-y: auto; } #jt-screen-fs, #jt-screen-fs div, #jt-screen-fs canvas { outline: none; } #"+Javatari.SCREEN_ELEMENT_ID+" { display: inline-block; visibility: hidden; font-family: sans-serif; font-weight: normal; margin: 0; padding: 0; border: 1px solid black; background: black; overflow: visible; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; touch-callout: none; -webkit-tap-highlight-color: transparent; tap-highlight-color: transparent; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; } html.jt-full-screen #"+Javatari.SCREEN_ELEMENT_ID+" { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; box-shadow: none; z-index: 2147483646; /* one behind fsElement */ } html.jt-started #"+Javatari.SCREEN_ELEMENT_ID+" { visibility: visible; } #jt-screen-scroll-message { position: absolute; bottom: 150%; left: 50%; height: 0; width: 0; margin: 0; padding: 0; font-size: 16px; line-height: 28px; white-space: nowrap; color: hsl(0, 0%, 4%); background: hsl(0, 0%, 92%); border-radius: 15px; transform: translate(-50%, 0); box-shadow: 2px 2px 9px rgba(0, 0, 0, 0.7); transition: all 1.7s step-end, opacity 1.6s linear; overflow: hidden; opacity: 0; z-index: -1; } html.jt-full-screen-scroll-hack #jt-screen-fs.jt-scroll-message #jt-screen-scroll-message { opacity: 1; bottom: 23%; width: 215px; height: 56px; padding: 13px 20px; z-index: 60; transition: none; } #jt-screen-fs { position: relative; background: black; text-align: center; -webkit-tap-highlight-color: rgba(0,0,0,0); tap-highlight-color: rgba(0,0,0,0) } html.jt-full-screen #jt-screen-fs { position: absolute; width: 100%; height: 100%; left: 0; bottom: 0; right: 0; z-index: 2147483647; } html.jt-full-screen-scroll-hack #jt-screen-fs { position: fixed; bottom: 0; height: 100vh; } html.jt-full-screen #jt-screen-fs-center { /* Used to center and move things horizontally in Landscape Full Screen */ position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #jt-screen-canvas-outer { display: inline-block; position: relative; overflow: hidden; vertical-align: top; line-height: 1px; z-index: 3; } #jt-screen-canvas { display: block; } #jt-bar { position: relative; left: 0; right: 0; height: "+this.BAR_HEIGHT+'px; margin: 0 auto; border-top: 1px solid black; background: hsl(0, 0%, 16%); overflow: visible; /* for the Menu to show through */ box-sizing: content-box; z-index: 40; } #jt-bar-inner { position: absolute; overflow: hidden; top: 0; bottom: 0; left: 0; right: 0; text-align: left; } html.jt-bar-auto-hide #jt-bar, html.jt-full-screen #jt-bar { position: absolute; bottom: 0; transition: height 0.08s ease-in-out; } html.jt-bar-auto-hide #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } @media only screen and (orientation: landscape) { html.jt-full-screen #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } } #jt-bar.jt-narrow .jt-narrow-hidden { display: none; } .jt-bar-button { display: inline-block; width: 24px; height: 28px; margin: 0 1px; background-image: url("'+jt.Images.urls.iconSprites+'"); background-repeat: no-repeat; background-size: 264px 82px; cursor: pointer; } /* .jt-bar-button { border: 1px solid yellow; background-origin: border-box; box-sizing: border-box; } */ #jt-bar-power { margin: 0 8px 0 6px; } #jt-bar-select { margin: 0 2px; width: 50px; } #jt-bar-reset { margin: 0 2px; width: 50px; } html.jt-console-panel-active #jt-bar-select, html.jt-console-panel-active #jt-bar-reset { display: none; } #jt-bar-settings, #jt-bar-full-screen, #jt-bar-scale-plus, #jt-bar-scale-minus { float: right; margin: 0; } #jt-bar-settings { margin-right: 5px; } #jt-bar-full-screen.jt-mobile { margin: 0 6px; } #jt-bar-scale-plus { width: 21px; } #jt-bar-scale-minus { width: 18px; } #jt-bar-text { float: right; width: 32px; } #jt-bar-text.jt-mobile { margin: 0 0 0 6px; } #jt-bar-console-panel { position: absolute; left: 2px; right: 0; width: 39px; margin: 0 auto; } #jt-bar.jt-narrow #jt-bar-console-panel { position: static; float: right; margin-right: 3px; } #jt-bar-logo { position: absolute; left: 0; right: 0; width: 34px; margin: 0 auto; } html:not(.jt-console-panel-active) #jt-bar.jt-narrow #jt-bar-logo { display: none; } #jt-bar-menu { position: absolute; display: none; bottom: '+this.BAR_HEIGHT+"px; font-size: "+this.BAR_MENU_ITEM_FONT_SIZE+"px; line-height: 1px; overflow: hidden; transform-origin: bottom center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-bar-menu-inner { display: inline-block; padding-bottom: 2px; border: 1px solid black; background: hsl(0, 0%, 16%); } .jt-bar-menu-item, #jt-bar-menu-title { position: relative; display: none; width: "+this.BAR_MENU_WIDTH+"px; height: "+this.BAR_MENU_ITEM_HEIGHT+"px; color: rgb(205, 205, 205); border: none; padding: 0; line-height: "+this.BAR_MENU_ITEM_HEIGHT+'px; text-shadow: 1px 1px 1px black; background: transparent; outline: none; overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden; cursor: pointer; box-sizing: border-box; } #jt-bar-menu-title { display: block; color: white; font-weight: bold; border-bottom: 1px solid black; margin-bottom: 1px; text-align: center; background: rgb(70, 70, 70); cursor: auto; } .jt-bar-menu-item.jt-hover:not(.jt-bar-menu-item-disabled):not(.jt-bar-menu-item-divider) { color: white; background: hsl(358, 67%, 46%); } .jt-bar-menu-item-disabled { color: rgb(110, 110, 110); } .jt-bar-menu-item-divider { height: 1px; margin: 1px 0; background: black; } .jt-bar-menu-item-toggle { text-align: left; padding-left: 30px; } .jt-bar-menu-item-toggle::after { content: ""; position: absolute; width: 6px; height: 19px; top: '+((this.BAR_MENU_ITEM_HEIGHT-21)/2|0)+"px; left: 10px; background: rgb(70, 70, 70); box-shadow: black 1px 1px 1px; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked { color: white; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked::after { background: rgb(248, 33, 28); } #jt-console-panel { display: none; position: absolute; bottom: -"+(jt.ConsolePanel.DEFAULT_HEIGHT+2)+"px; left: 50%; transform: translate(-50%, 0); transform-origin: center top; margin: 0 auto; border: 1px solid black; z-index: 30; } html.jt-console-panel-active #jt-console-panel { display: block; } html.jt-full-screen #jt-console-panel { bottom: "+(jt.ScreenGUI.BAR_HEIGHT+2)+'px; border: none; transform-origin: center bottom; } #jt-screen-fs .jt-select-dialog { position: absolute; overflow: hidden; display: none; top: 0; bottom: 0; left: 0; right: 0; width: 540px; max-width: 92%; height: 297px; margin: auto; color: white; font-size: 18px; line-height: 21px; background: hsl(0, 0%, 16%); padding: 11px 0 0; text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-screen-fs .jt-select-dialog.jt-show { display: block; } #jt-screen-fs .jt-select-dialog .jt-footer { position: absolute; width: 100%; bottom: 7px; font-size: 13px; text-align: center; color: rgb(170, 170, 170); } #jt-screen-fs .jt-select-dialog ul { position: relative; width: 88%; top: 5px; margin: auto; padding: 0; list-style: none; font-size: 14px; color: hsl(0, 0%, 88%); } #jt-screen-fs .jt-select-dialog li { display: none; position: relative; overflow: hidden; height: 26px; background: rgb(70, 70, 70); margin: 7px 0; padding: 11px 10px 0 18px; /* Space on the left for the toggle mark for all lines */ line-height: 0; text-align: left; text-overflow: ellipsis; border: 2px dashed transparent; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); white-space: nowrap; box-sizing: border-box; cursor: pointer; } #jt-screen-fs .jt-select-dialog li.jt-visible { display: block; } #jt-screen-fs .jt-select-dialog li.jt-selected { color: white; background: hsl(358, 67%, 46%); } #jt-screen-fs .jt-select-dialog li.jt-droptarget { color: white; border-color: lightgray; } #jt-screen-fs .jt-select-dialog li.jt-toggle::after { content: ""; position: absolute; width: 6px; height: 17px; top: 2px; left: 6px; background: rgb(60, 60, 60); box-shadow: black 1px 1px 1px; } #jt-screen-fs .jt-select-dialog li.jt-toggle-checked::after { background: rgb(248, 33, 28); } #jt-logo { position: absolute; display: none; top: 0; bottom: 0; left: 0; right: 0; background: black; } #jt-logo.jt-show { display: block; } #jt-logo-center { position: absolute; top: 50%; left: 50%; width: 598px; height: 456px; transform: translate(-50%, -50%); } #jt-logo-image { position: absolute; top: 50%; left: 50%; width: 335px; max-width: 57%; transform: translate(-50%, -50%); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-image { top: 128px; width: 37%; max-width: initial; } #jt-logo-loading-icon, #jt-canvas-loading-icon { display: none; position: absolute; top: 79%; left: 0; right: 0; width: 14%; height: 3%; margin: 0 auto; background-color: rgba(0, 0, 0, .8); border: solid transparent; border-width: 8px 30px; border-radius: 3px; box-sizing: content-box; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-loading-icon { top: 204px; } #jt-logo-message { display: none; position: absolute; top: 226px; width: 100%; color: hsl(0, 0%, 97%); font-size: 29px; line-height: 34px; } #jt-screen-fs.jt-logo-message-active #jt-logo-message { display: block; } #jt-logo-message-ok { display: block; position: absolute; top: 91px; left: 193px; width: 214px; height: 130px; } #jt-logo-message-ok.jt-higher { top: 74px; } #jt-logo-message-ok-text { position: absolute; top: 49%; left: 50%; width: 120px; height: 47px; font-size: 23px; line-height: 47px; background: hsl(358, 67%, 46%); border-radius: 6px; color: white; transform: translate(-50%, -50%); } #jt-osd { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: -29px; right: 16px; height: 29px; padding: 0 12px; margin: 0; font-weight: bold; font-size: 15px; line-height: 29px; color: rgb(0, 255, 0); background: rgba(0, 0, 0, 0.7); transform-origin: top right; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; opacity: 0; } .jt-arrow-up, .jt-arrow-down, .jt-arrow-left, .jt-arrow-right { border: 0px solid transparent; box-sizing: border-box; } .jt-arrow-up { border-bottom-color: inherit; } .jt-arrow-down { border-top-color: inherit; } .jt-arrow-left { border-right-color: inherit; } .jt-arrow-right { border-left-color: inherit; } .jt-quick-options-list { margin-top: 12px; padding: 0; list-style: none; color: hsl(0, 0%, 88%); } .jt-quick-options-list li { margin-top: 8px; line-height: 1px; text-align: left; } .jt-quick-options-list li div { display: inline-block; overflow: hidden; height: 26px; font-size: 14px; line-height: 26px; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; } .jt-quick-options-list .jt-control { float: right; width: 86px; font-size: 15px; line-height: 25px; color: hsl(0, 0%, 70%); background: black; text-align: center; cursor: pointer; } .jt-quick-options-list .jt-control.jt-selected { color: white; background: hsl(358, 67%, 46%); box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); } .jt-quick-options-list .jt-control.jt-selected.jt-inactive { line-height: 21px; border: 2px dashed hsl(358, 67%, 46%); background: black; } #jt-quick-options { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 233px; height: 310px; margin: auto; padding: 11px 14px 0; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-quick-options.jt-show { display: block; } #jt-quick-options::before { content: "Quick Options"; display: block; } #jt-touch-left, #jt-touch-right, #jt-touch-speed { display: none; position: absolute; z-index: 1; } html.jt-full-screen.jt-touch-active #jt-touch-left, html.jt-full-screen.jt-touch-active #jt-touch-right, html.jt-full-screen.jt-touch-active #jt-touch-speed { display: block; } .jt-touch-dir { width: 130px; height: 130px; color: hsl(0, 0%, 75%); border-radius: 100%; } .jt-touch-dir::before { content: ""; position: absolute; top: 14px; left: 14px; right: 14px; bottom: 14px; border: 1px solid hsl(0, 0%, 26%); border-radius: 100%; } .jt-touch-dir-joy .jt-touch-dir-up, .jt-touch-dir-joy .jt-touch-dir-left { position: absolute; background: hsl(0, 0%, 31%); border-radius: 2px 2px 0 0; box-shadow: inset 1px 2px 0px hsl(0, 0%, 43%), inset -1px -1px hsl(0, 0%, 19%), 0 3px 0 1px hsl(0, 0%, 21%); } .jt-touch-dir-joy .jt-touch-dir-up { width: 26px; height: 78px; top: 24px; left: 52px; } .jt-touch-dir-joy .jt-touch-dir-left { width: 78px; height: 25px; top: 51px; left: 26px; } .jt-touch-dir-joy .jt-touch-dir-left::before { content: ""; position: absolute; top: 2px; left: 23px; width: 33px; height: 22px; background: inherit; z-index: 1; } .jt-touch-dir-joy .jt-touch-dir-left::after { content: ""; position: absolute; top: 4px; left: 30px; height: 17px; width: 17px; border-radius: 100%; box-shadow: inset 0 0 2px hsl(0, 0%, 22%), inset 1px 2px 3px 1px hsl(0, 0%, 26%), inset -1px -2px 1px hsl(0, 0%, 64%); z-index: 2; } .jt-touch-dir .jt-arrow-up, .jt-touch-dir .jt-arrow-down, .jt-touch-dir .jt-arrow-left, .jt-touch-dir .jt-arrow-right { position: absolute; border-width: 5px; z-index: 2; } .jt-touch-dir .jt-arrow-up { top: 26px; left: 60px; border-bottom-width: 11px; } .jt-touch-dir .jt-arrow-down { bottom: 29px; left: 60px; border-top-width: 11px; } .jt-touch-dir .jt-arrow-left { top: 58px; left: 26px; border-right-width: 11px; } .jt-touch-dir .jt-arrow-right { top: 58px; right: 26px; border-left-width: 11px; } .jt-touch-button { position: relative; display: block; width: 72px; height: 72px; font-size: 20px; line-height: 67px; color: hsl(0, 0%, 79%); border-radius: 100%; cursor: default; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; z-index: 0; } .jt-touch-button::before { content: ""; position: absolute; box-sizing: border-box; z-index: -1; } .jt-touch-button-joy::before, .jt-touch-button-none::before { width: 50px; height: 48px; top: 9px; left: 11px; border-radius: 100%; } #jt-screen-fs.jt-touch-config-active .jt-touch-button-none::before { border: 2px solid hsl(0, 0%, 30%); } .jt-touch-button-joy.jt-touch-button-joy-button::before { border: none; background: hsl(1, 70%, 37%); box-shadow: inset -2px -7px 3px 1px hsl(1, 68%, 43%), inset 0px 0px 1px 9px hsl(1, 72%, 33%), 0px -1px 0px 1px hsl(1, 70%, 47%), 0px 1px 0px 2px hsl(1, 70%, 29%); } .jt-touch-button-joy.jt-touch-button-joy-buttonT::before { border: none; background: hsl(220, 72%, 39%); box-shadow: inset -2px -7px 3px 1px hsl(220, 70%, 43%), inset 0px 0px 1px 9px hsl(220, 75%, 34%), 0px -1px 0px 1px hsl(220, 72%, 50%), 0px 1px 0px 2px hsl(220, 72%, 28%); } #jt-touch-button { z-index: 7 } #jt-touch-buttonT { z-index: 6 } #jt-touch-speed.jt-center { width: 84px; left: 0; right: 0; margin: 0 auto; } #jt-touch-speed.jt-center.jt-poweroff #jt-touch-pause { margin-left: 21px } #jt-touch-pause, #jt-touch-fast { float: left; width: 42px; height: 42px; border-color: hsl(0, 0%, 70%); } #jt-touch-pause::after, #jt-touch-fast::before, #jt-touch-fast::after { content: ""; display: inline-block; border: 0 solid transparent; box-sizing: border-box; } #jt-touch-pause::after { margin-top: 14px; width: 13px; height: 14px; border-width: 0; border-left-width: 4px; border-left-color: inherit; border-right-width: 4px; border-right-color: inherit; } #jt-touch-fast::before, #jt-touch-fast::after { margin-top: 14px; width: 11px; height: 14px; border-width: 7px; border-left-width: 11px; border-left-color: inherit; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-pause::after, #jt-touch-speed.jt-poweroff #jt-touch-pause::after { margin: 12px 0 0 3px; width: 15px; height: 18x; border-width: 9px; border-left-width: 15px; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-fast::after { width: 7px; border-width: 0; border-left-width: 3px; } #jt-touch-speed.jt-poweroff #jt-touch-fast { display: none; } .jt-console-panel { width:'+jt.ConsolePanel.DEFAULT_WIDTH+"px; height:"+jt.ConsolePanel.DEFAULT_HEIGHT+'px; background: black url("'+jt.Images.urls.panel+'") no-repeat; background-size: 460px 134px; box-shadow: '+jt.ConsolePanel.sameBoxShadowAsScreen()+'; outline: none; } html.jt-full-screen .jt-console-panel { box-shadow: none; } .jt-console-panel-icon { position: absolute; background: url("'+jt.Images.urls.iconSprites+'") center no-repeat; background-size: 264px 82px; } .jt-console-panel-switch { position: absolute; bottom: 107px; width: 50px; height: 26px; opacity: 0; cursor: pointer; } .jt-console-panel-switch:after { content: ""; position: absolute; left: 11px; bottom: 5px; width: 27px; height: 16px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; } .jt-console-panel-lever { position: absolute; bottom: 30px; width: 44px; height: 72px; cursor: pointer; } .jt-console-panel-lever:after { content: ""; position: absolute; left: 12px; bottom: 8px; width: 20px; height: 46px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; } .jt-console-panel-power { left: 19px; } .jt-console-panel-power:after { background-position: 0px 0px; } .jt-console-panel-color { left: 84px; } .jt-console-panel-color:after { background-position: -21px 0px; } .jt-console-panel-select { left: 340px; } .jt-console-panel-select:after { background-position: 0px -47px; } .jt-console-panel-reset { left: 403px; } .jt-console-panel-reset:after { background-position: -21px -47px; } .jt-console-panel-p0-diff { left: 152px; } .jt-console-panel-p0-diff:after { background-position: -229px -17px; } .jt-console-panel-p1-diff { left: 265px; } .jt-console-panel-p1-diff:after { background-position: -229px 0px; } .jt-console-panel-cart-image { position: absolute; left: 140px; bottom: 9px; width: 186px; height: 82px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; background-position: -42px 0px; } .jt-console-panel-cart-load { position: absolute; left: 141px; bottom: 36px; width: 184px; height: 55px; cursor: pointer; } .jt-console-panel-cart-file { left: 170px; bottom: 3px; width: 31px; height: 30px; background-position: -132px -6px; cursor: pointer; } .jt-console-panel-cart-url { left: 266px; bottom: 3px; width: 31px; height: 30px; background-position: -161px -6px; cursor: pointer; } .jt-console-panel-cart-label { position: absolute; top: 51px; left: 156px; width: 148px; height: 25px; padding: 0px 2px; margin: 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: normal; font-variant: normal; font-weight: bold; font-stretch: normal; font-size: 14px; line-height: 25px; font-family: sans-serif; text-align: center; color: black; background: black; border: 1px solid transparent; opacity: 1; cursor: pointer; } .jt-console-panel-power-labels { left: 31px; bottom: 9px; width: 88px; height: 15px; background-position: -135px -37px; } .jt-console-panel-reset-labels { right: 16px; bottom: 9px; width: 96px; height: 15px; background-position: -135px -55px; } .jt-console-panel-p0-diff-label { left: 128px; top: 8px; width: 29px; height: 15px; background-position: -233px -37px; } .jt-console-panel-p1-diff-label { left: 313px; top: 8px; width: 28px; height: 15px; background-position: -233px -55px; } .jt-hide-labels .jt-console-panel-p0-diff-label, .jt-hide-labels .jt-console-panel-p1-diff-label, .jt-hide-labels .jt-console-panel-power-labels, .jt-hide-labels .jt-console-panel-reset-labels, .jt-hide-labels .jt-console-panel-cart-file, .jt-hide-labels .jt-console-panel-cart-url { visibility: hidden; } @media only screen and (orientation: landscape) { /* Landscape */ #jt-touch-left { left: calc(-6px - '+this.TOUCH_CONTROLS_LEFT_WIDTH+"px); bottom: 50%; transform: translateY(50%); } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { left: calc(-6px - "+this.TOUCH_CONTROLS_LEFT_WIDTH_BIG+"px); transform: translateY(50%) scale(1.2); transform-origin: left center; } #jt-touch-right { right: calc(5px - "+this.TOUCH_CONTROLS_RIGHT_WIDTH+"px); bottom: 50%; transform: translateY(50%); } #jt-touch-speed { position: absolute; left: -103px; top: 10px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-speed { left: -118px; } /* Adjust centered elements leaving space to the touch controls on both sides */ html.jt-full-screen.jt-touch-active #jt-screen-fs-center { left: "+this.TOUCH_CONTROLS_LEFT_WIDTH+"px; right: "+this.TOUCH_CONTROLS_RIGHT_WIDTH+"px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-screen-fs-center { left: "+this.TOUCH_CONTROLS_LEFT_WIDTH_BIG+"px; } } @media only screen and (orientation: portrait) { /* Portrait */ #jt-touch-left { left: 2px; bottom: 200px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { transform: scale(1.2); transform-origin: left center; } #jt-touch-right { right: 5px; bottom: 144px; width: 112px; height: 112px; } #jt-touch-speed { position: absolute; left: 19px; bottom: "+(this.BAR_HEIGHT+12)+"px; } .jt-touch-button { position: absolute; } #jt-touch-button { bottom: 50%; right: 50%; } #jt-touch-buttonT { bottom: 100%; right: 0%; } } @media only screen and (orientation: portrait) and (max-device-height: 638px) { /* Medium Portrait. Like iPhone 5 */ #jt-touch-left { bottom: 156px; } #jt-touch-right { bottom: 100px; } } @media only screen and (orientation: portrait) and (max-device-height: 518px) { /* Short Portrait. Like iPhone 4 */ #jt-touch-left { bottom: 98px; } #jt-touch-right { bottom: 42px; } html.jt-console-panel-active #jt-touch-left { bottom: 106px; } html.jt-console-panel-active #jt-touch-right { bottom: 52px; } html.jt-full-screen.jt-console-panel-active #jt-touch-speed { display: none; } } "; },jt.Monitor=function(a){"use strict";function b(){n(),m(),e.setVideoStandard(H)}function c(a){var b=a<.5?.5:a>2.5?2.5:a;return Math.round(10*b)/10}function d(a){var b=a<.5?.5:a;return Math.round(10*b)/10}var e=this;this.connect=function(a){s=a,s.connectMonitor(this)},this.nextLine=function(a,b){var c=!1;return I=B&&Iw&&f()};this.setVideoStandard=function(a){H=a,t=a.totalWidth,u=a.totalHeight,v=u-R,w=u+R+S,K&&(z=H.defaultHeightPct,C=H.defaultOriginYPct),k(x,z),j(A,C)};var h=function(){var a=L;L=0,(a>=250&&a<=281||a>=300&&a<=325)&&++G>=5&&i(a)},i=function(a){F=a<290?jt.VideoStandard.NTSC:jt.VideoStandard.PAL;var b=M,c=a-F.totalHeight;c=c>2?(c>6?6:c)-2:0,c!=b&&(M=c,e.setVideoStandard(F))};this.videoSignalOff=function(){I=0,a.videoSignalOff()};var j=function(a,b){A=a,A<0?A=0:A>t-x&&(A=t-x),C=b,C<0?C=0:C/100*u>u-y&&(C=(u-y)/u*100);var c=M/2;B=C/100*u+c|0,B+y>u&&(B=u-y)},k=function(a,b){x=a,x<10?x=10:x>t&&(x=t),z=b,z<10?z=10:z>100&&(z=100),y=z/100*(u+M)|0,y>u&&(y=u),o.width=x,o.height=y,j(A,C),l()},l=function(){a&&a.displayMetrics(x,y)},m=function(){K=!0,A=Q,C=H.defaultOriginYPct,k(O,H.defaultHeightPct)},n=function(){o=document.createElement("canvas"),o.width=O,o.height=P,p=o.getContext("2d",{alpha:!1,antialias:!1}),p.globalCompositeOperation="copy",p.globalAlpha=1,q=p.createImageData(jt.VideoStandard.PAL.totalWidth,jt.VideoStandard.PAL.totalHeight),r=new Uint32Array(q.data.buffer)};this.currentLine=function(){return I},this.refresh=function(){p.putImageData(q,-A,0,A,0,x,y),a.refresh(o,x,y)},this.videoStandardDetectionStart=function(){F=null,G=0,L=0},this.getVideoStandardDetected=function(){return F},this.toggleShowInfo=function(){N=!N,N||a.showOSD(null,!0)},this.signalOff=function(){a.videoSignalOff()},this.showOSD=function(b,c,d){a.showOSD(b,c,d)},this.setDefaults=function(){m(),a.crtModeSetDefault(),a.crtFilterSetDefault(),a.requestReadjust(!0)},this.setDebugMode=function(b){a.setDebugMode(b)},this.crtModeToggle=function(){a.crtModeToggle()},this.crtFilterToggle=function(){a.crtFilterToggle()},this.fullscreenToggle=function(){a.displayToggleFullscreen()},this.displayAspectDecrease=function(){this.displayScale(c(D-T),E),this.showOSD("Display Aspect: "+D.toFixed(2)+"x",!0)},this.displayAspectIncrease=function(){this.displayScale(c(D+T),E),this.showOSD("Display Aspect: "+D.toFixed(2)+"x",!0)},this.displayScaleDecrease=function(){this.displayScale(D,d(E-T)),this.showOSD("Display Size: "+E.toFixed(2)+"x",!0)},this.displayScaleIncrease=function(){this.displayScale(D,d(E+T)),this.showOSD("Display Size: "+E.toFixed(2)+"x",!0)},this.viewportOriginDecrease=function(){K=!1,j(A,C+U),this.showOSD("Viewport Origin: "+B,!0)},this.viewportOriginIncrease=function(){K=!1,j(A,C-U),this.showOSD("Viewport Origin: "+B,!0)},this.viewportSizeDecrease=function(){m(),this.showOSD("Viewport Size: Standard",!0)},this.viewportSizeIncrease=function(){K=!1,k(t,100),this.showOSD("Viewport Size: Full Signal",!0)},this.displayScale=function(b,c){D=b,E=c,a.displayScale(D,E)},this.controlStateChanged=function(b,c){a.controlStateChanged(b,c)},this.controlsStatesRedefined=function(){a.controlsStatesRedefined()},this.consolePowerAndUserPauseStateUpdate=function(b,c){a.consolePowerAndUserPauseStateUpdate(b,c)},this.cartridgeInserted=function(b){a.cartridgeInserted(b)};var o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H=jt.VideoStandard.NTSC,I=0,J=0,K=!0,L=0,M=0,N=!1,O=160,P=213,Q=68,R=16,S=5,T=.1,U=.4;b()},jt.ConsolePanel=function(a,b){"use strict";function c(){k(),l(),p()}function d(b){jt.Util.blockEvent(b),I||(r.hapticFeedbackOnTouch(b),a.closeAllOverlays(),b.target.jtPressed=!0,t.controlStateChanged(b.target.jtControl,!0))}function e(a){jt.Util.blockEvent(a),a.target.jtPressed=!1,I||(r.hapticFeedbackOnTouch(a),t.controlStateChanged(a.target.jtControl,!1))}function f(a){a.target.jtPressed&&e(a)}function g(b){r.hapticFeedbackOnTouch(b),a.closeAllOverlays(),s.controlActivated(b.target.jtControl)}this.connectPeripherals=function(a,c,d){r=c,s=d,a.registerForDnD(b)},this.connect=function(a){t=a},this.setActive=function(a){G=a,G&&(v||c(),i(),j()),document.documentElement.classList.toggle("jt-console-panel-active",G)},this.setLogoMessageActive=function(a){I=a},this.updateScale=function(a,c,d){var e=0,f=0;if(G){a=c?d?.85*a:a-36:.85*a;var g=Math.min(1,a/jt.ConsolePanel.DEFAULT_WIDTH);b.style.transform=g<1?"translateX(-50%) scale("+g.toFixed(8)+")":"translateX(-50%)",e=Math.ceil(g*jt.ConsolePanel.DEFAULT_HEIGHT),f=Math.ceil(g*jt.ConsolePanel.DEFAULT_WIDTH)}return r&&r.getTouchControls().updateConsolePanelSize(a,f,e,c,d),e};var h=function(){o(v,!H[q.POWER]),o(w,H[q.BLACK_WHITE]),o(x,H[q.SELECT]),o(y,H[q.RESET]),o(z,H[q.DIFFICULTY0]),o(A,H[q.DIFFICULTY1]),i()},i=function(){if(o(B,u),o(F,u),F.innerHTML=u&&u.rom.info.l||K,u&&u.rom.info.lc){var a=u.rom.info.lc.trim().split(/\s+/);F.style.color=a[0]||L,F.style.background=a[1]||M,F.style.borderColor=a[2]||N}else F.style.color=L,F.style.background=M,F.style.borderColor=N},j=function(){t.controlsStateReport(H),h()},k=function(){b.innerHTML=jt.ScreenGUI.htmlConsolePanel,delete jt.ScreenGUI.htmlConsolePanel,jt.Util.isMobileDevice()&&b.classList.add("jt-hide-labels")},l=function(){v=document.getElementById("jt-console-panel-power"),m(v,q.POWER,!1),w=document.getElementById("jt-console-panel-color"),m(w,q.BLACK_WHITE,!1),x=document.getElementById("jt-console-panel-select"),m(x,q.SELECT,!0),y=document.getElementById("jt-console-panel-reset"),m(y,q.RESET,!0),z=document.getElementById("jt-console-panel-p0-diff"),m(z,q.DIFFICULTY0,!1),A=document.getElementById("jt-console-panel-p1-diff"),m(A,q.DIFFICULTY1,!1),B=document.getElementById("jt-console-panel-cart-image"),C=document.getElementById("jt-console-panel-cart-load"),n(C,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT),Javatari.CARTRIDGE_CHANGE_DISABLED||(D=document.getElementById("jt-console-panel-cart-file"),n(D,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT),o(D,!0),E=document.getElementById("jt-console-panel-cart-url"),n(E,jt.PeripheralControls.AUTO_LOAD_URL),o(E,!0))},m=function(a,b,c){a.jtControl=b,c?(a.jtPressed=!1,jt.Util.addEventsListener(a,"mousedown touchstart",d),jt.Util.addEventsListener(a,"mouseup touchend touchcancel",e),jt.Util.addEventsListener(a,"mouseleave",f)):jt.Util.onTapOrMouseDown(a,d)},n=function(a,b){a.jtControl=b,a.jtNeedsUIG=!0,jt.Util.onTapOrMouseDownWithBlockUIG(a,g)},o=function(a,b){a.style.opacity=b?1:0},p=function(){var a=(Javatari.CARTRIDGE_LABEL_COLORS||"").trim().split(/\s+/);a[0]&&(L=a[0]),a[1]&&(M=a[1]),a[2]&&(N=a[2]),F=document.getElementById("jt-console-panel-cart-label"),n(F,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT)},q=jt.ConsoleControls;this.controlStateChanged=function(a,b){G&&J[a]&&j()},this.controlsStatesRedefined=function(){G&&j()},this.cartridgeInserted=function(a){u=a,G&&i()};var r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=!1,H={},I=!1,J={};J[q.POWER]=1,J[q.BLACK_WHITE]=1,J[q.SELECT]=1,J[q.RESET]=1,J[q.DIFFICULTY0]=1,J[q.DIFFICULTY1]=1;var K="JAVATARI",L="#fa2525",M="#101010",N="transparent"},jt.ConsolePanel.DEFAULT_WIDTH=460,jt.ConsolePanel.DEFAULT_HEIGHT=134,jt.ConsolePanel.shouldStartActive=function(){return!Javatari.SCREEN_CONSOLE_PANEL_DISABLED&&(Javatari.CONSOLE_PANEL_ELEMENT_ID===-1||document.getElementById(Javatari.CONSOLE_PANEL_ELEMENT_ID))},jt.ConsolePanel.sameBoxShadowAsScreen=function(){var a=document.getElementById(Javatari.SCREEN_ELEMENT_ID);return a?window.getComputedStyle(a,null).getPropertyValue("box-shadow"):"none"},jt.CanvasDisplay=function(mainElement){"use strict";function init(){jt.Util.insertCSS(jt.ScreenGUI.css()),delete jt.ScreenGUI.css,setupMain(),setupBar(),setupFullscreen(),consolePanel=new jt.ConsolePanel(self,consolePanelElement),monitor=new jt.Monitor(self)}function consolePanelUpdateForOrientation(){ setConsolePanelActive(isFullscreen&&isLandscape?consolePanelActiveLandscape:consolePanelActivePortrait)}function setConsolePanelActive(a){consolePanelActive!==a&&(consolePanelActive=a,consolePanel.setActive(consolePanelActive),updateScale(),consolePanelActive?showBar():cursorHideFrameCountdown=CURSOR_HIDE_FRAMES)}function hideOSD(){osd.style.transition="all 0.15s linear",osd.style.top="-29px",osd.style.opacity=0,osdShowing=!1}function releaseControllersOnLostFocus(){consoleControlsSocket.releaseControllers()}function hideCursorAndBar(){hideCursor(),hideBar(),cursorHideFrameCountdown=-1}function showCursorAndBar(a){showCursor(),!a&&mousePointerLocked||showBar(),cursorHideFrameCountdown=CURSOR_HIDE_FRAMES}function showCursor(){cursorShowing||(fsElement.style.cursor=cursorType,cursorShowing=!0)}function hideCursor(){cursorShowing&&(fsElement.style.cursor="none",cursorShowing=!1)}function fullscreenByAPIChanged(){var a=isFullscreen,b=isFullScreenByAPI();b||fullScreenAPIExitUserRequested||!isBrowserStandalone?setFullscreenState(b):self.requestReadjust(),a&&!b&&!fullScreenAPIExitUserRequested&&isMobileDevice&&(isBrowserStandalone?setEnterFullscreenByAPIOnFirstTouch():(atariConsole.systemPause(!0),showLogoMessage("
Emulation suspended","RESUME",!0,function(){self.setFullscreen(!0),atariConsole.systemPause(!1)}))),fullScreenAPIExitUserRequested=!1}function isFullScreenByAPI(){return!!document[fullScreenAPIQueryProp]}function enterFullScreenByAPI(){if(fullscreenAPIEnterMethod)try{fullscreenAPIEnterMethod.call(fsElement)}catch(a){}}function exitFullScreenByAPI(){if(fullScreenAPIExitMethod)try{fullScreenAPIExitUserRequested=!0,fullScreenAPIExitMethod.call(document)}catch(a){}}function updateScale(){var a=Math.round(targetWidth*scaleY*aspectX*2),b=Math.round(targetHeight*scaleY);canvas.style.width=""+a+"px",canvas.style.height=""+b+"px",updateBarWidth(a),signalIsOn||updateLogoScale(),settingsDialog&&settingsDialog.isVisible()&&settingsDialog.position(),updateConsolePanelScale(a)}function updateBarWidth(a){var b=buttonsBarDesiredWidth>0?buttonsBarDesiredWidth:a;buttonsBar.style.width=buttonsBarDesiredWidth===-1?"100%":""+b+"px",buttonsBar.classList.toggle("jt-narrow",b0?""+Math.ceil(b+3)+"px":"initial"}function updateCanvasContentSize(){var a=crtFilterEffective>0?CANVAS_SIZE_FACTOR:1;canvas.width=targetWidth*a,canvas.height=targetHeight*a,canvasContext=null}function setCRTFilter(a){crtFilter=a,crtFilterEffective=crtFilter===-2?null:crtFilter===-1?crtFilterAutoValue():a,updateCanvasContentSize()}function crtFilterAutoValue(){return isMobileDevice&&!isIOSDevice&&"FIREFOX"===browserName?0:1}function setCRTMode(a){crtMode=a,crtModeEffective=crtMode===-1?crtModeAutoValue():crtMode,canvasContext=null}function crtModeAutoValue(){return 0}function updateLogo(){signalIsOn||(updateLogoScale(),showCursorAndBar(!0),canvasContext&&canvasContext.clearRect(0,0,canvas.width,canvas.height)),logo.classList.toggle("jt-show",!signalIsOn)}function updateLoading(){var a=isLoading?"block":"none";logoLoadingIcon.style.display=a,canvasLoadingIcon.style.display=a}function createCanvasContext(){canvasContext=canvas.getContext("2d",{alpha:!1,antialias:!1}),setImageComposition(),setImageSmoothing()}function setImageComposition(){crtModeEffective>0&&!debugMode?(canvasContext.globalCompositeOperation="source-over",canvasContext.globalAlpha=.8):(canvasContext.globalCompositeOperation="copy",canvasContext.globalAlpha=1)}function setImageSmoothing(){if(canvas.style.imageRendering=0===crtFilterEffective||2===crtFilterEffective?canvasImageRenderingValue:"initial",null!==crtFilterEffective){var a=crtFilterEffective>=2;void 0!==canvasContext.imageSmoothingEnabled?canvasContext.imageSmoothingEnabled=a:(canvasContext.webkitImageSmoothingEnabled=a,canvasContext.mozImageSmoothingEnabled=a,canvasContext.msImageSmoothingEnabled=a)}}function suppressContextMenu(a){a.addEventListener("contextmenu",jt.Util.blockEvent)}function preventDrag(a){a.ondragstart=jt.Util.blockEvent}function setupMain(){switch(mainElement.innerHTML=jt.ScreenGUI.html(),mainElement.tabIndex=-1,delete jt.ScreenGUI.html,fsElement=document.getElementById("jt-screen-fs"),fsElementCenter=document.getElementById("jt-screen-fs-center"),canvasOuter=document.getElementById("jt-screen-canvas-outer"),canvas=document.getElementById("jt-screen-canvas"),canvasLoadingIcon=document.getElementById("jt-canvas-loading-icon"),osd=document.getElementById("jt-osd"),logo=document.getElementById("jt-logo"),logoCenter=document.getElementById("jt-logo-center"),logoImage=document.getElementById("jt-logo-image"),logoLoadingIcon=document.getElementById("jt-logo-loading-icon"),logoMessage=document.getElementById("jt-logo-message"),logoMessageText=document.getElementById("jt-logo-message-text"),logoMessageOK=document.getElementById("jt-logo-message-ok"),logoMessageOKText=document.getElementById("jt-logo-message-ok-text"),scrollMessage=document.getElementById("jt-screen-scroll-message"),consolePanelElement=document.getElementById("jt-console-panel"),suppressContextMenu(mainElement),preventDrag(logoImage),preventDrag(logoLoadingIcon),preventDrag(canvasLoadingIcon),updateCanvasContentSize(),browserName){case"CHROME":case"EDGE":case"OPERA":canvasImageRenderingValue="pixelated";break;case"FIREFOX":canvasImageRenderingValue="-moz-crisp-edges";break;case"SAFARI":canvasImageRenderingValue="-webkit-optimize-contrast";break;default:canvasImageRenderingValue="pixelated"}setupMainEvents()}function setupMainEvents(){(isMobileDevice?canvasOuter:fsElement).addEventListener("mousemove",function(){showCursorAndBar()}),"onblur"in document?fsElement.addEventListener("blur",releaseControllersOnLostFocus,!0):fsElement.addEventListener("focusout",releaseControllersOnLostFocus,!0),window.addEventListener("orientationchange",function(){closeAllOverlays(),signalIsOn?hideCursorAndBar():showCursorAndBar(),self.requestReadjust()}),mainElement.addEventListener("drop",closeAllOverlays,!0),logoMessageOK.jtNeedsUIG=logoMessageOKText.jtNeedsUIG=!0,jt.Util.onTapOrMouseDownWithBlockUIG(logoMessageOK,function(a){consoleControls.hapticFeedbackOnTouch(a),self.closeLogoMessage()}),jt.Util.addEventsListener(fsElementCenter,"touchstart touchend mousedown",function(a){"touchend"!==a.type?(closeAllOverlays(),showCursorAndBar()):a.cancelable&&a.preventDefault()})}function setupBar(){buttonsBar=document.getElementById("jt-bar"),buttonsBarInner=document.getElementById("jt-bar-inner"),BAR_AUTO_HIDE&&(document.documentElement.classList.add("jt-bar-auto-hide"),fsElement.addEventListener("mouseleave",hideBar),hideBar());var a=[{label:"Power",clickModif:0,control:jt.PeripheralControls.MACHINE_POWER_TOGGLE},{label:"Fry Console",control:jt.PeripheralControls.MACHINE_POWER_FRY},{label:"",divider:!0},{label:"Select Cartridge",control:jt.PeripheralControls.CARTRIDGE_LOAD_RECENT},{label:"",divider:!0},{label:"Open File",clickModif:KEY_CTRL_MASK,control:jt.PeripheralControls.AUTO_LOAD_FILE,needsUIG:!0},{label:"Open URL",clickModif:KEY_CTRL_MASK|KEY_ALT_MASK,control:jt.PeripheralControls.AUTO_LOAD_URL,needsUIG:!0},{label:"",divider:!0},{label:"Load State",control:jt.PeripheralControls.MACHINE_LOAD_STATE_MENU},{label:"Save State",control:jt.PeripheralControls.MACHINE_SAVE_STATE_MENU}];powerButton=addBarButton("jt-bar-power",-5,-26,"System Power",null,!1,a,"System"),barMenuSystem=a,self.consolePowerAndUserPauseStateUpdate(!1,!1),isMobileDevice?settingsButton=addBarButton("jt-bar-settings",-33,-26,"Quick Options",jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS,!1):(a=[{label:"Help & Settings",clickModif:0,control:jt.PeripheralControls.SCREEN_OPEN_SETTINGS},{label:"Quick Options",control:jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS},{label:"Defaults",control:jt.PeripheralControls.SCREEN_DEFAULTS }],settingsButton=addBarButton("jt-bar-settings",-33,-26,"Settings",null,!1,a,"Settings")),gameSelectButton=addBarButton("jt-bar-select",-78,-51,"Game Select",jt.ConsoleControls.SELECT,!0),gameResetButton=addBarButton("jt-bar-reset",-33,-51,"Game Reset",jt.ConsoleControls.RESET,!0),FULLSCREEN_MODE!==-2&&(fullscreenButton=addBarButton("jt-bar-full-screen",-103,-1,"Full Screen",jt.PeripheralControls.SCREEN_FULLSCREEN,!1),fullscreenButton.jtNeedsUIG=!0,isMobileDevice&&fullscreenButton.classList.add("jt-mobile")),Javatari.SCREEN_RESIZE_DISABLED||isMobileDevice||(scaleUpButton=addBarButton("jt-bar-scale-plus",-80,-1,"Increase Screen",jt.PeripheralControls.SCREEN_SCALE_PLUS,!1),scaleUpButton.classList.add("jt-full-screen-hidden"),scaleDownButton=addBarButton("jt-bar-scale-minus",-58,-1,"Decrease Screen",jt.PeripheralControls.SCREEN_SCALE_MINUS,!1),scaleDownButton.classList.add("jt-full-screen-hidden"));var b=addBarButton("jt-bar-console-panel",-61,-25,"Toggle Console Panel",jt.PeripheralControls.SCREEN_CONSOLE_PANEL_TOGGLE,!1);b.classList.add("jt-full-screen-only"),logoButton=addBarButton("jt-bar-logo",-99,-26,"About Javatari",jt.PeripheralControls.SCREEN_OPEN_ABOUT,!1),logoButton.classList.add("jt-full-screen-hidden"),jt.Util.onTapOrMouseDownWithBlockUIG(buttonsBar,barElementTapOrMouseDown),jt.Util.addEventsListener(buttonsBar,"touchmove",barElementTouchMove),jt.Util.addEventsListener(buttonsBar,"mouseup touchend",barElementTouchEndOrMouseUp)}function addBarButton(a,b,c,d,e,f,g,h){var i=document.createElement("div");return i.id=a,i.classList.add("jt-bar-button"),i.jtBarElementType=1,i.jtControl=e,i.jtIsConsoleControl=f,i.style.backgroundPosition=""+b+"px "+c+"px",i.jtBX=b,g&&(i.jtMenu=g,g.jtTitle=h,g.jtRefElement=i,g.jtMenuIndex=barMenus.length,barMenus.push(g)),d&&(i.title=d),i.addEventListener("mouseenter",function(a){barButtonHoverOver(a.target,a)}),f&&i.addEventListener("mouseleave",barButtonMouseLeft),buttonsBarInner.appendChild(i),i}function barButtonTapOrMousedown(a,b){if(!logoMessageActive){consoleControls.hapticFeedbackOnTouch(b);var c=barMenuActive;if(closeAllOverlays(),a.jtControl)return void(b.button||(a.jtIsConsoleControl?(barConsoleControlPressed=a.jtControl,consoleControlsSocket.controlStateChanged(barConsoleControlPressed,!0)):peripheralControls.controlActivated(a.jtControl)));var d=a.jtMenu;if(d){var e=0|(b.altKey&&KEY_ALT_MASK)|(b.ctrlKey&&KEY_CTRL_MASK)|(b.shiftKey&&KEY_SHIFT_MASK);if(0===e&&!b.button)return void(c!==d&&(showBarMenu(d),"touchstart"===b.type&&barButtonLongTouchStart(b)));for(var f=0;f1||barMenuItemFireActive(a.shiftKey,1===a.button||a.ctrlKey))}function barMenuItemTapOrMouseDown(a,b){barMenuItemSetActive(a,"touchstart"===b.type)}function barMenuItemHoverOver(a,b){barMenuItemSetActive(a,"touchmove"===b.type)}function barMenuItemHoverOut(){barMenuItemSetActive(null)}function barMenuItemTouchEndOrMouseUp(a){logoMessageActive||!barMenuItemActive||a.button>1||barMenuItemFireActive(a.shiftKey,1===a.button||a.ctrlKey)}function barMenuItemFireActive(a,b){var c=barMenuItemActive.jtMenuOption;barMenuItemSetActive(null),c&&!c.disabled&&(c.extension?extensionsSocket.toggleExtension(c.extension,b,a):c.control&&(a|=c.secSlot,closeAllOverlays(),peripheralControls.controlActivated(c.control,b,a)))}function barMenuItemSetActive(a,b){a!==barMenuItemActive&&(barMenuItemActive&&barMenuItemActive.classList.remove("jt-hover"),a&&a.jtMenuOption?(barMenuItemActive=a,b&&consoleControls.hapticFeedback(),barMenuItemActive.classList.add("jt-hover")):barMenuItemActive=null)}function barElementTapOrMouseDown(a){cursorHideFrameCountdown=CURSOR_HIDE_FRAMES;var b=a.target;1===b.jtBarElementType?barButtonTapOrMousedown(b,a):2===b.jtBarElementType?barMenuItemTapOrMouseDown(b,a):hideBarMenu()}function barElementTouchMove(a){jt.Util.blockEvent(a);var b=a.changedTouches[0],c=b&&document.elementFromPoint(b.clientX,b.clientY);barButtonLongTouchTarget&&c!==barButtonLongTouchTarget&&barButtonLongTouchCancel(),2!==c.jtBarElementType&&c!==barButtonLongTouchTarget&&barMenuItemSetActive(null),1===c.jtBarElementType?barButtonHoverOver(c,a):2===c.jtBarElementType&&barMenuItemHoverOver(c,a)}function barElementTouchEndOrMouseUp(a){cursorHideFrameCountdown=CURSOR_HIDE_FRAMES,jt.Util.blockEvent(a),barButtonLongTouchCancel();var b=a.target;1===b.jtBarElementType?barButtonTouchEndOrMouseUp(a):2===b.jtBarElementType&&barMenuItemTouchEndOrMouseUp(a)}function setupFullscreen(){fullscreenAPIEnterMethod=fsElement.requestFullscreen||fsElement.webkitRequestFullscreen||fsElement.webkitRequestFullScreen||fsElement.mozRequestFullScreen,fullScreenAPIExitMethod=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen,"fullscreenElement"in document?fullScreenAPIQueryProp="fullscreenElement":"webkitFullscreenElement"in document?fullScreenAPIQueryProp="webkitFullscreenElement":"mozFullScreenElement"in document&&(fullScreenAPIQueryProp="mozFullScreenElement"),fullscreenAPIEnterMethod||!isMobileDevice||isBrowserStandalone||(fullScreenScrollHack=!0),"onfullscreenchange"in document?document.addEventListener("fullscreenchange",fullscreenByAPIChanged):"onwebkitfullscreenchange"in document?document.addEventListener("webkitfullscreenchange",fullscreenByAPIChanged):"onmozfullscreenchange"in document&&document.addEventListener("mozfullscreenchange",fullscreenByAPIChanged),fullscreenAPIEnterMethod||(scrollMessage.jtScroll=canvas.jtScroll=logo.jtScroll=logoCenter.jtScroll=logoImage.jtScroll=logoMessage.jtScroll=logoMessageText.jtScroll=logoMessageOK.jtScroll=logoMessageOKText.jtScroll=!0,fsElement.addEventListener("touchmove",function(a){if(isFullscreen){if(!fullScreenScrollHack||!a.target.jtScroll)return jt.Util.blockEvent(a);scrollMessageActive&&setScrollMessage(!1)}}))}function setEnterFullscreenByAPIOnFirstTouch(){if(fullscreenAPIEnterMethod){var a=!1,b=function(){a||(a=!0,jt.Util.removeEventsListener(fsElement,"touchend mousedown",b,!0),enterFullScreenByAPI())};jt.Util.addEventsListener(fsElement,"touchend mousedown",b,!0)}}function setFullscreenState(a){isFullscreen=a,a?(setViewport(),document.documentElement.classList.add("jt-full-screen"),fullScreenScrollHack&&document.documentElement.classList.add("jt-full-screen-scroll-hack"),consoleControls.setupTouchControlsIfNeeded(fsElementCenter),fullScreenScrollHack&&setScrollMessage(!0),fullscreenAPIEnterMethod||tryToFixSafariBugOnFullScreenChange()):(restoreViewport(),document.documentElement.classList.remove("jt-full-screen"),fullScreenScrollHack&&document.documentElement.classList.remove("jt-full-screen-scroll-hack"), fullscreenAPIEnterMethod||tryToFixSafariBugOnFullScreenChange()),self.requestReadjust()}function tryToFixSafariBugOnFullScreenChange(){var a=document.getElementById("jt-dummy-element");a?mainElement.removeChild(a):(a=document.createElement("div"),a.id="jt-dummy-element",mainElement.appendChild(a))}function showBar(){buttonsBar.classList.remove("jt-hidden")}function hideBar(){!BAR_AUTO_HIDE&&!isFullscreen||barMenuActive||consolePanelActive||barConsoleControlPressed||(hideBarMenu(),buttonsBar.classList.add("jt-hidden"))}function showBarMenu(a,b){if(a&&barMenuActive!==a){if(!barMenu)return setupBarMenu(),void setTimeout(function(){showBarMenu(a,b)},1);refreshBarMenu(a),barMenuItemSetActive(b?barMenu.jtDefaultItem:null);var c=a.jtRefElement,d=c&&c.offsetLeft-15||0;d+jt.ScreenGUI.BAR_MENU_WIDTH>c.parentElement.clientWidth?(barMenu.style.right=0,barMenu.style.left="auto",barMenu.style.transformOrigin="bottom right"):(d<0&&(d=0),barMenu.style.left=""+d+"px",barMenu.style.right="auto",barMenu.style.transformOrigin="bottom left"),showCursorAndBar(!0),barMenuActive=a,barMenu.style.display="inline-block",barMenu.jtTitle.focus()}}function refreshBarMenu(a){barMenu.jtTitle.innerHTML=a.jtTitle,barMenu.jtDefaultItem=null;for(var b,c=0,d=Math.min(a.length,BAR_MENU_MAX_ITEMS),e=jt.ScreenGUI.BAR_MENU_ITEM_HEIGHT+3,f=0;f=0&&!c[d].jtMenuOption);e>=0&&barMenuItemSetActive(c[d])}return jt.Util.blockEvent(a)}),buttonsBar.appendChild(barMenu)}function closeAllOverlays(){hideBarMenu(),saveStateDialog&&saveStateDialog.hide(),quickOtionsDialog&&quickOtionsDialog.hide(),settingsDialog&&settingsDialog.hide(),recentROMsDialog&&recentROMsDialog.hide()}function showLogoMessage(a,b,c,d){consolePanel.setLogoMessageActive(!0),logoMessageActive||(closeAllOverlays(),d&&(afterMessageAction=d),logoMessageText.innerHTML=a,logoMessageOK.classList.toggle("jt-higher",!!c),logoMessageOKText.innerHTML=b||"OK",fsElement.classList.add("jt-logo-message-active"),logoMessageActive=!0,signalIsOn=!1,updateLogo())}function updateLogoScale(){var a=canvasOuter.clientWidth,b=Math.min(a/jt.ScreenGUI.LOGO_SCREEN_WIDTH,1);b<1?logoCenter.style.transform="translate(-50%, -50%) scale("+b.toFixed(4)+")":logoCenter.style.transform="translate(-50%, -50%)"}function setScrollMessage(a){console.error("Scroll Message: "+a),fsElement.classList.toggle("jt-scroll-message",a),scrollMessageActive=a,a&&setTimeout(function(){setScrollMessage(!1)},5e3)}function readjustAll(a){if(isReadjustScreeSizeChanged(a)){if(isFullscreen){buttonsBarDesiredWidth=isLandscape?0:-1;var b=readjustScreenSize.h;isLandscape||(b-=jt.ScreenGUI.BAR_HEIGHT+2),monitor.displayScale(aspectX,displayOptimalScaleY(readjustScreenSize.w,b))}else buttonsBarDesiredWidth=-1,monitor.displayScale(Javatari.SCREEN_DEFAULT_ASPECT,self.displayDefaultScale());self.focus(),consolePanelUpdateForOrientation(),consoleControlsSocket.releaseControllers()}readjustInterval&&jt.Util.performanceNow()-readjustRequestTime>=1e3&&(clearInterval(readjustInterval),readjustInterval=null)}function isReadjustScreeSizeChanged(a){var b=mainElement.parentElement.clientWidth,c=fsElementCenter.clientWidth,d=fsElementCenter.clientHeight;return!(!a&&readjustScreenSize.pw===b&&readjustScreenSize.w===c&&readjustScreenSize.h===d)&&(readjustScreenSize.pw=b,readjustScreenSize.w=c,readjustScreenSize.h=d,isLandscape=c>d,!0)}function displayOptimalScaleY(a,b){var c=2*aspectX,d=b/targetHeight;return targetWidth*c*d>a&&(d=a/(targetWidth*c)),d}function setViewport(){if(isMobileDevice){if(void 0===viewPortOriginalContent&&(viewPortOriginalTag=document.querySelector("meta[name=viewport]"),viewPortOriginalContent=viewPortOriginalTag&&viewPortOriginalTag.content||null),viewportTag||(viewportTag=document.createElement("meta"),viewportTag.name="viewport",viewportTag.content="width = device-width, height = device-height, initial-scale = 1.0, minimum-scale = 1.0, maximum-scale = 1.0, user-scalable = yes",document.head.appendChild(viewportTag)),viewPortOriginalTag)try{document.head.removeChild(viewPortOriginalTag)}catch(a){}viewPortOriginalTag=null}}function restoreViewport(){if(isMobileDevice){if(!viewPortOriginalTag&&viewPortOriginalContent&&(viewPortOriginalTag=document.createElement("meta"),viewPortOriginalTag.name="viewport",viewPortOriginalTag.content=viewPortOriginalContent,document.head.appendChild(viewPortOriginalTag)),viewportTag)try{document.head.removeChild(viewportTag)}catch(a){}viewportTag=null}}function setPageVisibilityHandling(){function a(){logoMessageActive||(document.hidden?b=!atariConsole.systemPause(!0):b&&atariConsole.systemPause(!1))}var b;document.addEventListener("visibilitychange",a)}var self=this;this.connect=function(a){atariConsole=a,monitor.connect(atariConsole.getVideoOutput()),consoleControlsSocket=atariConsole.getConsoleControlsSocket(),cartridgeSocket=atariConsole.getCartridgeSocket(),consolePanel.connect(consoleControlsSocket)},this.connectPeripherals=function(a,b,c,d,e,f){recentROMs=a,fileLoader=b,b.registerForDnD(fsElement),b.registerForFileInputElement(fsElement),fileDownloader=c,fileDownloader.registerForDownloadElement(fsElement),peripheralControls=e,consoleControls=d,consoleControls.addKeyInputElement(fsElement),stateMedia=f,consolePanel.connectPeripherals(b,consoleControls,peripheralControls)},this.powerOn=function(){monitor.setDefaults(),updateLogo(),document.documentElement.classList.add("jt-started"),setPageVisibilityHandling(), this.focus(),JavatariFullScreenSetup.shouldStartInFullScreen()&&(setFullscreenState(!0),setEnterFullscreenByAPIOnFirstTouch())},this.powerOff=function(){document.documentElement.remove("jt-started")},this.start=function(a){function b(){self.setFullscreen(!0),a()}!isMobileDevice||isBrowserStandalone||isFullscreen?a():jt.Util.isOfficialHomepage()?showLogoMessage("For "+(fullscreenAPIEnterMethod?"the best":"a full-screen")+' experience, use
the "Add to Home Screen" function
then launch from the Installed App',"NICE!",!1,b):showLogoMessage("For the best experience,
Javatari will go full-screen","GO!",!0,b)},this.refresh=function(a,b,c){cursorHideFrameCountdown>0&&--cursorHideFrameCountdown<=0&&hideCursorAndBar(),signalIsOn||(signalIsOn=!0,updateLogo()),canvasContext||createCanvasContext(),canvasContext.drawImage(a,0,0,canvas.width,canvas.height)},this.videoSignalOff=function(){signalIsOn=!1,showCursorAndBar(),updateLogo()},this.mousePointerLocked=function(a){mousePointerLocked=a,mousePointerLocked?hideCursorAndBar():showCursorAndBar()},this.openHelp=function(){return self.openSettings("GENERAL"),!1},this.openAbout=function(){return self.openSettings("ABOUT"),!1},this.openSettings=function(a){closeAllOverlays(),settingsDialog||(settingsDialog=new jt.SettingsDialog(fsElementCenter,consoleControls)),settingsDialog.show(a)},this.openSaveStateDialog=function(a){closeAllOverlays(),saveStateDialog||(saveStateDialog=new jt.SaveStateDialog(fsElementCenter,consoleControlsSocket,peripheralControls,stateMedia)),saveStateDialog.show(a)},this.openQuickOptionsDialog=function(){closeAllOverlays(),quickOtionsDialog||(quickOtionsDialog=new jt.QuickOptionsDialog(fsElementCenter,consoleControlsSocket,peripheralControls)),quickOtionsDialog.show()},this.openLoadFileDialog=function(a,b){fileLoader.openFileChooserDialog(jt.FileLoader.OPEN_TYPE.AUTO,a,b,!1)},this.openRecentROMsDialog=function(){closeAllOverlays(),recentROMsDialog||(recentROMsDialog=new jt.RecentROMsDialog(fsElementCenter,this,recentROMs,fileLoader)),recentROMsDialog.show()},this.openCartridgeChooserDialog=function(a,b,c){logoMessageActive&&self.closeLogoMessage(),a||0!==recentROMs.getCatalog().length?this.openRecentROMsDialog():this.openLoadFileDialog(b,c)},this.toggleConsolePanel=function(){isFullscreen&&isLandscape?consolePanelActiveLandscape=!consolePanelActiveLandscape:consolePanelActivePortrait=!consolePanelActivePortrait,consolePanelUpdateForOrientation()},this.getControlReport=function(a){return{label:crtFilter===-2?"Browser":crtFilter===-1?"Auto":0===crtFilter?"OFF":"Level "+crtFilter,active:crtFilter>=0}},this.toggleMenuByKey=function(){barMenuActive?hideBarMenu():(closeAllOverlays(),showBarMenu(barMenuSystem,!0))},this.getScreenCapture=function(){if(signalIsOn)return canvas.toDataURL("image/png")},this.saveScreenCapture=function(){var a=this.getScreenCapture();a&&fileDownloader.startDownloadURL("Javatari Screen",a,"Screen Capture")},this.displayMetrics=function(a,b){targetWidth===a&&targetHeight===b||(targetWidth=a,targetHeight=b,updateCanvasContentSize(),isFullscreen?this.requestReadjust(!0):updateScale())},this.displayScale=function(a,b){aspectX=a,scaleY=b,updateScale()},this.getMonitor=function(){return monitor},this.showOSD=function(a,b,c){if(osdTimeout&&clearTimeout(osdTimeout),!a)return osd.style.transition="all 0.15s linear",osd.style.top="-29px",osd.style.opacity=0,void(osdShowing=!1);!b&&osdShowing||(osd.innerHTML=a,osd.style.color=c?"rgb(255, 60, 40)":"rgb(0, 255, 0)"),osd.style.transition="none",osd.style.top="15px",osd.style.opacity=1,osdShowing=!0;var d=canvasOuter.clientWidth-30,e=osd.clientWidth,f=e0)return Javatari.SCREEN_DEFAULT_SCALE;var a=Number.parseFloat(window.getComputedStyle(mainElement.parentElement).width);return a>=640?2:a>=540?1.65:a>=420?1.25:a>=355?1.05:a>=340?1:a>=300?.9:.8},this.setDebugMode=function(a){debugMode=!!a,canvasContext=null},this.crtFilterToggle=function(){var a=crtFilter+1;a>3&&(a=-2),setCRTFilter(a);var b=null===crtFilterEffective?"browser default":crtFilterEffective<1?"OFF":"level "+crtFilterEffective;this.showOSD("CRT filter: "+(crtFilter===-1?"AUTO ("+b+")":b),!0),Javatari.userPreferences.current.crtFilter!==crtFilter&&(Javatari.userPreferences.current.crtFilter=crtFilter,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save())},this.crtFilterSetDefault=function(){var a=Javatari.userPreferences.current.crtFilter;setCRTFilter(null===a?Javatari.SCREEN_FILTER_MODE:a)},this.crtModeToggle=function(){var a=crtMode+1;a>1&&(a=-1),setCRTMode(a);var b=1===crtModeEffective?"Phosphor":"OFF";this.showOSD("CRT mode: "+(crtMode===-1?"AUTO ("+b+")":b),!0)},this.crtModeSetDefault=function(){setCRTMode(Javatari.SCREEN_CRT_MODE)},this.displayToggleFullscreen=function(){if(FULLSCREEN_MODE!==-2)return fullscreenAPIEnterMethod&&!isFullScreenByAPI()?void enterFullScreenByAPI():void this.setFullscreen(!isFullscreen)},this.setFullscreen=function(a){fullscreenAPIEnterMethod?a?enterFullScreenByAPI():exitFullScreenByAPI():setFullscreenState(a)},this.focus=function(){canvas.focus()},this.consolePowerAndUserPauseStateUpdate=function(a,b){isLoading&&(a=!1),powerButton.style.backgroundPosition=""+powerButton.jtBX+"px "+mediaButtonBackYOffsets[a?2:1]+"px",powerButton.jtMenu[0].label="Power "+(a?"OFF":"ON"),powerButton.jtMenu[1].disabled=powerButton.jtMenu[9].disabled=!a},this.cartridgeInserted=function(a){consolePanel.cartridgeInserted(a)},this.controlsModeStateUpdate=function(){settingsDialog&&settingsDialog.controlsModeStateUpdate()},this.touchControlsActiveUpdate=function(a,b){touchControlsActive===a&&touchControlsDirBig===b||(touchControlsActive=a,touchControlsDirBig=b,isFullscreen&&(touchControlsActive&&consoleControls.setupTouchControlsIfNeeded(fsElementCenter),this.requestReadjust(!0)))},this.controlStateChanged=function(a,b){consolePanel.controlStateChanged(a,b)},this.controlsStatesRedefined=function(){consolePanel.controlsStatesRedefined()},this.setLoading=function(a){isLoading=a,updateLoading()},this.requestReadjust=function(a){settingsDialog&&settingsDialog.isVisible()&&settingsDialog.position(),a?readjustAll(!0):(readjustRequestTime=jt.Util.performanceNow(),readjustInterval||(readjustInterval=setInterval(readjustAll,50)))},this.closeAllOverlays=closeAllOverlays,this.closeLogoMessage=function(){if(consolePanel.setLogoMessageActive(!1),fsElement.classList.remove("jt-logo-message-active"),logoMessageActive=!1,afterMessageAction){var a=afterMessageAction;afterMessageAction=null,a()}};var afterMessageAction,atariConsole,consoleControlsSocket,monitor,peripheralControls,fileLoader,fileDownloader,consoleControls,cartridgeSocket,stateMedia,recentROMs,readjustInterval=0,readjustRequestTime=0,readjustScreenSize={w:0,wk:0,h:0,pw:0,l:!1},isFullscreen=!1,isLandscape=!1,isTouchDevice=jt.Util.isTouchDevice(),isMobileDevice=jt.Util.isMobileDevice(),isIOSDevice=jt.Util.isIOSDevice(),isBrowserStandalone=jt.Util.isBrowserStandaloneMode(),browserName=jt.Util.browserInfo().name,fullscreenAPIEnterMethod,fullScreenAPIExitMethod,fullScreenAPIQueryProp,fullScreenAPIExitUserRequested=!1,fullScreenScrollHack=!1,viewportTag,viewPortOriginalTag,viewPortOriginalContent,consolePanel,consolePanelElement,settingsDialog,saveStateDialog,recentROMsDialog,quickOtionsDialog,fsElement,fsElementCenter,canvas,canvasOuter,canvasLoadingIcon,canvasContext,canvasImageRenderingValue,touchControlsActive=!1,touchControlsDirBig=!1,consolePanelActive=!1,consolePanelActiveLandscape=!1,consolePanelActivePortrait=jt.ConsolePanel.shouldStartActive(),buttonsBar,buttonsBarInner,buttonsBarDesiredWidth=-1,barButtonLongTouchTarget,barButtonLongTouchSelectTimeout,barMenu,barMenus=[],barMenuActive,barMenuItemActive,barMenuSystem,barConsoleControlPressed,osd,osdTimeout,osdShowing=!1,cursorType="auto",cursorShowing=!0,cursorHideFrameCountdown=-1,signalIsOn=!1,crtFilter=-2,crtFilterEffective=null,crtMode=-1,crtModeEffective=0,debugMode=!1,isLoading=!1,aspectX=Javatari.SCREEN_DEFAULT_ASPECT,scaleY=1,mousePointerLocked=!1,targetWidth=160,targetHeight=213,logo,logoCenter,logoImage,logoMessage,logoMessageText,logoMessageOK,logoMessageOKText,logoMessageActive=!1,logoLoadingIcon,scrollMessage,scrollMessageActive=!1,powerButton,logoButton,scaleDownButton,scaleUpButton,fullscreenButton,settingsButton,gameSelectButton,gameResetButton,mediaButtonBackYOffsets=[-51,-26,-1],CANVAS_SIZE_FACTOR=Javatari.SCREEN_CANVAS_SIZE,OSD_TIME=3e3,CURSOR_HIDE_FRAMES=180,FULLSCREEN_MODE=Javatari.SCREEN_FULLSCREEN_MODE,BAR_AUTO_HIDE=0===Javatari.SCREEN_CONTROL_BAR,BAR_MENU_MAX_ITEMS=10,NARROW_WIDTH=336,k=jt.DOMKeys,KEY_CTRL_MASK=k.CONTROL,KEY_ALT_MASK=k.ALT,KEY_SHIFT_MASK=k.SHIFT,MENU_CLOSE_KEYS={}; MENU_CLOSE_KEYS[k.VK_ESCAPE.c]=1,MENU_CLOSE_KEYS[k.VK_CONTEXT.c]=1;var MENU_EXEC_KEYS={};MENU_EXEC_KEYS[k.VK_ENTER.c]=1,MENU_EXEC_KEYS[k.VK_SPACE.c]=1;var MENU_SELECT_KEYS={};MENU_SELECT_KEYS[k.VK_LEFT.c]=-1,MENU_SELECT_KEYS[k.VK_RIGHT.c]=1;var MENU_ITEM_SELECT_KEYS={};MENU_ITEM_SELECT_KEYS[k.VK_UP.c]=-1,MENU_ITEM_SELECT_KEYS[k.VK_DOWN.c]=1,init(),this.eval=function(str){return eval(str)}},jt.RecentROMsDialog=function(a,b,c,d){"use strict";function e(){j.style.height=""+(42+33*(l.length+1))+"px";for(var a=0;a<11;++a){var b=n[a],c=l[a];b.classList.toggle("jt-visible",a<=l.length),b.classList.toggle("jt-toggle",a=0&&(jt.DOMConsoleControls.hapticFeedbackOnTouch(a),m=a.target.jtItem,f(),setTimeout(b,120))}),j.addEventListener("keydown",function(c){return c.keyCode===q?a():r.indexOf(c.keyCode)>=0?b():s[c.keyCode]&&(m+=s[c.keyCode],m<0?m=0:m>l.length&&(m=l.length),f()),jt.Util.blockEvent(c)})}var i=this;this.show=function(b){if(!j)return g(),setTimeout(function(){i.show(b)},0);l=c.getCatalog().slice(),l.sort(function(a,b){return a.n>b.n});var d=c.lastROMLoadedIndex;d=l.indexOf(l.find(function(a){return a.i===d})),m=d<0||d>=l.length?l.length:d,o=!0,e(),j.classList.add("jt-show"),j.focus();var f=a.clientHeight-jt.ScreenGUI.BAR_HEIGHT-20,h=j.clientHeight,k=h=0&&(jt.DOMConsoleControls.hapticFeedbackOnTouch(a),n=a.target.jtSlot,f(),setTimeout(b,120))}),j.addEventListener("keydown",function(c){return c.keyCode===u?a():v.indexOf(c.keyCode)>=0?b():w[c.keyCode]&&(n+=w[c.keyCode],n<0?n=0:n>10&&(n=10),f()),jt.Util.blockEvent(c)})}var i=this;this.show=function(b){if(!j)return g(),setTimeout(function(){i.show(b)},0);m=b,p=!0,e(),j.classList.add("jt-show"),j.focus();var c=a.clientHeight-jt.ScreenGUI.BAR_HEIGHT-20,d=j.clientHeight,f=d=0&&g.hide(),jt.Util.blockEvent(a)})}var g=this;this.show=function(){if(!h)return e(),setTimeout(g.show,0);d(),j=!0,h.classList.add("jt-show"),h.focus();var b=a.clientHeight-jt.ScreenGUI.BAR_HEIGHT-20,c=h.clientHeight,f=c
Help & Settings
CONSOLE
CONTROLLERS
EMULATION
ABOUT
F1
POWER
F2
TV TYPE
F4
P1 Difficulty
F5
Load Cartridge File
F6
Load Cartridge URL
F7
Remove Cartridge
F12
RESET
F11
SELECT
F9
P2 Difficulty
Alt
 + 
L
Toggle Paddles
Alt
 + 
K
Toggle Swap Sides
Alt
 + 
J
Toggle Gamepads
Alt
 + 
H
Adjust Turbo Fire speed
PLAYER 1
Fire
Up
Turbo Fire
Left
Right
Down
PLAYER 2
Fire
Up
Turbo Fire
Left
Right
Down
Alt
 + 
C
Collisions
Shift
 + 
F1
Fry Console
Alt
 + 
Q
NTSC/PAL
Alt
 + 
W
V-Synch Modes
Alt
 + 
R
CRT Modes
Alt
 + 
T
CRT Filters
Alt
 + 
D
Debug Modes
Alt
 + 
I
Show Info
Alt
 + 
G
Capture Screen
Right-Click Bar Icons: Default Action
Alt
 + 
0 - 9
Load State
Ctrl
 + 
0 - 9
Save State
F8
Save State File
F12
  /  
Shift
 + 
F12
Fast / Slow Speed
Shift
 
Alt
 + 
Arrows
Adjust Speed
Alt
 + 
P
Toggle Pause
Alt
 + 
O
 / 
F
Next Frame
Alt
 + 
Enter
Full Screen
Ctrl
 
Alt
 + 
Arrows
Screen Size / Width
Shift
 
Ctrl
 + 
Arrows
Viewport Size / Origin
Backspace
Defaults
version '+Javatari.VERSION+'
'+atob("Q3JlYXRlZCBieSBQYXVsbyBBdWd1c3RvIFBlY2Npbg==")+"
"+atob("PGEgdGFyZ2V0PSJfYmxhbmsiIGhyZWY9Imh0dHA6Ly9qYXZhdGFyaS5vcmciPmh0dHA6Ly9qYXZhdGFyaS5vcmc8L2E+")+'
'; },jt.SettingsGUI.css=function(){return"#jt-modal * { outline: none; box-sizing: border-box; } #jt-modal { position: absolute; overflow: hidden; width: "+jt.SettingsGUI.WIDTH+"px; height: 0; opacity: 0; visibility: hidden; top: 50%; left: 50%; color: hsl(0, 0%, 10%); font: normal 13px sans-serif; white-space: nowrap; text-align: initial; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform: scale(0.85); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out, height .25s step-end; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; z-index: 50; } #jt-modal.jt-show { transform: scale(1); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out; height: "+jt.SettingsGUI.HEIGHT+'px; visibility: visible; opacity: 1; } #jt-modal .jt-heading { font-weight: 700; color: hsl(0, 0%, 30%); } #jt-modal .jt-link { font-weight: 700; line-height: 21px; color: hsl(228, 90%, 40%); cursor: pointer; } #jt-modal .jt-link:hover { outline: 1px solid; } .jt-command { position: relative; display: inline-block; font-weight: 600; color: hsl(0, 0%, 48%); } .jt-hotkey { height: 27px; padding: 3px 5px; box-sizing: border-box; } .jt-hotkey .jt-desc { display: inline-block; line-height: 21px; } .jt-key { position: relative; display: inline-block; top: -1px; min-width: 25px; height: 21px; padding: 4px 6px 3px; box-sizing: border-box; font-weight: 600; font-size: 12px; line-height: 12px; color: hsl(0, 0%, 42%); background: white; border-radius: 3px; border: 1px solid rgb(210, 210, 210); box-shadow: 0 1px 0 1px hsl(0, 0%, 47%); text-align: center; } .jt-key-fixed { width: 31px; padding-left: 0; padding-right: 2px; } .jt-footer { margin-top: 16px; text-align: center; } #jt-menu { position: relative; background: white; border-bottom: 1px solid hsl(0, 0%, 72%); } #jt-menu #jt-back { position: absolute; width: 40px; height: 34px; margin: 3px 1px; padding: 16px 12px; cursor: pointer; } #jt-menu #jt-back:hover { background: rgba(0, 0, 0, .12); } .jt-back-arrow { display: block; width: 16px; height: 2px; border-radius: 1000px; background: hsl(0, 0%, 98%); } .jt-back-arrow:before { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(-45deg); transform-origin: 1px 1px; } .jt-back-arrow:after { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(45deg); transform-origin: 1px 1px; } #jt-menu .jt-caption { height: 29px; margin: 0 -1px; padding: 10px 0 0 48px; font-size: 18px; color: white; background: hsl(358, 66%, 50%); box-shadow: 0 1px 3px rgba(0, 0, 0, .9); vertical-align: middle; box-sizing: content-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-menu .jt-items { position: relative; width: 84%; height: 39px; margin: 0 auto; font-weight: 600; } #jt-menu .jt-item { float: left; width: 25%; height: 100%; padding-top: 13px; font-size: 14px; color: rgba(0, 0, 0, .43); text-align: center; cursor: pointer; } #jt-menu .jt-selected { color: hsl(358, 67%, 46%); } #jt-menu #jt-menu-selection { position: absolute; left: 0; bottom: 0; width: 25%; height: 3px; background: hsl(358, 67%, 46%); transition: left 0.3s ease-in-out; } #jt-content { position: relative; left: 0; width: 3000px; height: 371px; background: rgb(218, 218, 218); transition: left 0.3s ease-in-out } #jt-console, #jt-ports, #jt-general, #jt-about { position: absolute; width: '+jt.SettingsGUI.WIDTH+"px; height: 100%; box-sizing: border-box; } #jt-console { padding-top: 35px; } #jt-console .jt-hotkey { height: 29px; } #jt-console .jt-command { width: 42px; } #jt-console .jt-left, #jt-console .jt-middle, #jt-console .jt-right { float: left; } #jt-console .jt-left { width: 160px; margin-left: 58px; } #jt-console .jt-middle { width: 204px; } #jt-console .jt-right .jt-command { width: 46px; } #jt-console .jt-console-panel { position: relative; margin: 18px auto 0; box-shadow: rgba(0, 0, 0, 0.6) 2px 2px 4px; } #jt-console .jt-console-panel * { cursor: auto; } #jt-console .jt-footer { margin: 20px auto; } #jt-ports { left: "+jt.SettingsGUI.WIDTH+'px; padding: 18px 0 0 27px; } #jt-ports > .jt-left { float: left; width: 335px; padding-left: 26px; } #jt-ports > .jt-right { float: left; } #jt-ports .jt-command { width: 91px; } #jt-ports .jt-bottom { width: 546px; text-align: center; } #jt-ports .jt-player { position: absolute; top: 146px; width: 217px; color: rgba(0, 0, 0, .8); } #jt-ports .jt-p1 { left: 47px; } #jt-ports .jt-p2 { right: 47px; } #jt-ports .jt-title { margin-bottom: 09px; font-size: 14px; line-height: 14px; font-weight: bold; color: hsl(0, 0%, 35%); text-align: center; } #jt-ports .jt-player .jt-command { display: block; position: relative; float: left; width: 33%; height: 45px; font-size: 13px; text-align: center; } #jt-ports .jt-command.jt-fire1, #jt-ports .jt-command.jt-fire2 { top: 14px; } #jt-ports .jt-command.jt-left, #jt-ports .jt-command.jt-right { top: 27px; } #jt-ports .jt-command.jt-down { float: none; clear: both; margin: 0 auto; } #jt-ports .jt-command.jt-controller { height: 90px; } #jt-ports #jt-control-p1-controller, #jt-ports #jt-control-p2-controller { width: 70px; height: 89px; margin-left: 1px; background: url("'+jt.Images.urls.controllers+'") no-repeat -1px 0; background-size: 73px 179px; } #jt-ports .jt-player .jt-key { min-width: 33px; height: 23px; padding: 5px 6px 4px; margin-top: 2px; cursor: pointer; } #jt-ports .jt-player .jt-key:hover { box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5), 1px 2px 6px 4px rgb(170, 170, 170); } #jt-ports .jt-player .jt-key.jt-redefining { color: white; background-color: rgb(87, 128, 255); border-color: rgb(71, 117, 255); } #jt-ports .jt-player .jt-key.jt-undefined { background-color: rgb(255, 150, 130); border-color: rgb(255, 130, 90); } #jt-ports-defaults, #jt-ports-revert { position: absolute; left: 260px; width: 82px; text-align: center; padding: 3px 0 1px; font-size: 12px; } #jt-ports-defaults { bottom: 47px; } #jt-ports-revert { bottom: 21px; } #jt-general { left: '+2*jt.SettingsGUI.WIDTH+"px; padding-top: 18px; padding-left: 34px; } #jt-general .jt-left { float: left; width: 245px; } #jt-general .jt-left .jt-command { width: 99px; } #jt-general .jt-right { float: left; } #jt-general .jt-right .jt-command { width: 160px; } #jt-about { left: "+3*jt.SettingsGUI.WIDTH+'px; font-size: 18px; } #jt-about #jt-logo-version { width: 300px; height: 238px; margin: 26px auto 19px; color: hsl(0, 0%, 98%); padding-top: 200px; box-sizing: border-box; text-align: center; background: black url("'+jt.Images.urls.logo+'") center 18px no-repeat; background-size: 233px 173px; box-shadow: 3px 3px 14px rgb(75, 75, 75); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-about .jt-info { line-height: 30px; text-align: center; } #jt-about a { color: rgb(0, 40, 200); text-decoration: none; } #jt-about a:hover { text-decoration: underline; } #jt-about #jt-browserinfo { position: absolute; left: 0; right: 0; bottom: 7px; font-size: 10px; text-align: center; color: transparent; } .jt-clear { clear: both; } .jt-divider { clear: both; height: 27px; } .jt-full-divider { clear: both; height: 21px; } #jt-general .jt-full-divider { clear: both; height: 18px; }'},jt.SettingsDialog=function(a,b){"use strict";function c(){jt.Util.insertCSS(jt.SettingsGUI.css()),a.insertAdjacentHTML("beforeend",jt.SettingsGUI.html()),j=document.getElementById("jt-modal"),delete jt.SettingsGUI.html,delete jt.SettingsGUI.css,d(),e()}function d(){function a(b,c){c(b);for(var d=b.childNodes,e=0;e=0;d-=1)b[d]=0;if(0!==j.length)for(var e=j.length-1;e>=0;e-=1){for(var f=n[e],g=j[e].retrieveSamples(c*f+o[e]|0,r),h=g.buffer,i=g.bufferSize,k=g.start+o[e],l=0;l=i&&(k-=i);o[e]=k-(0|k)}}this.connect=function(a){a.connectMonitor(this)},this.connectPeripherals=function(a){g=a},this.connectAudioSignal=function(a){j.indexOf(a)>=0||(jt.Util.arrayAdd(j,a),e())},this.disconnectAudioSignal=function(a){j.indexOf(a)<0||(jt.Util.arrayRemoveAllElement(j,a),e())},this.powerOn=function(){h(),m&&(d(),this.unpause())},this.powerOff=function(){this.pause(),k&&k.close(),k=m=void 0},this.mute=function(){r=!0},this.unMute=function(){r=!1},this.pause=function(){m&&m.disconnect()},this.unpause=function(){m&&m.connect(k.destination)},this.toggleBufferBaseSize=function(){return k?(q=(q+2)%8-1,this.pause(),i(),this.unpause(),g.showOSD("Audio Buffer size: "+(q===-1?"Auto ("+l+")":0===q?"Browser ("+l+")":l),!0),p.audioBufferBase=q,void Javatari.userPreferences.setDirty()):g.showOSD("Audio is DISABLED",!0,!0)},this.getControlReport=function(a){return{label:q===-2?"OFF":q===-1?"Auto":0===q?"Browser":l,active:q>0}};var g,h=function(){if(q===-2||0===Javatari.AUDIO_MONITOR_BUFFER_SIZE)return void jt.Util.warning("Audio disabled in configuration");try{var a=window.AudioContext||window.webkitAudioContext||window.WebkitAudioContext;if(!a)throw new Error("WebAudio API not supported by the browser");k=new a,jt.Util.log("Speaker AudioContext created. Sample rate: "+k.sampleRate+(k.state?", "+k.state:"")),i()}catch(a){jt.Util.error("Could not create AudioContext. Audio DISABLED!\n"+a)}},i=function(){try{var a=q===-1?b():0===q?c():q,d=Javatari.AUDIO_MONITOR_BUFFER_SIZE>0?Javatari.AUDIO_MONITOR_BUFFER_SIZE:a>0?jt.Util.exp2(0|jt.Util.log2((k.sampleRate+14e3)/22050))*jt.Util.exp2(a-1)*256:0;m=k.createScriptProcessor(d,1,1),m.onaudioprocess=f,l=m.bufferSize,e(),jt.Util.log("Audio Processor buffer size: "+m.bufferSize)}catch(a){jt.Util.error("Could not create ScriptProcessorNode. Audio DISABLED!\n"+a)}},j=[];this.signals=j; var k,l,m,n=[],o=[],p=Javatari.userPreferences.current,q=Javatari.AUDIO_MONITOR_BUFFER_BASE===-3?p.audioBufferBase:Javatari.AUDIO_MONITOR_BUFFER_BASE,r=!1},jt.LocalStorageSaveStateMedia=function(){"use strict";this.connect=function(a){a.connectMedia(this)},this.connectPeripherals=function(b){a=b},this.isSlotUsed=function(a){return void 0!==localStorage["javatarisave"+a]},this.saveState=function(a,c){var e=d(c);return e&&b("save"+a,e)},this.loadState=function(a){var b=c("save"+a);return e(b)},this.saveStateFile=function(b,c){var e=d(c);e&&a.startDownloadBinary((b||"Javatari SaveState")+h,e,"System State file")},this.loadStateFile=function(a){return e(a)},this.saveResource=function(a,c){try{var d=c&&JSON.stringify(c);return b("res"+a,d)}catch(a){}},this.loadResource=function(a){try{var b=c("res"+a);return b&&JSON.parse(b)}catch(a){}};var a,b=function(a,b){try{return localStorage["javatari"+a]=b,!0}catch(a){return jt.Util.error(a),!1}},c=function(a){try{return localStorage["javatari"+a]}catch(a){jt.Util.warning(a)}},d=function(a){try{return f+JSON.stringify(a)}catch(a){jt.Util.error(a)}},e=function(a){try{var b;if(b="string"==typeof a?a.substr(0,f.length):jt.Util.int8BitArrayToByteString(a,0,f.length),b!==f&&b!==g)return;var c;return c="string"==typeof a?a.slice(f.length):jt.Util.int8BitArrayToByteString(a,f.length),c&&JSON.parse(c)}catch(a){jt.Util.error(a)}},f=String.fromCharCode(0,0)+"javataristate!",g="javatarijsstate!",h=".jst"},jt.PeripheralControls={SCREEN_ASPECT_PLUS:1,SCREEN_ASPECT_MINUS:2,SCREEN_SCALE_PLUS:3,SCREEN_SCALE_MINUS:4,VIEWPORT_ORIGIN_PLUS:5,VIEWPORT_ORIGIN_MINUS:6,VIEWPORT_SIZE_PLUS:7,VIEWPORT_SIZE_MINUS:8,SCREEN_FULLSCREEN:10,SCREEN_CRT_FILTER:11,SCREEN_CRT_MODE:12,SCREEN_TOGGLE_MENU:13,SCREEN_OPEN_HELP:14,SCREEN_OPEN_ABOUT:15,SCREEN_OPEN_SETTINGS:16,SCREEN_OPEN_QUICK_OPTIONS:17,SCREEN_DEFAULTS:18,SCREEN_CONSOLE_PANEL_TOGGLE:19,SPEAKER_BUFFER_TOGGLE:20,MACHINE_POWER_TOGGLE:102,MACHINE_POWER_FRY:103,MACHINE_LOAD_STATE_FILE:104,MACHINE_SAVE_STATE_FILE:105,MACHINE_LOAD_STATE_MENU:106,MACHINE_SAVE_STATE_MENU:107,P1_CONTROLS_TOGGLE:201,JOYSTICKS_TOGGLE_MODE:202,PADDLES_TOGGLE_MODE:203,TOUCH_TOGGLE_MODE:204,TOUCH_TOGGLE_DIR_BIG:205,TURBO_FIRE_TOGGLE:206,HAPTIC_FEEDBACK_TOGGLE_MODE:207,CAPTURE_SCREEN:304,CARTRIDGE_LOAD_RECENT:40,CARTRIDGE_LOAD_FILE:41,CARTRIDGE_LOAD_URL:42,CARTRIDGE_REMOVE:43,CARTRIDGE_LOAD_DATA_FILE:44,CARTRIDGE_SAVE_DATA_FILE:45,AUTO_LOAD_FILE:46,AUTO_LOAD_URL:47},jt.DOMPeripheralControls=function(){"use strict";function a(){k()}var b=this;this.connect=function(a,b){c=a,i=b},this.connectPeripherals=function(a,b,c,i){d=a,f=b,e=a.getMonitor(),g=c,h=i},this.getControlReport=function(a){switch(a){case l.PADDLES_TOGGLE_MODE:case l.TURBO_FIRE_TOGGLE:case l.TOUCH_TOGGLE_DIR_BIG:case l.HAPTIC_FEEDBACK_TOGGLE_MODE:return g.getControlReport(a);case l.SCREEN_CRT_FILTER:return d.getControlReport(a);case l.SPEAKER_BUFFER_TOGGLE:return f.getControlReport(a)}return{label:"Unknown",active:!1}},this.processKey=function(a,c){if(!c)return!1;var d=m[a]||m[a&n];return!!d&&(b.controlActivated(d,!!(a&o),!1),!0)},this.controlActivated=function(a,b,k){switch(a){case l.MACHINE_POWER_TOGGLE:c.controlStateChanged(jt.ConsoleControls.POWER,!0);break;case l.MACHINE_POWER_FRY:c.controlStateChanged(jt.ConsoleControls.POWER_FRY,!0);break;case l.MACHINE_LOAD_STATE_FILE:j()||h.openFileChooserDialog(p.STATE,!1,!1,!1);break;case l.MACHINE_SAVE_STATE_FILE:c.controlStateChanged(jt.ConsoleControls.SAVE_STATE_FILE,!0);break;case l.MACHINE_LOAD_STATE_MENU:d.openSaveStateDialog(!1);break;case l.MACHINE_SAVE_STATE_MENU:d.openSaveStateDialog(!0);break;case l.CARTRIDGE_LOAD_RECENT:j()||d.openCartridgeChooserDialog(!1,b,k);break;case l.CARTRIDGE_LOAD_FILE:j()||h.openFileChooserDialog(p.ROM,b,k,!1);break;case l.CARTRIDGE_LOAD_URL:j()||h.openURLChooserDialog(p.ROM,b,k);break;case l.CARTRIDGE_REMOVE:j()||i.insert(null,!1);break;case l.CARTRIDGE_LOAD_DATA_FILE:break;case l.CARTRIDGE_SAVE_DATA_FILE:break;case l.AUTO_LOAD_FILE:j()||h.openFileChooserDialog(p.AUTO,b,k,!1);break;case l.AUTO_LOAD_URL:j()||h.openURLChooserDialog(p.AUTO,b,k,!1);break;case l.SCREEN_CRT_MODE:e.crtModeToggle();break;case l.SCREEN_CRT_FILTER:e.crtFilterToggle();break;case l.SCREEN_FULLSCREEN:e.fullscreenToggle();break;case l.SCREEN_DEFAULTS:c.setDefaults(),e.setDefaults(),e.showOSD("Default Settings",!0);break;case l.SCREEN_TOGGLE_MENU:d.toggleMenuByKey();break;case l.SCREEN_OPEN_HELP:d.openHelp();break;case l.SCREEN_OPEN_ABOUT:d.openAbout();break;case l.SCREEN_OPEN_SETTINGS:if(b)return this.controlActivated(l.SCREEN_DEFAULTS);d.openSettings();break;case l.SCREEN_OPEN_QUICK_OPTIONS:d.openQuickOptionsDialog();break;case l.SCREEN_CONSOLE_PANEL_TOGGLE:d.toggleConsolePanel();break;case l.P1_CONTROLS_TOGGLE:g.toggleP1ControlsMode();break;case l.JOYSTICKS_TOGGLE_MODE:g.toggleGamepadMode();break;case l.PADDLES_TOGGLE_MODE:g.togglePaddleMode();break;case l.TOUCH_TOGGLE_MODE:g.toggleTouchControlsMode();break;case l.TOUCH_TOGGLE_DIR_BIG:g.toggleTouchDirBig();break;case l.TURBO_FIRE_TOGGLE:g.toggleTurboFireSpeed();break;case l.HAPTIC_FEEDBACK_TOGGLE_MODE:g.toggleHapticFeedback();break;case l.CAPTURE_SCREEN:d.saveScreenCapture();break;case l.SPEAKER_BUFFER_TOGGLE:f.toggleBufferBaseSize();break;case l.VIEWPORT_ORIGIN_MINUS:e.viewportOriginDecrease();break;case l.VIEWPORT_ORIGIN_PLUS:e.viewportOriginIncrease()}if(!N)switch(a){case l.SCREEN_ASPECT_MINUS:e.displayAspectDecrease();break;case l.SCREEN_ASPECT_PLUS:e.displayAspectIncrease();break;case l.SCREEN_SCALE_MINUS:e.displayScaleDecrease();break;case l.SCREEN_SCALE_PLUS:e.displayScaleIncrease();break;case l.VIEWPORT_SIZE_MINUS:e.viewportSizeDecrease();break;case l.VIEWPORT_SIZE_PLUS:e.viewportSizeIncrease()}};var c,d,e,f,g,h,i,j=function(){return!!Javatari.CARTRIDGE_CHANGE_DISABLED&&(e.showOSD("Cartridge change is disabled!",!0,!0),!0)},k=function(){var a=jt.DOMKeys;m[y]=l.CARTRIDGE_LOAD_RECENT,m[y|a.ALT]=l.CARTRIDGE_LOAD_RECENT,m[z]=l.AUTO_LOAD_URL,m[z|a.ALT]=l.AUTO_LOAD_URL,m[A]=l.CARTRIDGE_REMOVE,m[A|a.ALT]=l.CARTRIDGE_REMOVE,m[M]=l.MACHINE_SAVE_STATE_FILE,m[M|a.ALT]=l.MACHINE_SAVE_STATE_FILE,m[B|a.ALT]=l.P1_CONTROLS_TOGGLE,m[D|a.ALT]=l.PADDLES_TOGGLE_MODE,m[C|a.ALT]=l.JOYSTICKS_TOGGLE_MODE,m[E|a.ALT]=l.TOUCH_TOGGLE_MODE,m[F|a.ALT]=l.TURBO_FIRE_TOGGLE,m[H|a.ALT]=l.SCREEN_CRT_FILTER,m[G|a.ALT]=l.SCREEN_CRT_MODE,m[I|a.ALT]=l.SCREEN_OPEN_SETTINGS,m[J|a.ALT]=l.SCREEN_OPEN_QUICK_OPTIONS,m[K|a.ALT]=l.SCREEN_CONSOLE_PANEL_TOGGLE,m[L|a.ALT]=l.SCREEN_FULLSCREEN,m[r|a.CONTROL|a.ALT]=l.SCREEN_SCALE_MINUS,m[t|a.CONTROL|a.ALT]=l.SCREEN_SCALE_PLUS,m[q|a.CONTROL|a.ALT]=l.SCREEN_ASPECT_MINUS,m[s|a.CONTROL|a.ALT]=l.SCREEN_ASPECT_PLUS,m[r|a.SHIFT|a.CONTROL]=l.VIEWPORT_ORIGIN_MINUS,m[t|a.SHIFT|a.CONTROL]=l.VIEWPORT_ORIGIN_PLUS,m[q|a.SHIFT|a.CONTROL]=l.VIEWPORT_SIZE_MINUS,m[s|a.SHIFT|a.CONTROL]=l.VIEWPORT_SIZE_PLUS,m[u]=l.SCREEN_TOGGLE_MENU,m[v]=l.SCREEN_DEFAULTS,m[v|a.ALT]=l.SCREEN_DEFAULTS,m[w|a.ALT]=l.CAPTURE_SCREEN,m[x|a.ALT]=l.SPEAKER_BUFFER_TOGGLE},l=jt.PeripheralControls,m={},n=~jt.DOMKeys.SHIFT,o=jt.DOMKeys.SHIFT,p=jt.FileLoader.OPEN_TYPE,q=jt.DOMKeys.VK_LEFT.c,r=jt.DOMKeys.VK_UP.c,s=jt.DOMKeys.VK_RIGHT.c,t=jt.DOMKeys.VK_DOWN.c,u=jt.DOMKeys.VK_CONTEXT.c,v=jt.DOMKeys.VK_BACKSPACE.c,w=jt.DOMKeys.VK_X.c,x=jt.DOMKeys.VK_A.c,y=jt.DOMKeys.VK_F5.c,z=jt.DOMKeys.VK_F6.c,A=jt.DOMKeys.VK_F7.c,B=jt.DOMKeys.VK_K.c,C=jt.DOMKeys.VK_J.c,D=jt.DOMKeys.VK_L.c,E=jt.DOMKeys.VK_N.c,F=jt.DOMKeys.VK_H.c,G=jt.DOMKeys.VK_R.c,H=jt.DOMKeys.VK_T.c,I=jt.DOMKeys.VK_Y.c,J=jt.DOMKeys.VK_U.c,K=jt.DOMKeys.VK_S.c,L=jt.DOMKeys.VK_ENTER.c,M=(jt.DOMKeys.VK_F1.c,jt.DOMKeys.VK_F8.c),N=Javatari.SCREEN_RESIZE_DISABLED;a()},jt.Room=function(a,b){"use strict";function c(){f(),g()}function d(a){var b=Javatari.AUTO_POWER_ON_DELAY;b>=0&&JavatariFullScreenSetup.shouldStartInFullScreen()&&(b+=1400),b-=Date.now()-i,b<1&&(b=1),setTimeout(a,b)}function e(){b&&(h.console.getCartridgeSocket().inserted()?h.console.userPowerOn():Javatari.CARTRIDGE_SHOW_RECENT&&!Javatari.CARTRIDGE_CHANGE_DISABLED&&h.screen.openCartridgeChooserDialog(!0)); }function f(){h.peripheralControls=new jt.DOMPeripheralControls,h.consoleControls=new jt.DOMConsoleControls(h.peripheralControls),h.fileDownloader=new jt.FileDownloader,h.stateMedia=new jt.LocalStorageSaveStateMedia,h.recentROMs=new jt.RecentStoredROMs,h.fileLoader=new jt.FileLoader(h.recentROMs),h.speaker=new jt.WebAudioSpeaker(a),h.screen=new jt.CanvasDisplay(a),h.fileDownloader.connectPeripherals(h.screen),h.screen.connectPeripherals(h.recentROMs,h.fileLoader,h.fileDownloader,h.consoleControls,h.peripheralControls,h.stateMedia),h.speaker.connectPeripherals(h.screen),h.consoleControls.connectPeripherals(h.screen),h.stateMedia.connectPeripherals(h.fileDownloader),h.peripheralControls.connectPeripherals(h.screen,h.speaker,h.consoleControls,h.fileLoader)}function g(){h.console=new jt.AtariConsole,h.stateMedia.connect(h.console.getSavestateSocket()),h.fileLoader.connect(h.console),h.screen.connect(h.console),h.speaker.connect(h.console.getAudioSocket()),h.consoleControls.connect(h.console.getConsoleControlsSocket()),h.peripheralControls.connect(h.console.getConsoleControlsSocket(),h.console.getCartridgeSocket())}var h=this;this.powerOn=function(){h.screen.powerOn(),h.speaker.powerOn(),h.consoleControls.powerOn(),h.setLoading(!0),i=Date.now()},this.powerOff=function(){h.console.powerOff(),h.consoleControls.powerOff(),h.speaker.powerOff(),h.screen.powerOff()},this.setLoading=function(a){this.isLoading!==a&&(this.isLoading=a,this.console.setLoading(this.isLoading),this.screen.setLoading(this.isLoading))},this.start=function(a){jt.Clock.detectHostNativeFPSAndCallback(function(b){h.console.vSynchSetSupported(b>0),d(function(){h.setLoading(!1),h.screen.start(a||e)})})},this.console=null,this.screen=null,this.speaker=null,this.consoleControls=null,this.fileDownloader=null,this.stateMedia=null,this.recentROMs=null,this.fileLoader=null,this.peripheralControls=null,this.isLoading=!1;var i;c()},Javatari.userPreferences={},Javatari.userPreferences.currentVersion=1,Javatari.userPreferences.compatibleVersions=new Set([1]),Javatari.userPreferences.defaults=function(){"use strict";var a=jt.DOMKeys;return{joystickKeys:[{left:a.VK_LEFT,up:a.VK_UP,right:a.VK_RIGHT,down:a.VK_DOWN,button:a.VK_SPACE,buttonT:a.VK_DELETE},{left:a.VK_F,up:a.VK_T,right:a.VK_H,down:a.VK_G,button:a.VK_A,buttonT:a.VK_PERIOD}],joystickGamepads:[{button:0,buttonT:1,select:8,reset:9,pause:4,fastSpeed:7,slowSpeed:6,device:-1,xAxis:0,xAxisSig:1,yAxis:1,yAxisSig:1,paddleAxis:0,paddleAxisSig:1,paddleCenter:.3,paddleSens:.75,deadzone:.3},{button:0,buttonT:1,select:8,reset:9,pause:4,fastSpeed:7,slowSpeed:6,device:-1,xAxis:0,xAxisSig:1,yAxis:1,yAxisSig:1,paddleAxis:0,paddleAxisSig:1,paddleCenter:.3,paddleSens:.75,deadzone:.3}],touch:{directionalBig:!1},hapticFeedback:!0,turboFireSpeed:6,vSynch:null,crtFilter:null,audioBufferBase:-1}},Javatari.userPreferences.load=function(){var a;try{a=JSON.parse(localStorage.javatari4prefs||"{}"),a.version&&delete a.version}catch(a){}if(!a||!Javatari.userPreferences.compatibleVersions.has(a.prefsVersion)){a={}}var b=Javatari.userPreferences.defaults();for(var c in b)void 0===a[c]&&(a[c]=b[c]);a.prefsVersion=Javatari.userPreferences.currentVersion,Javatari.userPreferences.current||(Javatari.userPreferences.current={});var d=Javatari.userPreferences.current;for(c in a)d[c]=a[c];Javatari.userPreferences.isDirty=!1},Javatari.userPreferences.setDefaultJoystickKeys=function(){Javatari.userPreferences.current.joystickKeys=Javatari.userPreferences.defaults().joystickKeys,Javatari.userPreferences.setDirty()},Javatari.userPreferences.save=function(){if(Javatari.userPreferences.isDirty)try{Javatari.userPreferences.current.javatariVersion=Javatari.VERSION,localStorage.javatari4prefs=JSON.stringify(Javatari.userPreferences.current),Javatari.userPreferences.isDirty=!1,jt.Util.log("Preferences saved!")}catch(a){}},Javatari.userPreferences.setDirty=function(){Javatari.userPreferences.isDirty=!0},jt.Images.embedded=!0,jt.Images.urls.logo="data:image/png;base64,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", jt.Images.urls.loading="data:image/gif;base64,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",jt.Images.urls.mouseCursor="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABL0lEQVRYw+3VP0oDQRTH8U8k+AcFFRUFERGLiFjEA1jZTo6RG6T3ArmFR9j0WlpaWBiwsNNyiwgW0Vg4CUPELhMt9guPffumeG9nf/MbvlnEYVmWo3a7PcIO1s2R3aT5KQ6wMo/GC/G5nNTWsYr6PHdgE+fJLjRxhFqMbNSxFr96K6nvYxhr7zE+Y8yUWghhNH5pNBr6/f5ksdfrXeA1xiCbBoqiUBSF6RwN7GIptwh/4wR7UyKduQZ0Op1JIc2xHTVSzzpAt9v9sdBqtczTB/6Mfz/A2AOGOYe4DCGMUqI33OAKl1MmNVsjwhmaIYTrxIBu8YA73OMZb7kG2MFhPPPH2ECJJzzG5iU+ch3DMvnfL/HcDxILztZcctPVo9stxXyYCPBDRUVFRUVFRUa+AB+1YCivg1lPAAAAAElFTkSuQmCC",jt.Images.urls.panel="data:image/jpeg;base64,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", jt.Images.urls.panelSprites="data:image/jpeg;base64,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", jt.Images.urls.controllers="data:image/jpeg;base64,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", jt.Images.urls.iconSprites="data:image/png;base64,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", jt.Configurator={applyConfig:function(){function a(){for(var a,b=(window.location.search||"").split("+").join(" "),c=/[?&]?([^=]+)=([^&]*)/g,d={};a=c.exec(b);){var e=decodeURIComponent(a[1]).trim().toUpperCase();e=jt.Configurator.abbreviations[e]||e,d[e]=decodeURIComponent(a[2]).trim()}return d}function b(){Javatari.AUTO_POWER_ON_DELAY|=0,Javatari.CARTRIDGE_CHANGE_DISABLED=Javatari.CARTRIDGE_CHANGE_DISABLED===!0||"true"==Javatari.CARTRIDGE_CHANGE_DISABLED,Javatari.SCREEN_RESIZE_DISABLED=Javatari.SCREEN_RESIZE_DISABLED===!0||"true"==Javatari.SCREEN_RESIZE_DISABLED,Javatari.SCREEN_FULLSCREEN_MODE=Javatari.SCREEN_FULLSCREEN_MODE|=0,Javatari.SCREEN_FILTER_MODE|=0,Javatari.SCREEN_CRT_MODE|=0,Javatari.SCREEN_DEFAULT_SCALE=parseFloat(Javatari.SCREEN_DEFAULT_SCALE),Javatari.SCREEN_DEFAULT_ASPECT=parseFloat(Javatari.SCREEN_DEFAULT_ASPECT),Javatari.SCREEN_CANVAS_SIZE=0|Javatari.SCREEN_CANVAS_SIZE,Javatari.SCREEN_CONTROL_BAR|=0,Javatari.SCREEN_FORCE_HOST_NATIVE_FPS|=0,Javatari.SCREEN_VSYNCH_MODE|=0,Javatari.AUDIO_MONITOR_BUFFER_BASE|=0,Javatari.AUDIO_MONITOR_BUFFER_SIZE|=0,Javatari.AUDIO_SIGNAL_BUFFER_RATIO=parseFloat(Javatari.AUDIO_SIGNAL_BUFFER_RATIO),Javatari.AUDIO_SIGNAL_ADD_FRAMES|=0}var c={};Javatari.ALLOW_URL_PARAMETERS&&(c=a(),c.PRESETS&&(this.applyParam("PRESETS",c.PRESETS),delete c.PRESETS)),c.RESET&&this.applyReset(),this.applyPresets(Javatari.PRESETS);for(var d in c)this.applyParam(d,c[d]);b()},applyPresets:function(a){for(var b=(a||"").trim().toUpperCase().split(","),c=0;c=0),Javatari.room=new jt.Room(Javatari.screenElement,a),Javatari.room.powerOn(),jt.Util.log("version "+Javatari.VERSION+" started"),jt.CartridgeDatabase.uncompress(),Javatari.STATE_URL)new jt.MultiDownloader([{url:Javatari.STATE_URL}],function(a){Javatari.room.start(function(){Javatari.room.fileLoader.loadFromContent(a[0].url,a[0].content,jt.FileLoader.OPEN_TYPE.STATE,0,!1)})}).start();else{var b=jt.Configurator.mediaURLSpecs();new jt.MultiDownloader(b,function(){Javatari.room.start()}).start()}Javatari.shutdown=function(){Javatari.room&&Javatari.room.powerOff(),jt.Util.log("shutdown")}},Javatari.preLoadImagesAndStart=function(){function a(a){Javatari.start&&Javatari.AUTO_START&&(a||b&&0===c)&&Javatari.start()}var b=!1,c=jt.Images.embedded?0:jt.Images.count;if(document.addEventListener("DOMContentLoaded",function(){b=!0,a(!1)}),c>0)for(var d in jt.Images.urls){var e=new Image;e.src=jt.Images.urls[d],e.onload=function(){c--,a(!1)}}window.addEventListener("load",function(){a(!0)})},window.applicationCache&&(window.applicationCache.status===window.applicationCache.UPDATEREADY?onUpdateReady():window.applicationCache.addEventListener("updateready",onUpdateReady)),Javatari.VERSION="4.0.1",Javatari.preLoadImagesAndStart(); ================================================ FILE: release/stable/4.0/standalone/cache.manifest ================================================ CACHE MANIFEST # Version 4.0.001 # Stable CACHE: manifest.webapp images/logo-icon192.png images/logo-icon512.png NETWORK: * ================================================ FILE: release/stable/4.0/standalone/index.html ================================================ Javatari
The online Atari 2600 emulator
Select Cartridge slot to load ROMs
Drag & Drop or Select Cartridge slot to load ROMs
================================================ FILE: release/stable/4.0/standalone/manifest.webapp ================================================ { "name": "Javatari", "description": "Javatari - The online Atari 2600 emulator", "display": "standalone", "background_color": "#000", "theme_color": "#363636", "icons": [{ "src": "images/logo-icon192.png", "sizes": "192x192", "type": "image/png" }, { "src": "images/logo-icon512.png", "sizes": "512x512", "type": "image/png" }] } ================================================ FILE: release/stable/5.0/embedded/index.html ================================================ Javatari
================================================ FILE: release/stable/5.0/embedded/javatari.js ================================================ // Javatari version 5.0.4 // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Main Emulator parameters. // May be overridden dynamically by URL query parameters, if ALLOW_URL_PARAMETERS = true. Javatari = { PRESETS: "", // Configuration Presets to apply. See Presets Configuration // Full or relative URL of Media files to load CARTRIDGE_URL: "", AUTODETECT_URL: "", STATE_URL: "", // Forcing ROM formats CARTRIDGE_FORMAT: "", // 4K, F8, F4, FE, AR, etc... // NetPlay NETPLAY_JOIN: "", // Join NetPlay! Session automatically NETPLAY_NICK: "", // NetPlay! Nickname // General configuration AUTO_START: true, AUTO_POWER_ON_DELAY: 1200, // -1: no auto Power-ON; >= 0: wait specified milliseconds before Power-ON CARTRIDGE_SHOW_RECENT: true, CARTRIDGE_CHANGE_DISABLED: false, CARTRIDGE_LABEL_COLORS: "", // Space-separated colors for Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults SCREEN_RESIZE_DISABLED: false, SCREEN_CONSOLE_PANEL_DISABLED: false, SCREEN_ELEMENT_ID: "javatari-screen", CONSOLE_PANEL_ELEMENT_ID: -1, // -1: auto. Don't change! :-) SCREEN_FULLSCREEN_MODE: -1, // -2: disabled; -1: auto; 0: off; 1: on SCREEN_CRT_MODE: 0, // -1: auto; 0: off; 1: on SCREEN_FILTER_MODE: -3, // -3: user set (default auto); -2: browser default; -1: auto; 0..3: smoothing level SCREEN_DEFAULT_SCALE: -1, // -1: auto; 0.5..N in 0.1 steps: scale SCREEN_DEFAULT_ASPECT: 1, // in 0.1 steps SCREEN_CANVAS_SIZE: 2, // Internal canvas size factor. Don't change! :-) SCREEN_CONTROL_BAR: 1, // 0: on hover; 1: always SCREEN_FORCE_HOST_NATIVE_FPS: -1, // -1: auto. Don't change! :-) SCREEN_VSYNCH_MODE: -2, // -2: user set (default on); -1: disabled; 0: off; 1: on AUDIO_MONITOR_BUFFER_BASE: -3, // -3: user set (default auto); -2: disable audio; -1: auto; 0: browser default; 1..6: base value. More buffer = more delay AUDIO_MONITOR_BUFFER_SIZE: -1, // -1: auto; 256, 512, 1024, 2048, 4096, 8192, 16384: buffer size. More buffer = more delay. Don't change! :-) AUDIO_SIGNAL_BUFFER_RATIO: 2, // Internal Audio Signal buffer based on Monitor buffer AUDIO_SIGNAL_ADD_FRAMES: 3, // Additional frames in internal Audio Signal buffer based on Monitor buffer PADDLES_MODE: -1, // -1: auto; 0: off; 1: on TOUCH_MODE: -1, // -1: auto; 0: disabled; 1: enabled; 2: enabled (swapped) IMAGES_PATH: window.JAVATARI_IMAGES_PATH || "images/", PAGE_BACK_CSS: "", // CSS to modify page background color. Applied to the body element SERVER_ADDRESS: "webmsx.azurewebsites.net/", SERVER_KEEPALIVE: 0, RESET: 0, // if value = 1 clear all saved data on the client ALLOW_URL_PARAMETERS: true // Allows user to override any of these parameters via URL query parameters }; Javatari.PRESETS_CONFIG = { }; // No built-in Presets for now jt = window.jt || {}; // Namespace for all classes and objects function onUpdateReady(){alert("A new version is available!\nJavatari will restart..."),window.applicationCache.swapCache(),window.location.reload()}JavatariFullScreenSetup={apply:function(){if(!this.cssApplied){var a=document.createElement("style");a.type="text/css",a.innerHTML=this.css,document.head.appendChild(a),this.cssApplied=!0}document.documentElement.classList.toggle("jt-full-screen",this.shouldStartInFullScreen())},shouldStartInFullScreen:function(){return window.Javatari?1===Javatari.SCREEN_FULLSCREEN_MODE||-1===Javatari.SCREEN_FULLSCREEN_MODE&&this.isBrowserStandaloneMode():this.isBrowserStandaloneMode()},isBrowserStandaloneMode:function(){return navigator.standalone||window.matchMedia("(display-mode: standalone)").matches},css:"html.jt-full-screen, html.jt-full-screen body { background: black;}html.jt-full-screen .jt-full-screen-hidden { display: none;}html:not(.jt-full-screen) .jt-full-screen-only { display: none;}"},JavatariFullScreenSetup.apply(),jt.Util=new function(){"use strict";function a(a,b){return a.nameb.name?1:0}function b(a){return a.stopPropagation(),a.cancelable&&a.preventDefault(),!1}this.logs=[],this.log=function(a){var b=[">> jt:"];Array.prototype.push.apply(b,arguments),console.log.apply(console,b)},this.warning=function(a){var b=[">> jt Warning:"];Array.prototype.push.apply(b,arguments),console.warn.apply(console,b)},this.error=function(a){var b=[">> jt Error:"];Array.prototype.push.apply(b,arguments),console.error.apply(console,b)},this.message=function(a){console.info(a),alert(a)},this.asNormalArray=function(a){return a instanceof Array?a:this.arrayCopy(a,0,new Array(a.length))},this.arrayFill=function(a,b,c,d){if(a.fill)return a.fill(b,c,d);void 0===c&&(c=0);for(var e=(void 0===d?a.length:d)-1;e>=c;e-=1)a[e]=b;return a},this.arrayFillSegment=function(a,b,c,d){for(var e=c;e-- >b;)a[e]=d;return a},this.arrayCopy=function(a,b,c,d,e){d=d||0;for(var f=e?b+e:a.length;b=0;)a.splice(c,1);return a},this.arraysConcatAll=function(a){for(var b=0,c=0;c>1|(32&a)>>3|(64&a)>>5|(128&a)>>7},this.int8BitArrayToByteString=function(a,b,c){if(null===a||void 0==a)return a;void 0===b&&(b=0),void 0===c&&(c=a.length-b);for(var d="",e=b,f=b+c;e>8&255)+String.fromCharCode(a[e]>>16&255)+String.fromCharCode(a[e]>>24&255);return d},this.byteStringToInt32BitArray=function(a,b){if(null===a||void 0===a)return a;if("null"==a)return null;if("undefined"!=a){for(var c=a.length/4|0,d=b&&b.length===c?b:new(b?b.constructor:Array)(c),e=0,f=0;e=0&&b.length%2?"0"+b:b},this.toHex4=function(a){if(null===a||void 0===a)return a;var b=a.toString(16).toUpperCase();if(a<0)return b;switch(b.length){case 4:return b;case 3:return"0"+b;case 2:return"00"+b;case 1:return"000"+b;default:return b}},this.escapeHtml=function(a){return a.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/").replace(/\?/g,"?").replace(/\-/g,"-").replace(/\|/g,"|")},this.arrayFind=function(a,b){if(a.find)return a.find(b);for(var c=0,d=a.length;c=0&&h=0?a.split("/").pop():a)||"").trim()},this.leafFilenameNoExtension=function(a){var b=this.leafFilename(a),c=b.lastIndexOf(".");return c<=0?b:b.substr(0,c).trim()},this.leafFilenameOnlyExtension=function(a){var b=this.leafFilename(a),c=b.lastIndexOf(".");return c<=0?"":b.substr(c+1).trim()},this.dump=function(a,b,c,d){var e="",f=b||0;d=d||1;for(var g=0;g0||navigator.msMaxTouchPoints>0},this.isMobileDevice=function(){return this.isTouchDevice()&&/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)},this.isIOSDevice=function(){return/ipad|iphone|ipod/i.test(navigator.userAgent)},this.isBrowserStandaloneMode=function(){return navigator.standalone||window.matchMedia("(display-mode: standalone)").matches},this.onTapOrMouseDown=function(a,b){this.addEventsListener(a,this.isTouchDevice()?"touchstart mousedown":"mousedown",b)},this.onTapOrMouseDownWithBlock=function(a,c){function d(a){return c(a),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart mousedown":"mousedown",d)},this.onTapOrMouseUpWithBlock=function(a,c){function d(a){return c(a),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart mouseup":"mouseup",d)},this.onTapOrMouseDownWithBlockUIG=function(a,c){function d(a){if("touchend"===a.type&&!a.target.jtNeedsUIG)return b(a);var d="touchstart"===a.type&&a.target.jtNeedsUIG,e="touchend"===a.type;return c(a,d,e),b(a)}this.addEventsListener(a,this.isTouchDevice()?"touchstart touchend mousedown":"mousedown",d)},this.blockEvent=b,this.addEventsListener=function(a,b,c,d){b=b.split(" ");for(var e=0;e>>0).toString(16);return"00000000".substr(0,8-b.length)+b}function c(a){for(var b=[],c=0;c<8;c++)b.push(255&a),a>>>=8;return b}function d(a,b){return a<>>32-b}function e(a,b,c){return a&b|~a&c}function f(a,b,c){return c&a|~c&b}function g(a,b,c){return a^b^c}function h(a,b,c){return b^(a|~c)}function i(a,b){return a[b+3]<<24|a[b+2]<<16|a[b+1]<<8|a[b]}function j(a){for(var b=[],c=0;c=0;i--)h=arguments[i],g=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=h,f+=b(g);return f}function l(a){for(var b=new Array(a.length),c=0;c56){for(var l=0;l<64-j;l++)n.push(0);j=n.length%64}for(l=0;l<56-j;l++)n.push(0);n=n.concat(c(8*b));var o=1732584193,p=4023233417,q=2562383102,r=271733878,s=0,t=0,u=0,v=0;for(l=0;l>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\0\0",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if(void 0===a||!a.length)return 0;var e="string"!==c.getTypeOf(a);void 0===b&&(b=0);var f=0,g=0,h=0;b^=-1;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date(1980+(a>>25&127),(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\0",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;gc;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b=void 0!==b&&b,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";return w+="\n\0",w+=p||q?"\0\b":"\0\0",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2),{fileRecord:f.LOCAL_FILE_HEADER+w+m+t,dirRecord:f.CENTRAL_FILE_HEADER+"\0"+w+s(o.length,2)+"\0\0\0\0"+(!0===j?"\0\0\0":"\0\0\0\0")+s(g,4)+m+t+o,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296==(64512&c)&&h>f+1&&56320==(64512&(d=a.charCodeAt(f+1)))&&(c=65536+(c-55296<<10)+(d-56320),f++),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296==(64512&c)&&h>f+1&&56320==(64512&(d=a.charCodeAt(f+1)))&&(c=65536+(c-55296<<10)+(d-56320),f++),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128==(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(128>(e=a[b++]))i[c++]=e;else if((f=g[e])>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length;f>c;){var g=j(a,Math.min(c+65536,f));b.push(k(e.uint8array?a.subarray(c,g):a.slice(c,g))),c=g}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(a){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8), this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44;d>0;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(0!==c)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};l.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:!0===b?4:0,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{ if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),1!==(c=g.deflate(e,d))&&0!==c)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&4===d)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&1!==c);return 4!==d||(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,0===c)},l.prototype.onData=function(a){this.chunks.push(a)},l.prototype.onEnd=function(a){0===a&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=l,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0==(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:!0===b?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),(c=f.inflate(l,i.Z_NO_FLUSH))!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d!==i.Z_FINISH||(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK)},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(a){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(a){g=!1}for(var h=new e.Buf8(256),i=0;256>i;i++)h[i]=i>=252?6:i>=248?5:i>=240?4:i>=224?3:i>=192?2:1;h[254]=h[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296==(64512&c)&&h>f+1&&56320==(64512&(d=a.charCodeAt(f+1)))&&(c=65536+(c-55296<<10)+(d-56320),f++),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296==(64512&c)&&h>f+1&&56320==(64512&(d=a.charCodeAt(f+1)))&&(c=65536+(c-55296<<10)+(d-56320),f++),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,i=b||a.length,j=new Array(2*i);for(e=0,c=0;i>c;)if(128>(f=a[c++]))j[e++]=f;else if((g=h[f])>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&i>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128==(192&a[c]);)c--;return 0>c?b:0===c?b:c+h[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do{e=e+b[d++]|0,f=f+e|0}while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(a,b,c,e){var f=d,g=e+c;a^=-1;for(var h=e;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var d=function(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}();b.exports=c},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-ha?a.strstart-(a.w_size-ha):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ga,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do{if(c=b, j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do{}while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ga-(m-f),f=m-ga,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}}while((b=l[b&k])>i&&0!=--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-ha)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do{d=a.head[--b],a.head[b]=d>=g?d-g:0}while(--c);c=g,b=c;do{d=a.prev[--b],a.prev[b]=d>=g?d-g:0}while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=fa)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return qa;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return qa;if(a.strstart-a.block_start>=a.w_size-ha&&(h(a,!1),0===a.strm.avail_out))return qa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?sa:ta):(a.strstart>a.block_start&&(h(a,!1),a.strm.avail_out),qa)}function o(a,b){for(var c,d;;){if(a.lookahead=fa&&(a.ins_h=(a.ins_h<=fa)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-fa),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=fa){a.match_length--;do{a.strstart++,a.ins_h=(a.ins_h<=fa&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=fa-1)),a.prev_length>=fa&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-fa,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-fa),a.lookahead-=a.prev_length-1,a.prev_length-=2;do{++a.strstart<=e&&(a.ins_h=(a.ins_h<=fa&&a.strstart>0&&(e=a.strstart-1,(d=g[e])===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ga;do{}while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ga-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=fa?(c=D._tr_tally(a,1,a.match_length-fa),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return qa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?sa:ta):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?qa:ra}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return qa;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return qa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?sa:ta):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?qa:ra}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=fa-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*da),this.dyn_dtree=new C.Buf16(2*(2*ba+1)),this.bl_tree=new C.Buf16(2*(2*ca+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(ea+1),this.heap=new C.Buf16(2*aa+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*aa+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?ja:oa,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)} function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===pa&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===ja)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=ka):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,ua),h.status=oa);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=ia),m+=31-m%31,h.status=oa,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===ka)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=la)}else h.status=la;if(h.status===la)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ma)}else h.status=ma;if(h.status===ma)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=na)}else h.status=na;if(h.status===na&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=oa)):h.status=oa),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===pa&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==pa){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===sa||o===ta)&&(h.status=pa),o===qa||o===sa)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===ra&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==ja&&b!==ka&&b!==la&&b!==ma&&b!==na&&b!==oa&&b!==pa?d(a,O):(a.state=null,b===oa?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,aa=286,ba=30,ca=19,da=2*aa+1,ea=15,fa=3,ga=258,ha=ga+fa+1,ia=32,ja=42,ka=69,la=73,ma=91,na=103,oa=113,pa=666,qa=1,ra=2,sa=3,ta=4,ua=3,va=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new va(0,0,0,0,n),new va(4,4,8,4,o),new va(4,5,16,8,o),new va(4,6,32,32,o),new va(4,4,16,16,p),new va(8,16,32,32,p),new va(8,16,128,128,p),new va(8,32,128,256,p),new va(32,128,258,1024,p),new va(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";b.exports=function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A;c=a.state,d=a.next_in,z=a.input,e=d+(a.avail_in-5),f=a.next_out,A=a.output,g=f-(b-a.avail_out),h=f+(a.avail_out-257),i=c.dmax,j=c.wsize,k=c.whave,l=c.wnext,m=c.window,n=c.hold,o=c.bits,p=c.lencode,q=c.distcode,r=(1<o&&(n+=z[d++]<>>24,n>>>=u,o-=u,0===(u=t>>>16&255))A[f++]=65535&t;else{if(!(16&u)){if(0==(64&u)){t=p[(65535&t)+(n&(1<o&&(n+=z[d++]<>>=u,o-=u),15>o&&(n+=z[d++]<>>24,n>>>=u,o-=u,!(16&(u=t>>>16&255))){if(0==(64&u)){t=q[(65535&t)+(n&(1<o&&(n+=z[d++]<o&&(n+=z[d++]<i){a.msg="invalid distance too far back",c.mode=30;break a}if(n>>>=u,o-=u,u=f-g,w>u){if((u=w-u)>k&&c.sane){a.msg="invalid distance too far back",c.mode=30;break a}if(x=0,y=m,0===l){if(x+=j-u,v>u){v-=u;do{A[f++]=m[x++]}while(--u);x=f-w,y=A}}else if(u>l){if(x+=j+l-u,u-=l,v>u){v-=u;do{A[f++]=m[x++]}while(--u);if(x=0,v>l){u=l,v-=u;do{A[f++]=m[x++]}while(--u);x=f-w,y=A}}}else if(x+=l-u,v>u){v-=u;do{A[f++]=m[x++]}while(--u);x=f-w,y=A}for(;v>2;)A[f++]=y[x++],A[f++]=y[x++],A[f++]=y[x++],v-=3;v&&(A[f++]=y[x++],v>1&&(A[f++]=y[x++]))}else{x=f-w;do{A[f++]=A[x++],A[f++]=A[x++],A[f++]=A[x++],v-=3}while(v>2);v&&(A[f++]=A[x++],v>1&&(A[f++]=A[x++]))}break}}break}}while(e>d&&h>f);v=o>>3,d-=v,o-=v<<3,n&=(1<d?e-d+5:5-(d-e),a.avail_out=h>f?h-f+257:257-(f-h),c.hold=n,c.bits=o}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(oa),b.distcode=b.distdyn=new r.Buf32(pa),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=1+(b>>4),48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F} function j(a){return i(a,qa)}function k(a){if(ra){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),ra=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=la;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=la;break}if(m>>>=4,n-=4,wa=8+(15&m),0===c.wbits)c.wbits=wa;else if(wa>c.wbits){a.msg="invalid window size",c.mode=la;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Ba[2]=m>>>16&255,Ba[3]=m>>>24&255,c.check=t(c.check,Ba,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wa=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wa)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do{wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.name+=String.fromCharCode(wa))}while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do{wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.comment+=String.fromCharCode(wa))}while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ia;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=ba,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=la}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=la;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=1+(31&m),m>>>=5,n-=5,c.ncode=4+(15&m),m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=la;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Ca[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,ya={bits:c.lenbits},xa=v(w,c.lens,0,19,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid code lengths set",c.mode=la;break}c.have=0,c.mode=aa;case aa:for(;c.have>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<sa)m>>>=qa,n-=qa,c.lens[c.have++]=sa;else{if(16===sa){for(za=qa+2;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,0===c.have){a.msg="invalid bit length repeat",c.mode=la;break}wa=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sa){for(za=qa+3;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=3+(7&m),m>>>=3,n-=3}else{for(za=qa+7;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=la;break}for(;q--;)c.lens[c.have++]=wa}}if(c.mode===la)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=la;break}if(c.lenbits=9,ya={bits:c.lenbits},xa=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid literal/lengths set",c.mode=la;break}if(c.distbits=6,c.distcode=c.distdyn,ya={bits:c.distbits},xa=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,ya),c.distbits=ya.bits,xa){a.msg="invalid distances set",c.mode=la;break}if(c.mode=ba,b===B)break a;case ba:c.mode=ca;case ca:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Aa=c.lencode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,c.length=sa,0===ra){c.mode=ha;break}if(32&ra){c.back=-1,c.mode=V;break}if(64&ra){a.msg="invalid literal/length code",c.mode=la;break}c.extra=15&ra,c.mode=da;case da:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=ea;case ea:for(;Aa=c.distcode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,64&ra){a.msg="invalid distance code",c.mode=la;break}c.offset=sa,c.extra=15&ra,c.mode=fa;case fa:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=la;break}c.mode=ga;case ga:if(0===j)break a;if(q=p-j,c.offset>q){if((q=c.offset-q)>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=la;break}q>c.wnext?(q-=c.wnext,oa=c.wsize-q):oa=c.wnext-q,q>c.length&&(q=c.length),pa=c.window}else pa=f,oa=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do{f[h++]=pa[oa++]}while(--q);0===c.length&&(c.mode=ca);break;case ha:if(0===j)break a;f[h++]=c.length,j--,c.mode=ca;break;case ia:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=y;y++)K[y]=0;for(z=0;j>z;z++)K[b[i+z]]++;for(C=x,B=d;B>=1&&0===K[B];B--);if(C>B&&(C=B),0===B)return k[l++]=20971520,k[l++]=20971520,n.bits=1,0;for(A=1;B>A&&0===K[A];A++);for(A>C&&(C=A),F=1,y=1;d>=y;y++)if(F<<=1,0>(F-=K[y]))return-1;if(F>0&&(0===a||1!==B))return-1;for(L[1]=0,y=1;d>y;y++)L[y+1]=L[y]+K[y];for(z=0;j>z;z++)0!==b[i+z]&&(m[L[b[i+z]]++]=z);if(0===a?(I=M=m,t=19):1===a?(I=e,J-=257,M=f,N-=257,t=256):(I=g,M=h,t=-1),H=0,z=0,y=A,s=l,D=C,E=0,q=-1,G=1<852||2===a&&G>592)return 1;for(var O=0;;){O++,u=y-E,m[z]t?(v=M[N+m[z]],w=I[J+m[z]]):(v=96,w=0),o=1<>E)+p]=u<<24|v<<16|w|0}while(0!==p);for(o=1<>=1;if(0!==o?(H&=o-1,H+=o):H=0,z++,0==--K[y]){if(y===B)break;y=b[i+m[z]]}if(y>C&&(H&r)!==q){for(0===E&&(E=C),s+=A,D=y-E,F=1<D+E&&!(0>=(F-=K[D+E]));)D++,F<<=1;if(G+=1<852||2===a&&G>592)return 1;q=H&r,k[q]=C<<24|D<<16|s-l|0}}return 0!==H&&(k[s+H]=y-E<<24|64<<16|0),n.bits=C,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?da[a]:da[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>T-c?(a.bi_buf|=b<>T-a.bi_valid,a.bi_valid+=c-T):(a.bi_buf|=b<>>=1,c<<=1}while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;S>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;R>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)(e=a.heap[--c])>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(S+1),g=0;for(d=1;S>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(S+1);for(c=0,d=0;M-1>d;d++)for(fa[d]=c,a=0;a<1<d;d++)for(ga[d]=e,a=0;a<1<<$[d];a++)da[e++]=d;for(e>>=7;P>d;d++)for(ga[d]=e<<7,a=0;a<1<<$[d]-7;a++)da[256+e++]=d;for(b=0;S>=b;b++)f[b]=0;for(a=0;143>=a;)ba[2*a+1]=8,a++,f[8]++;for(;255>=a;)ba[2*a+1]=9,a++,f[9]++;for(;279>=a;)ba[2*a+1]=7,a++,f[7]++;for(;287>=a;)ba[2*a+1]=8,a++,f[8]++;for(l(ba,O+1,f),a=0;P>a;a++)ca[2*a+1]=5,ca[2*a]=i(a,5);ha=new ka(ba,Z,N+1,O,S),ia=new ka(ca,$,0,P,S),ja=new ka(new Array(0),_,0,Q,U)}function n(a){var b;for(b=0;O>b;b++)a.dyn_ltree[2*b]=0;for(b=0;P>b;b++)a.dyn_dtree[2*b]=0;for(b=0;Q>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*V]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do{c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1)}while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b), l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*W]++):10>=h?a.bl_tree[2*X]++:a.bl_tree[2*Y]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++jj)do{h(a,e,a.bl_tree)}while(0!=--j);else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,W,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,X,a.bl_tree),g(a,j-3,3)):(h(a,Y,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=Q-1;b>=3&&0===a.bl_tree[2*aa[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*aa[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;N>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){ma||(m(),ma=!0),a.l_desc=new la(a.dyn_ltree,ha),a.d_desc=new la(a.dyn_dtree,ia),a.bl_desc=new la(a.bl_tree,ja),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,V,ba),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,ba,ca)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(ea[c]+N+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=29,N=256,O=N+1+M,P=30,Q=19,R=2*O+1,S=15,T=16,U=7,V=256,W=16,X=17,Y=18,Z=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],$=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],_=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],aa=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ba=new Array(2*(O+2));d(ba);var ca=new Array(2*P);d(ca);var da=new Array(512);d(da);var ea=new Array(256);d(ea);var fa=new Array(M);d(fa);var ga=new Array(P);d(ga);var ha,ia,ja,ka=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},la=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},ma=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}),jt.EmbeddedFiles={get:function(a){var b=this.compressedContent[a];if(void 0!==b)return{name:a,content:jt.Util.uncompressStringBase64ToInt8BitArray(b)};var c=this.diffsContent[a];if(void 0!==c){var d=this.get(c.based);if(void 0!==d){var e=d.content;for(var f in c.diffs)for(var g=c.diffs[f],h=0;h0||(a.success=!0,a.content=jt.Util.arraysConcatAll(a.filesContent),a.onSuccess&&a.onSuccess(a),j())}function i(a,b){a.success=!1,a.error=b;var d="Could not load file: "+a.url+"\nError: "+b;a.onError?(jt.Util.error(d),a.onError(a)):c||jt.Util.message(d),j()}function j(){if(!q){for(var d=0;dd){var j="Maximum total size limit exceeded: "+(d/1024|0)+"KB";return void(c&&c(a,j,!0))}for(i=0;i0){if(p<=0)return void(n=0);g(),--n,--p}}function f(){var a=s*Javatari.AUDIO_SIGNAL_BUFFER_RATIO+k*Javatari.AUDIO_SIGNAL_ADD_FRAMES|0;r.length=a,a>o&&jt.Util.arrayFill(r,0,o,a),o=a,t.bufferSize=o,q=o-2,j.flush()}function g(){r[l]=b.nextSample()*d,++l>=o&&(l=0)}function h(){r[l]=0,++l>=o&&(l=0)}function i(a,b){if(b)for(var c=a;c>0;c-=1)h();else for(var d=a;d>0;d-=1)g();p-=a}var j=this;this.flush=function(){l=0,m=0,p=q},this.setFps=function(a){k=c/a|0,f()},this.audioFinishFrame=function(){if(n>0)for(;n>0;)e();n=k},this.retrieveSamples=function(a,b){var c=q-p,d=a-c;d>0&&(d>p&&(d=p),i(d,b)),t.start=m;var e=c+d;return p+=e,m+=e,m>=o&&(m-=o),t},this.audioClockPulse=e,this.getSampleRate=function(){return c},this.toString=function(){return"AudioSignal "+a},this.setAudioMonitorBufferSize=function(a){s=a,f()},this.name=a;var k,l=0,m=0,n=0,o=0,p=0,q=0,r=jt.Util.arrayFill(new Array(o),0),s=0,t={buffer:r,bufferSize:o,start:0}},jt.M6502=function(){"use strict";function a(){return[ja,function(){Ta("KIL/HLT/JAM")},function(){X--}]}function b(a){return a(function(){Ta("NOP/DOP")})}function c(a){return a(function(){if(T){var a=Z,b=(15&O)+(15&a)+W;b>9&&(b+=6);var c=(O>>4)+(a>>4)+(b>15)<<4;Ka(O+a+W&255),La(c),Ma((O^c)&~(O^a)&128),c>159&&(c+=96),Na(c>255),O=255&(c|15&b)}else{var d=O+Z+W;Na(d>255),Ma((O^d)&(Z^d)&128),O=255&d,Ka(O),La(O)}})}function d(a){return a(function(){O&=Z,Ka(O),La(O)})}function e(a){return a(function(){var a=Z;Ka(O&a),Ma(64&a),La(a)})}function f(a){return a(function(){var a=O-Z&255;Na(O>=Z),Ka(a),La(a)})}function g(a){return a(function(){var a=P-Z&255;Na(P>=Z),Ka(a),La(a)})}function h(a){return a(function(){var a=Q-Z&255;Na(Q>=Z),Ka(a),La(a)})}function i(a){return a(function(){O^=Z,Ka(O),La(O)})}function j(a){return a(function(){O=Z,Ka(O),La(O)})}function k(a){return a(function(){P=Z,Ka(P),La(P)})}function l(a){return a(function(){Q=Z,Ka(Q),La(Q)})}function m(a){return a(function(){O|=Z,Ka(O),La(O)})}function n(a){return a(function(){if(T){var a=Z,b=(15&O)-(15&a)-(1-W),c=(O>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=O-a-(1-W);Na(256&~d),Ma((O^a)&(O^d)&128),Ka(255&d),La(d),O=255&(c<<4|15&b)}else a=255&~Z,d=O+a+W,Na(d>255),Ma((O^d)&(a^d)&128),O=255&d,Ka(O),La(O)})}function o(a){return a(function(){Ta("ANC"),O&=Z,Ka(O),R=W=128&O?1:0})}function p(a){return a(function(){Ta("LAX");var a=Z;O=a,P=a,Ka(a),La(a)})}function q(a){return a(function(){Z=O})}function r(a){return a(function(){Z=P})}function s(a){return a(function(){Z=Q})}function t(a){return a(function(){Ta("SAX"),Z=O&P})}function u(a){return a(function(){Ta("SHA"),Z=O&P&1+(_>>>8)&255})}function v(a){return a(function(){Na(Z>127);var a=Z<<1&255;Z=a,Ka(a),La(a)})}function w(a){return a(function(){var a=Z-1&255;Z=a,Ka(a),La(a)})}function x(a){return a(function(){var a=Z+1&255;Z=a,Ka(a),La(a)})}function y(a){return a(function(){W=1&Z,Z>>>=1,Ka(Z),R=0})}function z(a){return a(function(){var a=Z>127,b=255&(Z<<1|W);Z=b,Na(a),Ka(b),La(b)})}function A(a){return a(function(){var a=1&Z,b=Z>>>1|W<<7;Z=b,Na(a),Ka(b),La(b)})}function B(a){return a(function(){Ta("DCP");var a=Z-1&255;Z=a,a=O-a,Na(a>=0),Ka(a),La(a)})}function C(a){return a(function(){if(Ta("ISB"),Z=Z+1&255,T){var a=Z,b=(15&O)-(15&a)-(1-W),c=(O>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=O-a-(1-W);Na(256&~d),Ma((O^a)&(O^d)&128),Ka(255&d),La(d),O=255&(c<<4|15&b)}else a=255&~Z,d=O+a+W,Na(d>255),Ma((O^d)&(a^d)&128),O=255&d,Ka(O),La(O)})}function D(a){return a(function(){Ta("RLA");var a=Z,b=W;Na(128&a),a=255&(a<<1|b),Z=a,O&=a,Ka(a),La(a)})}function E(a){return a(function(){Ta("RRA");var a=Z,b=W?128:0;if(Na(1&a),a=a>>>1|b,Z=a,T){var c=Z,d=(15&O)+(15&c)+W;d>9&&(d+=6);var e=(O>>4)+(c>>4)+(d>15)<<4;Ka(O+c+W&255),La(e),Ma((O^e)&~(O^c)&128),e>159&&(e+=96),Na(e>255),O=255&(e|15&d)}else{var f=O+Z+W;Na(f>255),Ma((O^f)&(Z^f)&128),O=255&f,Ka(O),La(O)}})}function F(a){return a(function(){Ta("SLO");var a=Z;Na(128&a),a=a<<1&255,Z=a,a|=O,O=a,Ka(a),La(a)})}function G(a){return a(function(){Ta("SRE");var a=Z;Na(1&a),a>>>=1,Z=a,a=255&(O^a),O=a,Ka(a),La(a)})}function H(a,b){var c;return c=a===ha?function(){return V===b}:a===ga?function(){return R===b}:a===ia?function(){return W===b}:function(){return S===b},[ja,na,function(){c()?(ma(),Ia()):ka()},function(){da?(ma(),Ja()):ka()},ka]}var I=this;this.powerOn=function(){this.reset()},this.powerOff=function(){},this.clockPulse=function(){L&&(X++,K[X]())},this.connectBus=function(a){J=a},this.setRDY=function(a){L=a},this.reset=function(){U=1,X=-1,Y=-1,K=la,M=J.read(ea)|J.read(ea+1)<<8,this.setRDY(!0)};var J,K,L=!1,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=-1,Y=-1,Z=0,$=0,_=0,aa=!1,ba=0,ca=0,da=0,ea=65532,fa=65534,ga=7,ha=1,ia=0;this.debug=!1,this.trace=!1;var ja=function(){Y=J.read(M),K=nb[Y],X=0,M++},ka=ja,la=[ja],ma=function(){J.read(M)},na=function(){ca=J.read(M),M++},oa=function(){$=J.read(M),M++},pa=function(){$|=J.read(M)<<8,M++},qa=function(){$=J.read(_)},ra=function(){$|=J.read(_)<<8},sa=function(){_=J.read(M),M++},ta=function(){_|=J.read(M)<<8,M++},ua=function(){_=J.read(ba)},va=function(){_|=J.read(ba)<<8},wa=function(){var a=(255&_)+P;aa=a>255,_=65280&_|255&a},xa=function(){var a=(255&_)+Q;aa=a>255,_=65280&_|255&a},ya=function(){var a=1+(255&_);aa=a>255,_=65280&_|255&a},za=function(){aa&&(_=_+256&65535)},Aa=function(){ba=J.read(M),M++},Ba=function(){ba|=J.read(M)<<8,M++},Ca=function(){ba=65280&ba|255&1+(255&ba)},Da=function(){Z=J.read(M),M++},Ea=function(){Z=J.read($)},Fa=function(){Z=J.read(_)},Ga=function(){J.write($,Z)},Ha=function(){J.write(_,Z)},Ia=function(){var a=255&M,b=a+ca&255;da=ca>127?b>a?-256:0:b>>7,S=a>>>6&1,T=a>>>3&1,U=a>>>2&1,V=a>>>1&1,W=1&a},Ta=function(a){I.debug&&I.breakpoint("Illegal Opcode: "+a)},Ua=function(a){return[ja,ma,function(){a(),ka()}]},Va=function(a){return[ja,Da,function(){a(),ka()}]},Wa=function(a){return[ja,oa,Ea,function(){a(),ka()}]},Xa=function(a){return[ja,oa,pa,Ea,function(){a(),ka()}]},Ya=function(a){return[ja,sa,Fa,function(){wa(),qa()},function(){ya(),ra()},Ea,function(){a(),ka()}]},Za=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,ta,function(){b(),Fa(),za()},function(){aa?Fa():(a(),ka())},function(){a(),ka()}]}},$a=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,Fa,function(){b(),Fa()},function(){a(),ka()}]}},_a=function(a){return[ja,Aa,ua,function(){Ca(),va()},function(){xa(),Fa(),za()},function(){aa?Fa():(a(),ka())},function(){a(),ka()}]},ab=function(a){return[ja,oa,function(){a(),Ga()},ka]},bb=function(a){return[ja,oa,pa,function(){a(),Ga()},ka]},cb=function(a){return[ja,sa,Fa,function(){wa(),qa()},function(){ya(),ra()},function(){a(),Ga()},ka]},db=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,ta,function(){b(),Fa(),za()},function(){a(),Ha()},ka]}},eb=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,Fa,function(){b(),a(),Ha()},ka]}},fb=function(a){return[ja,Aa,ua,function(){Ca(),va()},function(){xa(),Fa(),za()},function(){a(),Ha()},ka]},gb=function(a){return[ja,oa,Ea,Ga,function(){a(),Ga()},ka]},hb=function(a){return[ja,oa,pa,Ea,Ga,function(){a(),Ga()},ka]},ib=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,Fa,function(){b(),Fa()},Ha,function(){a(),Ha()},ka]}},jb=function(a){var b=0===a?wa:xa;return function(a){return[ja,sa,ta,function(){b(),Fa(),za()},Fa,Ha,function(){a(),Ha()},ka]} },kb=function(a){return[ja,sa,Fa,function(){wa(),qa()},function(){ya(),ra()},Ea,Ga,function(){a(),Ga()},ka]},lb=function(a){return[ja,Aa,ua,function(){Ca(),va()},function(){xa(),Fa(),za()},Fa,Ha,function(){a(),Ha()},ka]},mb=new Array(256),nb=new Array(256);mb[0]="BRK",nb[0]=function(){return[ja,Da,function(){I.debug&&I.breakpoint("BRK "+Z),Qa(M>>>8&255)},function(){Qa(255&M)},function(){Qa(Ra())},function(){$=J.read(fa)},function(){$|=J.read(fa+1)<<8},function(){M=$,ka()}]}(),mb[1]="ORA",nb[1]=m(Ya),mb[2]="uKIL",nb[2]=a(),mb[3]="uSLO",nb[3]=F(kb),mb[4]="uNOP",nb[4]=b(Wa),mb[5]="ORA",nb[5]=m(Wa),mb[6]="ASL",nb[6]=v(gb),mb[7]="uSLO",nb[7]=F(gb),mb[8]="PHP",nb[8]=function(){return[ja,ma,function(){Qa(Ra())},ka]}(),mb[9]="ORA",nb[9]=m(Va),mb[10]="ASL",nb[10]=function(){return Ua(function(){Na(O>127),O=O<<1&255,Ka(O),La(O)})}(),mb[11]="uANC",nb[11]=o(Va),mb[12]="uNOP",nb[12]=b(Xa),mb[13]="ORA",nb[13]=m(Xa),mb[14]="ASL",nb[14]=v(hb),mb[15]="uSLO",nb[15]=F(hb),mb[16]="BPL",nb[16]=H(ga,0),mb[17]="ORA",nb[17]=m(_a),mb[18]="uKIL",nb[18]=a(),mb[19]="uSLO",nb[19]=F(lb),mb[20]="uNOP",nb[20]=b($a(0)),mb[21]="ORA",nb[21]=m($a(0)),mb[22]="ASL",nb[22]=v(ib(0)),mb[23]="uSLO",nb[23]=F(ib(0)),mb[24]="CLC",nb[24]=function(){return Ua(function(){W=0})}(),mb[25]="ORA",nb[25]=m(Za(1)),mb[26]="uNOP",nb[26]=b(Ua),mb[27]="uSLO",nb[27]=F(jb(1)),mb[28]="uNOP",nb[28]=b(Za(0)),mb[29]="ORA",nb[29]=m(Za(0)),mb[30]="ASL",nb[30]=v(jb(0)),mb[31]="uSLO",nb[31]=F(jb(0)),mb[32]="JSR",nb[32]=function(){return[ja,oa,Pa,function(){Qa(M>>>8&255)},function(){Qa(255&M)},pa,function(){M=$,ka()}]}(),mb[33]="AND",nb[33]=d(Ya),mb[34]="uKIL",nb[34]=a(),mb[35]="uRLA",nb[35]=D(kb),mb[36]="BIT",nb[36]=e(Wa),mb[37]="AND",nb[37]=d(Wa),mb[38]="ROL",nb[38]=z(gb),mb[39]="uRLA",nb[39]=D(gb),mb[40]="PLP",nb[40]=function(){return[ja,ma,Pa,function(){Sa(Oa())},ka]}(),mb[41]="AND",nb[41]=d(Va),mb[42]="ROL",nb[42]=function(){return Ua(function(){var a=O>127;O=255&(O<<1|W),Na(a),Ka(O),La(O)})}(),mb[43]="uANC",nb[43]=o(Va),mb[44]="BIT",nb[44]=e(Xa),mb[45]="AND",nb[45]=d(Xa),mb[46]="ROL",nb[46]=z(hb),mb[47]="uRLA",nb[47]=D(hb),mb[48]="BMI",nb[48]=H(ga,1),mb[49]="AND",nb[49]=d(_a),mb[50]="uKIL",nb[50]=a(),mb[51]="uRLA",nb[51]=D(lb),mb[52]="uNOP",nb[52]=b($a(0)),mb[53]="AND",nb[53]=d($a(0)),mb[54]="ROL",nb[54]=z(ib(0)),mb[55]="uRLA",nb[55]=D(ib(0)),mb[56]="SEC",nb[56]=function(){return Ua(function(){W=1})}(),mb[57]="AND",nb[57]=d(Za(1)),mb[58]="uNOP",nb[58]=b(Ua),mb[59]="uRLA",nb[59]=D(jb(1)),mb[60]="uNOP",nb[60]=b(Za(0)),mb[61]="AND",nb[61]=d(Za(0)),mb[62]="ROL",nb[62]=z(jb(0)),mb[63]="uRLA",nb[63]=D(jb(0)),mb[64]="RTI",nb[64]=function(){return[ja,ma,Pa,function(){Sa(Oa())},function(){$=Oa()},function(){$|=Oa()<<8},function(){M=$,ka()}]}(),mb[65]="EOR",nb[65]=i(Ya),mb[66]="uKIL",nb[66]=a(),mb[67]="uSRE",nb[67]=G(kb),mb[68]="uNOP",nb[68]=b(Wa),mb[69]="EOR",nb[69]=i(Wa),mb[70]="LSR",nb[70]=y(gb),mb[71]="uSRE",nb[71]=G(gb),mb[72]="PHA",nb[72]=function(){return[ja,ma,function(){Qa(O)},ka]}(),mb[73]="EOR",nb[73]=i(Va),mb[74]="LSR",nb[74]=function(){return Ua(function(){W=1&O,O>>>=1,Ka(O),R=0})}(),mb[75]="uASR",nb[75]=function(a){return a(function(){Ta("ASR");var a=O&Z;W=1&a,a>>>=1,O=a,Ka(a),R=0})}(Va),mb[76]="JMP",nb[76]=function(){return[ja,oa,pa,function(){M=$,ka()}]}(),mb[77]="EOR",nb[77]=i(Xa),mb[78]="LSR",nb[78]=y(hb),mb[79]="uSRE",nb[79]=G(hb),mb[80]="BVC",nb[80]=H(6,0),mb[81]="EOR",nb[81]=i(_a),mb[82]="uKIL",nb[82]=a(),mb[83]="uSRE",nb[83]=G(lb),mb[84]="uNOP",nb[84]=b($a(0)),mb[85]="EOR",nb[85]=i($a(0)),mb[86]="LSR",nb[86]=y(ib(0)),mb[87]="uSRE",nb[87]=G(ib(0)),mb[88]="CLI",nb[88]=function(){return Ua(function(){U=0})}(),mb[89]="EOR",nb[89]=i(Za(1)),mb[90]="uNOP",nb[90]=b(Ua),mb[91]="uSRE",nb[91]=G(jb(1)),mb[92]="uNOP",nb[92]=b(Za(0)),mb[93]="EOR",nb[93]=i(Za(0)),mb[94]="LSR",nb[94]=y(jb(0)),mb[95]="uSRE",nb[95]=G(jb(0)),mb[96]="RTS",nb[96]=function(){return[ja,ma,Pa,function(){$=Oa()},function(){$|=Oa()<<8},function(){M=$,Da()},ka]}(),mb[97]="ADC",nb[97]=c(Ya),mb[98]="uKIL",nb[98]=a(),mb[99]="uRRA",nb[99]=E(kb);mb[100]="uNOP",nb[100]=b(Wa),mb[101]="ADC",nb[101]=c(Wa),mb[102]="ROR",nb[102]=A(gb),mb[103]="uRRA",nb[103]=E(gb),mb[104]="PLA",nb[104]=function(){return[ja,ma,Pa,function(){O=Oa(),Ka(O),La(O)},ka]}(),mb[105]="ADC",nb[105]=c(Va),mb[106]="ROR",nb[106]=function(){return Ua(function(){var a=1&O;O=O>>>1|W<<7,Na(a),Ka(O),La(O)})}(),mb[107]="uARR",nb[107]=function(a){return a(function(){Ta("ARR");var a=O&Z;a=a>>>1|(W?128:0),O=a,Ka(a),La(a);var b=96&O;96==b?(W=1,S=0):0==b?(W=0,S=0):32==b?(W=0,S=1):64==b&&(W=1,S=1)})}(Va),mb[108]="JMP",nb[108]=function(){return[ja,Aa,Ba,ua,function(){Ca(),va()},function(){M=_,ka()}]}(),mb[109]="ADC",nb[109]=c(Xa),mb[110]="ROR",nb[110]=A(hb),mb[111]="uRRA",nb[111]=E(hb),mb[112]="BVS",nb[112]=H(6,1),mb[113]="ADC",nb[113]=c(_a),mb[114]="uKIL",nb[114]=a(),mb[115]="uRRA",nb[115]=E(lb),mb[116]="uNOP",nb[116]=b($a(0)),mb[117]="ADC",nb[117]=c($a(0)),mb[118]="ROR",nb[118]=A(ib(0)),mb[119]="uRRA",nb[119]=E(ib(0)),mb[120]="SEI",nb[120]=function(){return Ua(function(){U=1})}(),mb[121]="ADC",nb[121]=c(Za(1)),mb[122]="uNOP",nb[122]=b(Ua),mb[123]="uRRA",nb[123]=E(jb(1)),mb[124]="uNOP",nb[124]=b(Za(0)),mb[125]="ADC",nb[125]=c(Za(0)),mb[126]="ROR",nb[126]=A(jb(0)),mb[127]="uRRA",nb[127]=E(jb(0)),mb[128]="uNOP",nb[128]=b(Va),mb[129]="STA",nb[129]=q(cb),mb[130]="uNOP",nb[130]=b(Va),mb[131]="uSAX",nb[131]=t(cb),mb[132]="STY",nb[132]=s(ab),mb[133]="STA",nb[133]=q(ab),mb[134]="STX",nb[134]=r(ab),mb[135]="uSAX",nb[135]=t(ab),mb[136]="DEY",nb[136]=function(){return Ua(function(){Q=Q-1&255,Ka(Q),La(Q)})}(),mb[137]="uNOP",nb[137]=b(Va),mb[138]="TXA",nb[138]=function(){return Ua(function(){O=P,Ka(O),La(O)})}(),mb[139]="uANE",nb[139]=function(a){return a(function(){Ta("ANE")})}(Va),mb[140]="STY",nb[140]=s(bb),mb[141]="STA",nb[141]=q(bb),mb[142]="STX",nb[142]=r(bb),mb[143]="uSAX",nb[143]=t(bb),mb[144]="BCC",nb[144]=H(ia,0),mb[145]="STA",nb[145]=q(fb),mb[146]="uKIL",nb[146]=a(),mb[147]="uSHA",nb[147]=u(fb),mb[148]="STY",nb[148]=s(eb(0)),mb[149]="STA",nb[149]=q(eb(0)),mb[150]="STX",nb[150]=r(eb(1)),mb[151]="uSAX",nb[151]=t(eb(1)),mb[152]="TYA",nb[152]=function(){return Ua(function(){O=Q,Ka(O),La(O)})}(),mb[153]="STA",nb[153]=q(db(1)),mb[154]="TXS",nb[154]=function(){return Ua(function(){N=P})}(),mb[155]="uSHS",nb[155]=function(a){return a(function(){Ta("SHS");var a=O&P;N=a,Z=a&1+(_>>>8)&255})}(db(1)),mb[156]="uSHY",nb[156]=function(a){return a(function(){Ta("SHY"),Z=Q&1+(_>>>8)&255})}(db(0)),mb[157]="STA",nb[157]=q(db(0)),mb[158]="uSHX",nb[158]=function(a){return a(function(){Ta("SHX"),Z=P&1+(_>>>8)&255})}(db(1)),mb[159]="uSHA",nb[159]=u(db(1)),mb[160]="LDY",nb[160]=l(Va),mb[161]="LDA",nb[161]=j(Ya),mb[162]="LDX",nb[162]=k(Va),mb[163]="uLAX",nb[163]=p(Ya),mb[164]="LDY",nb[164]=l(Wa),mb[165]="LDA",nb[165]=j(Wa),mb[166]="LDX",nb[166]=k(Wa),mb[167]="uLAX",nb[167]=p(Wa),mb[168]="TAY",nb[168]=function(){return Ua(function(){Q=O,Ka(Q),La(Q)})}(),mb[169]="LDA",nb[169]=j(Va),mb[170]="TAX",nb[170]=function(){return Ua(function(){P=O,Ka(P),La(P)})}(),mb[171]="uLXA",nb[171]=function(a){return a(function(){Ta("LXA");var a=O&Z;O=a,P=a,Ka(a),La(a)})}(Va),mb[172]="LDY",nb[172]=l(Xa),mb[173]="LDA",nb[173]=j(Xa),mb[174]="LDX",nb[174]=k(Xa),mb[175]="uLAX",nb[175]=p(Xa),mb[176]="BCS",nb[176]=H(ia,1),mb[177]="LDA",nb[177]=j(_a),mb[178]="uKIL",nb[178]=a(),mb[179]="uLAX",nb[179]=p(_a),mb[180]="LDY",nb[180]=l($a(0)),mb[181]="LDA",nb[181]=j($a(0)),mb[182]="LDX",nb[182]=k($a(1)),mb[183]="uLAX",nb[183]=p($a(1)),mb[184]="CLV",nb[184]=function(){return Ua(function(){S=0})}(),mb[185]="LDA",nb[185]=j(Za(1)),mb[186]="TSX",nb[186]=function(){return Ua(function(){P=N,Ka(P),La(P)})}(),mb[187]="uLAS",nb[187]=function(a){return a(function(){Ta("LAS");var a=N&Z;O=a,P=a,N=a,Ka(a),La(a)})}(Za(1)),mb[188]="LDY",nb[188]=l(Za(0)),mb[189]="LDA",nb[189]=j(Za(0)),mb[190]="LDX",nb[190]=k(Za(1)),mb[191]="uLAX",nb[191]=p(Za(1)),mb[192]="CPY",nb[192]=h(Va), mb[193]="CMP",nb[193]=f(Ya),mb[194]="uNOP",nb[194]=b(Va),mb[195]="uDCP",nb[195]=B(kb),mb[196]="CPY",nb[196]=h(Wa),mb[197]="CMP",nb[197]=f(Wa),mb[198]="DEC",nb[198]=w(gb),mb[199]="uDCP",nb[199]=B(gb);mb[200]="INY",nb[200]=function(){return Ua(function(){Q=Q+1&255,Ka(Q),La(Q)})}(),mb[201]="CMP",nb[201]=f(Va),mb[202]="DEX",nb[202]=function(){return Ua(function(){P=P-1&255,Ka(P),La(P)})}(),mb[203]="uSBX",nb[203]=function(a){return a(function(){Ta("SBX");var a=O&P,b=Z,c=a-b&255;P=c,Na(a>=b),Ka(c),La(c)})}(Va),mb[204]="CPY",nb[204]=h(Xa),mb[205]="CMP",nb[205]=f(Xa),mb[206]="DEC",nb[206]=w(hb),mb[207]="uDCP",nb[207]=B(hb),mb[208]="BNE",nb[208]=H(ha,0),mb[209]="CMP",nb[209]=f(_a),mb[210]="uKIL",nb[210]=a(),mb[211]="uDCP",nb[211]=B(lb),mb[212]="uNOP",nb[212]=b($a(0)),mb[213]="CMP",nb[213]=f($a(0)),mb[214]="DEC",nb[214]=w(ib(0)),mb[215]="uDCP",nb[215]=B(ib(0)),mb[216]="CLD",nb[216]=function(){return Ua(function(){T=0})}(),mb[217]="CMP",nb[217]=f(Za(1)),mb[218]="uNOP",nb[218]=b(Ua),mb[219]="uDCP",nb[219]=B(jb(1)),mb[220]="uNOP",nb[220]=b(Za(0)),mb[221]="CMP",nb[221]=f(Za(0)),mb[222]="DEC",nb[222]=w(jb(0)),mb[223]="uDCP",nb[223]=B(jb(0)),mb[224]="CPX",nb[224]=g(Va),mb[225]="SBC",nb[225]=n(Ya),mb[226]="uNOP",nb[226]=b(Va),mb[227]="uISB",nb[227]=C(kb),mb[228]="CPX",nb[228]=g(Wa),mb[229]="SBC",nb[229]=n(Wa),mb[230]="INC",nb[230]=x(gb),mb[231]="uISB",nb[231]=C(gb),mb[232]="newINX",nb[232]=function(){return Ua(function(){P=P+1&255,Ka(P),La(P)})}(),mb[233]="SBC",nb[233]=n(Va),mb[234]="NOP",nb[234]=function(){return Ua(function(){})}(),mb[235]="SBC",nb[235]=n(Va),mb[236]="CPX",nb[236]=g(Xa),mb[237]="SBC",nb[237]=n(Xa),mb[238]="INC",nb[238]=x(hb),mb[239]="uISB",nb[239]=C(hb),mb[240]="BEQ",nb[240]=H(ha,1),mb[241]="SBC",nb[241]=n(_a),mb[242]="uKIL",nb[242]=a(),mb[243]="uISB",nb[243]=C(lb),mb[244]="uNOP",nb[244]=b($a(0)),mb[245]="SBC",nb[245]=n($a(0)),mb[246]="INC",nb[246]=x(ib(0)),mb[247]="uISB",nb[247]=C(ib(0)),mb[248]="SED",nb[248]=function(){return Ua(function(){T=1})}(),mb[249]="SBC",nb[249]=n(Za(1)),mb[250]="uNOP",nb[250]=b(Ua),mb[251]="uISB",nb[251]=C(jb(1)),mb[252]="uNOP",nb[252]=b(Za(0)),mb[253]="SBC",nb[253]=n(Za(0)),mb[254]="INC",nb[254]=x(jb(0)),mb[255]="uISB",nb[255]=C(jb(0)),this.saveState=function(){return{PC:M,A:O,X:P,Y:Q,SP:N,N:R,V:S,D:T,I:U,Z:V,C:W,T:X,o:Y,R:0|L,d:Z,AD:$,BA:_,BC:0|aa,IA:ba,bo:ca,boa:da}},this.loadState=function(a){M=a.PC,O=a.A,P=a.X,Q=a.Y,N=a.SP,R=a.N,S=a.V,T=a.D,U=a.I,V=a.Z,W=a.C,X=a.T,Y=a.o,L=!!a.R,Z=a.d,$=a.AD,_=a.BA,aa=!!a.BC,ba=a.IA,ca=a.bo,da=a.boa,K=-1===Y?la:nb[Y]},this.toString=function(){return"CPU PC: "+M.toString(16)+" op: "+Y.toString()+" T: "+X+" data: "+Z+"\n A: "+O.toString(16)+" X: "+P.toString(16)+" Y: "+Q.toString(16)+" SP: "+N.toString(16)+" N"+R+" V"+S+" D"+T+" I"+U+" Z"+V+" C"+W+" "},this.breakpoint=function(a){if(jt.Util.log(a),this.trace){var b="CPU Breakpoint! "+(a?"("+a+")":"")+"\n\n"+this.toString();jt.Util.message(b)}},this.runCycles=function(a){for(var b=performance.now(),c=0;c=0;b--)a[b]=256*Math.random()|0}()},jt.Pia=function(){"use strict";this.powerOn=function(){},this.powerOff=function(){},this.clockPulse=function(){--h<=0&&a()},this.connectBus=function(a){g=a},this.read=function(a){var b=a&u;return 4===b||6===b?(c(),o):0===b?k:2===b?m:1===b?l:3===b?n:5===b||7===b?p:0},this.write=function(a,c){var f=a&u;return 4===f?(q=c,void b(c,1)):5===f?(r=c,void b(c,8)):6===f?(s=c,void b(c,64)):7===f?(t=c,void b(c,1024)):2===f?void d(c):3===f?(n=c,void e(">>>> Ineffective Write to PIA SWBCNT: "+c)):0===f?void e(">>>> Unsupported Write to PIA SWCHA: "+c):1===f?void e(">>>> Unsupported Write to PIA SWACNT "+c):0};var a=function(){--o<0?(p|=192,o=255,h=i=1):h=i},b=function(b,c){o=b,p&=63,h=i=j=c,a()},c=function(){p&=191,1===i&&(h=i=j)},d=function(a){m=203&m|34&a},e=function(a){self.debug&&jt.Util.log(a)},f=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case f.JOY0_UP:return void(b?k&=239:k|=16);case f.JOY0_DOWN:return void(b?k&=223:k|=32);case f.PADDLE1_BUTTON:case f.JOY0_LEFT:return void(b?k&=191:k|=64);case f.PADDLE0_BUTTON:case f.JOY0_RIGHT:return void(b?k&=127:k|=128);case f.JOY1_UP:return void(b?k&=254:k|=1);case f.JOY1_DOWN:return void(b?k&=253:k|=2);case f.JOY1_LEFT:return void(b?k&=251:k|=4);case f.JOY1_RIGHT:return void(b?k&=247:k|=8);case f.RESET:return void(b?m&=254:m|=1);case f.SELECT:return void(b?m&=253:m|=2)}if(b)switch(a){case f.BLACK_WHITE:return 0==(8&m)?m|=8:m&=247,void g.getTia().getVideoOutput().showOSD(0!=(8&m)?"COLOR":"B/W",!0);case f.DIFFICULTY0:return 0==(64&m)?m|=64:m&=191,void g.getTia().getVideoOutput().showOSD(0!=(64&m)?"P1 Expert":"P1 Novice",!0);case f.DIFFICULTY1:return 0==(128&m)?m|=128:m&=127,void g.getTia().getVideoOutput().showOSD(0!=(128&m)?"P2 Expert":"P2 Novice",!0)}},this.controlsStateReport=function(a){a[f.BLACK_WHITE]=0==(8&m),a[f.DIFFICULTY0]=0!=(64&m),a[f.DIFFICULTY1]=0!=(128&m),a[f.SELECT]=0==(2&m),a[f.RESET]=0==(1&m)},this.saveState=function(){return{t:h,c:i,l:j,SA:k,SAC:l,SB:m,SBC:n,IT:o,IS:p,T1:q,T8:r,T6:s,T2:t}},this.loadState=function(a){h=a.t,i=a.c,j=a.l,l=a.SAC,m=a.SB,n=a.SBC,o=a.IT,p=a.IS,q=a.T1,r=a.T8,s=a.T6,t=a.T2},this.debug=!1;var g,h=1024,i=1024,j=1024,k=255,l=0,m=11,n=0,o=256*Math.random()|0,p=0,q=0,r=0,s=0,t=0,u=7},function(){"use strict" ;for(var a=[0,4210752,7105644,9474192,11579568,13158600,14474460,16053492,17476,1074276,2393220,3448992,4241592,5296336,6088936,6880508,10352,1328260,2645144,3963052,5016764,6070476,6862044,7915756,6276,1586328,3166380,4745408,6062288,7378144,8431852,9747708,136,2105500,3947696,5789888,7368912,8947936,10526956,11842812,6029432,7610508,8928416,10246320,11563200,12616912,13671644,14725356,7864392,9445472,10763384,12081292,13398176,14451892,15506628,16560340,8650772,9969712,11287628,12605544,13660284,14715028,15507624,16561340,8912896,10231836,11550776,12606544,13661288,14716028,15508624,16562340,8132608,9451548,11031608,12349520,13404264,14457980,15512720,16566436,6040576,7883804,9463864,11306064,12622952,13939836,15256720,16572580,2898944,4742172,6585400,8428624,9745512,11325564,12641424,13958308,15360,2120736,4226112,6069340,7648372,9228428,10806436,12123320,14356,1858612,3701840,5281900,6861956,8178844,9495732,10812616,12332,1855564,3436648,5016708,6596764,7913652,8967372,10284256,10308,1591396,3172484,4490400,5807288,7124176,8178920,9232636],b=[0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,22656,2125972,3966120,5807292,7384268,8700124,10277100,11591932,23620,2127964,3969140,5811340,7389344,8705200,10283204,11599060,13424,2117768,3958944,5801140,7379144,8695004,10273004,11588860,1336320,3440672,5281852,7123032,8701040,10279044,11856028,13171888,1310832,3416200,5258400,7100596,8679624,10257628,11836652,13152508,6052864,7631904,9210940,10789976,12105840,13158532,14474396,15527088,6029424,7610500,8928404,10246312,11563188,12616900,13671632,14725344,7355392,8935452,10515512,11832400,13149288,14465148,15518864,16572580,7340120,8921196,10501248,11819156,13136036,14451892,15506628,16560340,7348224,8928284,10508344,11826256,13142120,14459004,15512720,16566436,8388668,9707604,11025516,12343424,13398164,14451880,15506616,16560328,8912896,10231840,11549756,12605528,13660272,14713988,15506588,16560304,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113],c=new Uint32Array(256),d=new Uint32Array(256),e=0,f=a.length;e>4^a);return x>>>=1,0===b?x&=255:x|=256,a},f=function(){return 1===r?1:u=u?0:1},g=function(){return v},h=function(){return 0==--w&&(w=3,v=v?0:1),v},i=function(){return D[C]},j=function(){return 31==++C&&(C=0),D[C]},k=function(){return i()!==j()?c():b()},l=function(){return d()?c():b()},m=function(){return i()!=j()?h():g()},n=function(){return d()?h():g()},o=a,p=0,q=0,r=1,s=1,t=0,u=1,v=1,w=3,x=511,y=14,z=[1,1,1,1,0,0,0,1,0,0,1,1,0,1,0],A=30,B=[1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0],C=30,D=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0],E=15},jt.Tia=function(pCpu,pPia,audioSocket){"use strict";function init(){generateObjectsLineSprites(),generateObjectsCopiesOffsets()}function renderLineTo(a){var b,c=a>LINE_WIDTH?LINE_WIDTH:a;if(vBlankOn)for(var d=renderClock;d>(f>>2):playfieldPatternR>>(f-80>>2))?h=playfieldColor:i&=PFC),ballEnabled&&(b=f-ballPixel,b<0&&(b+=160),missileBallLineSprites[ballLineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=ballColor):i&=BLC)),player0Enabled&&(b=f-player0Pixel,b<0&&(b+=160),playerLineSprites[player0LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=player0Color):i&=P0C),missile0Enabled&&(b=f-missile0Pixel,b<0&&(b+=160),missileBallLineSprites[missile0LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=missile0Color):i&=M0C),player1Enabled&&(b=f-player1Pixel,b<0&&(b+=160),playerLineSprites[player1LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=player1Color):i&=P1C),missile1Enabled&&(b=f-missile1Pixel,b<0&&(b+=160),missileBallLineSprites[missile1LineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=missile1Color):i&=M1C),playfieldPriority||(playfieldEnabled&&(f<80?playfieldPatternL>>(f>>2)&1?h||(h=playfieldLeftColor):i&=PFC:playfieldPatternR>>(f-80>>2)&1?h||(h=playfieldRightColor):i&=PFC),ballEnabled&&(b=f-ballPixel,b<0&&(b+=160),missileBallLineSprites[ballLineSpritePointer+(b>>3)]>>(7&b)&1?h||(h=ballColor):i&=BLC)),linePixels[f+HBLANK_DURATION]=h||playfieldBackground,e|=i}debugNoCollisions||(collisions=e)}}function changeAt(a){vBlankOn||(a>renderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(a),renderClock=a),changeClock=renderClock)}function changeAtClock(){changeAt(clock)}function changeAtClockPlus(a){changeAt(clock+a)}function changePlayfieldAtClock(){if(debug&&debugPixel(DEBUG_PF_GR_COLOR),clockrenderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(a),renderClock=a),changeClock=renderClock}function updateToClock(){vBlankOn||clock>renderClock&&((changeClock>=0||changeClockPrevLine>=0)&&renderLineTo(clock),renderClock=clock)}function augmentCollisionsPossible(){collisionsPossible=65534,player0Enabled||(collisionsPossible&=P0C),player1Enabled||(collisionsPossible&=P1C),missile0Enabled||(collisionsPossible&=M0C),missile1Enabled||(collisionsPossible&=M1C),playfieldEnabled||(collisionsPossible&=PFC),ballEnabled||(collisionsPossible&=BLC)}function playfieldUpdateSprite(){playfieldPatternL=PF2<<12|jt.Util.reverseInt8(PF1)<<4|(240&PF0)>>4,playfieldUpdateSpriteR()}function playfieldUpdateSpriteR(){playfieldPatternR=playfieldReflected?jt.Util.reverseInt8(PF0)<<16|PF1<<8|jt.Util.reverseInt8(PF2):playfieldPatternL,0!==playfieldPatternL||0!==playfieldPatternR?(playfieldEnabled=!0,augmentCollisionsPossible()):(playfieldEnabled=!1,collisionsPossible&=PFC)}function ballSetEnabled(a){a?(ballEnabled=!0,augmentCollisionsPossible()):(ballEnabled=!1,collisionsPossible&=BLC)}function player0SetShape(a){if(NUSIZ0!==a){var b=NUSIZ0^a,c=NUSIZ0;NUSIZ0=a;var d=7&a,e=clock=160&&(f-=160);var g=playerScanOffsetsShape[160*(7&c)+f],h=playerScanOffsetsShape[160*d+f];if(h!==g)if(player0Enabled&&changeAtClockPlus(2),player0Alt=player0Pixel>=80?1:2,player0LineSpritePointer+=20,player0AltFrom=f,player0AltLength=playerCopyLengthPerShape[d],192&g)player0AltCopyOffset=191&g;else if(clock=160&&(f-=160),g=missileScanOffsetsShape[160*((48&c)>>1|7&c)+f],(h=missileScanOffsetsShape[160*((48&a)>>1|d)+f])!==g)){missile0Enabled&&changeAtClockPlus(2),missile0Alt=missile0Pixel>=80?1:2,missile0LineSpritePointer+=20,missile0AltFrom=f;var j=(48&a)>>4;missile0AltLength=4+(1<=160&&(f-=160);var g=playerScanOffsetsShape[160*(7&c)+f],h=playerScanOffsetsShape[160*d+f];h!==g&&(player1Enabled&&changeAtClockPlus(2),player1Alt=player1Pixel>=80?1:2,player1LineSpritePointer+=40,player1AltFrom=f,player1AltLength=playerCopyLengthPerShape[d],192&g?player1AltCopyOffset=191&g:clock=160&&(f-=160),g=missileScanOffsetsShape[160*((48&c)>>1|7&c)+f],(h=missileScanOffsetsShape[160*((48&a)>>1|d)+f])!==g)){missile1Enabled&&changeAtClockPlus(2),missile1Alt=missile1Pixel>=80?1:2,missile1LineSpritePointer+=40,missile1AltFrom=f;var i=(48&a)>>4;missile1AltLength=4+(1<>1|7&NUSIZ0)<<6)+(missile0Alt?20:0);missile0LineSpritePointer!==b&&(missile0Enabled?(changeAtClockPlus(a),missile0LineSpritePointer=b,missile0Alt&&missile0DefineAlt()):missile0LineSpritePointer=b)}function missile0SetEnabled(a){a?(missile0Enabled=!0,augmentCollisionsPossible(),missile0Alt&&missile0DefineAlt()):(missile0Enabled=!1,collisionsPossible&=M0C)}function missile0SetResetToPlayer(a){RESMP0!==(2&a)&&(ENAM0?(changeAtClock(),missile0SetEnabled(!(RESMP0=2&a))):RESMP0=2&a,RESMP0||(missile0Pixel=player0Pixel+missileCenterOffsetsPerPlayerSize[7&NUSIZ0])>=160&&(missile0Pixel-=160))}function missile1UpdateSprite(a){var b=(((48&NUSIZ1)>>1|7&NUSIZ1)<<6)+(missile1Alt?40:0);missile1LineSpritePointer!==b&&(missile1Enabled?(changeAtClockPlus(a),missile1LineSpritePointer=b,missile1Alt&&missile1DefineAlt()):missile1LineSpritePointer=b)}function missile1SetEnabled(a){a?(missile1Enabled=!0,augmentCollisionsPossible(),missile1Alt&&missile1DefineAlt()):(missile1Enabled=!1,collisionsPossible&=M1C)}function missile1SetResetToPlayer(a){RESMP1!==(2&a)&&(ENAM1?(changeAtClock(),missile1SetEnabled(!(RESMP1=2&a))):RESMP1=2&a,RESMP1||(missile1Pixel=player1Pixel+missileCenterOffsetsPerPlayerSize[7&NUSIZ1])>=160&&(missile1Pixel-=160))}function player0DefineAlt(){var a=player0AltFrom<<16|player0AltLength<<8|player0AltCopyOffset,b=player0LineSpritePointer-20>>6;if(player0AltControl[b]!==a){for(var c=player0LineSpritePointer-20,d=0;d<20;++d)playerLineSprites[player0LineSpritePointer+d]=playerLineSprites[c+d];var e=player0AltFrom;if(128&player0AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ0];for(var g=player0AltCopyOffset,h=player0AltCopyOffset+player0AltLength;g>3)]>>(7&g)&1?playerLineSprites[player0LineSpritePointer+(e>>3)]|=1<<(7&e):playerLineSprites[player0LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}player0AltControl[b]=a}}function player1DefineAlt(){var a=player1AltFrom<<16|player1AltLength<<8|player1AltCopyOffset,b=player1LineSpritePointer-40>>6;if(player1AltControl[b]!==a){for(var c=player1LineSpritePointer-40,d=0;d<20;++d)playerLineSprites[player1LineSpritePointer+d]=playerLineSprites[c+d];var e=player1AltFrom;if(128&player1AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ1];for(var g=player1AltCopyOffset,h=player1AltCopyOffset+player1AltLength;g>3)]>>(7&g)&1?playerLineSprites[player1LineSpritePointer+(e>>3)]|=1<<(7&e):playerLineSprites[player1LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}player1AltControl[b]=a}}function missile0DefineAlt(){var a=missile0AltFrom<<16|missile0AltLength<<8|missile0AltCopyOffset,b=missile0LineSpritePointer-20>>6;if(missile0AltControl[b]!==a){for(var c=missile0LineSpritePointer-20,d=0;d<20;++d)missileBallLineSprites[missile0LineSpritePointer+d]=missileBallLineSprites[c+d];var e=missile0AltFrom;if(128&missile0AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ0];for(var g=missile0AltCopyOffset,h=missile0AltCopyOffset+missile0AltLength;g>3)]>>(7&g)&1?missileBallLineSprites[missile0LineSpritePointer+(e>>3)]|=1<<(7&e):missileBallLineSprites[missile0LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}missile0AltControl[b]=a}}function missile1DefineAlt(){var a=missile1AltFrom<<16|missile1AltLength<<8|missile1AltCopyOffset,b=missile1LineSpritePointer-40>>6;if(missile1AltControl[b]!==a){for(var c=missile1LineSpritePointer-40,d=0;d<20;++d)missileBallLineSprites[missile1LineSpritePointer+d]=missileBallLineSprites[c+d];var e=missile1AltFrom;if(128&missile1AltCopyOffset)for(var f=0;f>3)]&=~(1<<(7&e)),++e>=160&&(e-=160);else{c-=objectsLineSpritePointerDeltaToSingleCopy[7&NUSIZ1];for(var g=missile1AltCopyOffset,h=missile1AltCopyOffset+missile1AltLength;g>3)]>>(7&g)&1?missileBallLineSprites[missile1LineSpritePointer+(e>>3)]|=1<<(7&e):missileBallLineSprites[missile1LineSpritePointer+(e>>3)]&=~(1<<(7&e)),++e>=160&&(e-=160)}missile1AltControl[b]=a}}function getRESxPixel(){if(clock>=HBLANK_DURATION+(hMoveHitBlank?7:0))return clock-HBLANK_DURATION;if(hMoveHitBlank){if(clock>=HBLANK_DURATION)return-6;var a=clock-hMoveHitClock-4>>2;return a>8?-6:a>1?-(a-2):-(158+a)}return-158} function checkLateHMOVE(){hMoveLateHit?(hMoveLateHit=!1,hMoveHitBlank=hMoveLateHitBlank,performHMOVE()):hMoveHitBlank=!1}function updateExtendedHBLANK(){hMoveHitBlank!==(linePixels[HBLANK_DURATION]===hBlankColor)&&(hMoveHitBlank?linePixels[HBLANK_DURATION]=linePixels[HBLANK_DURATION+1]=linePixels[HBLANK_DURATION+2]=linePixels[HBLANK_DURATION+3]=linePixels[HBLANK_DURATION+4]=linePixels[HBLANK_DURATION+5]=linePixels[HBLANK_DURATION+6]=linePixels[HBLANK_DURATION+7]=hBlankColor:changeClock=HBLANK_DURATION),hMoveHitBlank&&(renderClock=HBLANK_DURATION+8)}function endObjectsAltStatusMidLine(){1===player0Alt&&(player0Enabled&&changeAtClock(),player0Alt=0,player0LineSpritePointer-=20),1===player1Alt&&(player1Enabled&&changeAtClock(),player1Alt=0,player1LineSpritePointer-=40),1===missile0Alt&&(missile0Enabled&&changeAtClock(),missile0Alt=0,missile0LineSpritePointer-=20),1===missile1Alt&&(missile1Enabled&&changeAtClock(),missile1Alt=0,missile1LineSpritePointer-=40)}function endObjectsAltStatusEndOfLine(){2===player0Alt&&(player0Alt=0,player0LineSpritePointer-=20),2===player1Alt&&(player1Alt=0,player1LineSpritePointer-=40),2===missile0Alt&&(missile0Alt=0,missile0LineSpritePointer-=20),2===missile1Alt&&(missile1Alt=0,missile1LineSpritePointer-=40)}function vSyncSet(a){debug?(debugPixel(VSYNC_COLOR),changeAtClock(),vSyncOn=0!=(2&a),vBlankColor=vSyncOn?VSYNC_COLOR:DEBUG_VBLANK_COLOR):vSyncOn=0!=(2&a)}function generateObjectsLineSprites(){function a(a,b,c){for(var d=0;d<8;++d)a[c+d]=b>>d&1}function b(a,b,c){for(var d=0;d<8;++d)a[c+4*d]=a[c+4*d+1]=a[c+4*d+2]=a[c+4*d+3]=b>>d&1}function c(a,b,c,d,e){for(var f=((a<<11|b<<3|c)<<6)+20*d,g=0;g<20;++g)for(var h=0;h<8;++h)e[8*g+h]&&(playerLineSprites[f+g]|=1<>d&1}(e,h,6),c(f,g,5,0,e),b(e,h,6),c(f,g,7,0,e),b(e,0,6)}jt.Util.arrayFill(e,0);for(var i=0;i<4;++i)h=(1<<(1<>1,playerScanOffsetsShape[800+b]=c;for(b=0;b<38;b++)c=b-a[b],playerCopyOffsetsReset[1120+b]=c,c=b<6?64|b:b-6>>2,playerScanOffsetsShape[1120+b]=c;jt.Util.arrayFill(missileCopyOffsetsReset,128),jt.Util.arrayFill(missileScanOffsetsShape,128);for(var d=0;d<=3;++d){var e=4+(1<>d,missileScanOffsetsShape[8*d*160+0+b]=c,missileScanOffsetsShape[8*d*160+160+b]=c,missileScanOffsetsShape[8*d+160+b+16]=c,missileScanOffsetsShape[8*d*160+320+b]=c,missileScanOffsetsShape[8*d+320+b+32]=c,missileScanOffsetsShape[8*d*160+480+b]=c,missileScanOffsetsShape[8*d+480+b+16]=c,missileScanOffsetsShape[8*d*160+480+b+32]=c,missileScanOffsetsShape[8*d*160+640+b]=c,missileScanOffsetsShape[8*d+640+b+64]=c,missileScanOffsetsShape[8*d*160+800+b]=c,missileScanOffsetsShape[8*d*160+960+b]=c,missileScanOffsetsShape[8*d+960+b+32]=c,missileScanOffsetsShape[8*d*160+960+b+64]=c,missileScanOffsetsShape[8*d*160+1120+b]=c}}var self=this;this.powerOn=function(){jt.Util.arrayFill(linePixels,VBLANK_COLOR),jt.Util.arrayFill(debugPixels,0),audioSignal.getChannel0().setVolume(0),audioSignal.getChannel1().setVolume(0),initLatchesAtPowerOn(),hMoveLateHit=!1,changeClock=changeClockPrevLine=-1,audioSignal.powerOn(),powerOn=!0},this.powerOff=function(){powerOn=!1,videoSignal.signalOff(),audioSignal.powerOff()},this.frame=function(){do{clock=0,changeClock=-1,renderClock=HBLANK_DURATION,debug&&(debugLevel>=4?jt.Util.arrayFill(linePixels,4278190080):debugLevel>=2&&debugLevel<4&&(changeClock=0)),checkLateHMOVE(),bus.clockPulse(),cpu.setRDY(!0);for(var a=0;a<22;++a)clock+=3,bus.clockPulse();updateExtendedHBLANK();for(var b=0;b<27;++b)clock+=3,bus.clockPulse();audioSignal.audioClockPulse(),endObjectsAltStatusMidLine();for(var c=0;c<26;++c)clock+=3,bus.clockPulse();audioSignal.audioClockPulse(),finishLine()}while(!videoSignal.nextLine(linePixels,vSyncOn));videoSignal.finishFrame()},this.connectBus=function(a){bus=a},this.getVideoOutput=function(){return videoSignal},this.getAudioOutput=function(){return audioSignal},this.setVideoStandard=function(a){videoSignal.setVideoStandard(a),palette=jt.TiaPalettes[a.name]},this.debug=function(a){debugLevel=a>4?0:a,debug=0!==debugLevel,pia.debug=debug,debug?debugSetColors():debugRestoreColors()},this.showDebugMessage=function(){videoSignal.showOSD(debug?"Debug Level "+debugLevel:"Debug OFF",!0)},this.debugNoCollisions=function(a){debugNoCollisions=!!a},this.getDebugNoCollisions=function(){return debugNoCollisions},this.read=function(a){switch(a&READ_ADDRESS_MASK){case 0:return updateToClock(),(1024&collisions)>>3|(16384&collisions)>>8;case 1:return updateToClock(),(8192&collisions)>>6|(512&collisions)>>3;case 2:return updateToClock(),(4096&collisions)>>5|(2048&collisions)>>5;case 3:return updateToClock(),(256&collisions)>>1|(128&collisions)>>1;case 4:return updateToClock(),(32&collisions)<<2|(16&collisions)<<2;case 5:return updateToClock(),(8&collisions)<<4|(4&collisions)<<4;case 6:return updateToClock(),(2&collisions)<<6;case 7:return updateToClock(),(32768&collisions)>>8|64&collisions;case 8:return INPT0;case 9:return INPT1;case 10:return INPT2;case 11:return INPT3;case 12:return INPT4;case 13:return INPT5;default:return 0}},this.write=function(a,b){switch(a&WRITE_ADDRESS_MASK){case 0:return void vSyncSet(b);case 1:return void vBlankSet(b);case 2:return cpu.setRDY(!1),void(debug&&debugPixel(DEBUG_WSYNC_COLOR));case 9:return void(COLUBK===b||debug||(changeAtClock(),COLUBK=b,playfieldBackground=palette[b]));case 13:return void(PF0!==(240&b)&&(changePlayfieldAtClock(),PF0=240&b,playfieldUpdateSprite()));case 14:return void(PF1!==b&&(changePlayfieldAtClock(),PF1=b, playfieldUpdateSprite()));case 15:return void(PF2!==b&&(changePlayfieldAtClock(),PF2=b,playfieldUpdateSprite()));case 8:return void(COLUPF===b||debug||((playfieldEnabled&&!playfieldScoreMode||ballEnabled)&&changeAtClock(),COLUPF=b,ballColor=palette[b],playfieldScoreMode||(playfieldColor=playfieldLeftColor=playfieldRightColor=ballColor)));case 10:return void(CTRLPF!==b&&playfieldSetShape(b));case 20:return void hitRESBL();case 31:return void(ENABLd!==(2&b)&&(ENABLd=2&b,VDELBL||(changeAtClock(),ballSetEnabled(ENABLd))));case 39:return void(VDELBL!==(1&b)&&(VDELBL=1&b,ENABL!==ENABLd&&(changeAtClock(),ballSetEnabled(VDELBL?ENABL:ENABLd))));case 4:return void player0SetShape(b);case 6:return void(COLUP0===b||debug||(COLUP0=b,(player0Enabled||missile0Enabled||playfieldEnabled&&playfieldScoreMode)&&changeAtClock(),player0Color=missile0Color=palette[b],playfieldScoreMode&&(playfieldLeftColor=player0Color)));case 11:return void(REFP0!==(b>>3&1)&&(REFP0=b>>3&1,player0UpdateSprite(0)));case 16:return void hitRESP0();case 27:return void player0SetSprite(b);case 37:return void(VDELP0!==(1&b)&&(VDELP0=1&b,GRP0!==GRP0d&&player0UpdateSprite(0)));case 5:return void player1SetShape(b);case 7:return void(COLUP1===b||debug||(COLUP1=b,(player1Enabled||missile1Enabled||playfieldEnabled&&playfieldScoreMode)&&changeAtClock(),player1Color=missile1Color=palette[b],playfieldScoreMode&&(playfieldRightColor=player1Color)));case 12:return void(REFP1!==(b>>3&1)&&(REFP1=b>>3&1,player1UpdateSprite(0)));case 17:return void hitRESP1();case 28:return void player1SetSprite(b);case 38:return void(VDELP1!==(1&b)&&(VDELP1=1&b,GRP1!==GRP1d&&player1UpdateSprite(0)));case 18:return void hitRESM0();case 29:return void(ENAM0!==(2&b)&&(ENAM0=2&b,RESMP0||(changeAtClock(),missile0SetEnabled(ENAM0))));case 40:return void missile0SetResetToPlayer(b);case 19:return void hitRESM1();case 30:return void(ENAM1!==(2&b)&&(ENAM1=2&b,RESMP1||(changeAtClock(),missile1SetEnabled(ENAM1))));case 41:return void missile1SetResetToPlayer(b);case 32:return void(HMP0=(b>127?-16:0)+(b>>4));case 33:return void(HMP1=(b>127?-16:0)+(b>>4));case 34:return void(HMM0=(b>127?-16:0)+(b>>4));case 35:return void(HMM1=(b>127?-16:0)+(b>>4));case 36:return void(HMBL=(b>127?-16:0)+(b>>4));case 42:return void hitHMOVE();case 43:return void(HMP0=HMP1=HMM0=HMM1=HMBL=0);case 44:return changeAtClock(),void(collisions=0);case 21:return void(AUDC0!==b&&(AUDC0=b,audioSignal.getChannel0().setControl(15&b)));case 22:return void(AUDC1!==b&&(AUDC1=b,audioSignal.getChannel1().setControl(15&b)));case 23:return void(AUDF0!==b&&(AUDF0=b,audioSignal.getChannel0().setDivider(1+(31&b))));case 24:return void(AUDF1!==b&&(AUDF1=b,audioSignal.getChannel1().setDivider(1+(31&b))));case 25:return void(AUDV0!==b&&(AUDV0=b,audioSignal.getChannel0().setVolume(15&b)));case 26:return void(AUDV1!==b&&(AUDV1=b,audioSignal.getChannel1().setVolume(15&b)))}};var finishLine=function(){changeClock>=0?(renderLineTo(LINE_WIDTH),changeClockPrevLine=changeClock):changeClockPrevLine>=0&&(renderLineTo(changeClockPrevLine),changeClockPrevLine=-1),endObjectsAltStatusEndOfLine(),paddle0Position>=0&&!paddleCapacitorsGrounded&&(INPT0<128&&++paddle0CapacitorCharge>=paddle0Position&&(INPT0|=128),INPT1<128&&++paddle1CapacitorCharge>=paddle1Position&&(INPT1|=128)),debugLevel>=1&&processDebugPixelsInLine()},playfieldSetShape=function(a){if(CTRLPF!==a){var b=7&a;b!==(7&CTRLPF)&&(playfieldEnabled&&changeAtClock(),b=0!=(1&a),playfieldReflected!==b&&(playfieldReflected=b,playfieldUpdateSpriteR()),b=0!=(2&a),playfieldScoreMode!==b&&(playfieldScoreMode=b,debug||(b?(playfieldLeftColor=player0Color,playfieldRightColor=player1Color):playfieldColor=playfieldLeftColor=playfieldRightColor=ballColor)),playfieldPriority=0!=(4&a)),b=48&a,b!==(48&CTRLPF)&&(ballEnabled&&changeAtClock(),ballLineSpritePointer=b>>1<<6),CTRLPF=a}},hitRESP0=function(){debug&&debugPixel(DEBUG_P0_RES_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(player0Pixel!==b){player0Enabled&&changeAtClock();var c=a>=0?b:0,d=c-player0Pixel;d<0&&(d+=160),player0Pixel=b;var e=7&NUSIZ0;if(player0Alt){if(d<=playerCopyLengthPerShape[e])return}else player0LineSpritePointer+=20;var f=c-b;f<-100&&(f+=160),player0Alt=b>=80?1:2,player0AltFrom=f>=0?f:160+f,player0AltLength=playerCopyLengthPerShape[e]-f,player0AltCopyOffset=playerCopyOffsetsReset[160*e+d],player0Enabled&&player0DefineAlt()}},hitRESP1=function(){debug&&debugPixel(DEBUG_P1_RES_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(player1Pixel!==b){player1Enabled&&changeAtClock();var c=a>=0?b:0,d=c-player1Pixel;d<0&&(d+=160),player1Pixel=b;var e=7&NUSIZ1;if(player1Alt){if(d<=playerCopyLengthPerShape[e])return}else player1LineSpritePointer+=40;var f=c-b;f<-100&&(f+=160),player1Alt=b>=80?1:2,player1AltFrom=f>=0?f:160+f,player1AltLength=playerCopyLengthPerShape[e]-f,player1AltCopyOffset=playerCopyOffsetsReset[160*e+d],player1Enabled&&player1DefineAlt()}},hitRESM0=function(){debug&&debugPixel(DEBUG_M0_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;if(missile0Pixel!==b){missile0Enabled&&changeAtClock();var c=a>=0?b:0,d=c-missile0Pixel;if(d<0&&(d+=160),missile0Pixel=b,missile0Alt){if(d<=4+(1<<((48&NUSIZ0)>>4)))return}else missile0LineSpritePointer+=20;var e=c-b;e<-100&&(e+=160),missile0Alt=b>=80?1:2,missile0AltFrom=e>=0?e:160+e,missile0AltLength=4+(1<<((48&NUSIZ0)>>4))-e,missile0AltCopyOffset=missileCopyOffsetsReset[160*((48&NUSIZ0)>>1|7&NUSIZ0)+d],missile0Enabled&&missile0DefineAlt()}},hitRESM1=function(){debug&&debugPixel(DEBUG_M1_COLOR);var a=getRESxPixel(),b=a>=1?a:-a;if(missile1Pixel!==b){missile1Enabled&&changeAtClock();var c=a>=0?b:0,d=c-missile1Pixel;if(d<0&&(d+=160),missile1Pixel=b,missile1Alt){if(d<=4+(1<<((48&NUSIZ1)>>4)))return}else missile1LineSpritePointer+=40;var e=c-b;e<-100&&(e+=160),missile1Alt=b>=80?1:2,missile1AltFrom=e>=0?e:160+e,missile1AltLength=4+(1<<((48&NUSIZ1)>>4))-e,missile1AltCopyOffset=missileCopyOffsetsReset[160*((48&NUSIZ1)>>1|7&NUSIZ1)+d],missile1Enabled&&missile1DefineAlt()}},hitRESBL=function(){debug&&debugPixel(DEBUG_BL_COLOR);var a=getRESxPixel(),b=a>=0?a:-a;ballPixel!==b&&(ballEnabled&&changeAtClock(),ballPixel=b)},hitHMOVE=function(){if(debug&&debugPixel(DEBUG_HMOVE_COLOR),clock=225)},performHMOVE=function(){var a,b=!1;a=hMoveHitBlank?HMP0:HMP0+8,0!==a&&(player0Pixel-=a,player0Pixel>=160?player0Pixel-=160:player0Pixel<0&&(player0Pixel+=160),player0Enabled&&(b=!0)),a=hMoveHitBlank?HMP1:HMP1+8,0!==a&&(player1Pixel-=a,player1Pixel>=160?player1Pixel-=160:player1Pixel<0&&(player1Pixel+=160),player1Enabled&&(b=!0)),a=hMoveHitBlank?HMM0:HMM0+8,0!==a&&(missile0Pixel-=a,missile0Pixel>=160?missile0Pixel-=160:missile0Pixel<0&&(missile0Pixel+=160),missile0Enabled&&(b=!0)),a=hMoveHitBlank?HMM1:HMM1+8,0!==a&&(missile1Pixel-=a,missile1Pixel>=160?missile1Pixel-=160:missile1Pixel<0&&(missile1Pixel+=160),missile1Enabled&&(b=!0)),a=hMoveHitBlank?HMBL:HMBL+8,0!==a&&(ballPixel-=a,ballPixel>=160?ballPixel-=160:ballPixel<0&&(ballPixel+=160),ballEnabled&&(b=!0)),b&&(changeClock=hMoveHitBlank?HBLANK_DURATION+8:HBLANK_DURATION)},vBlankSet=function(a){var b=0!=(2&a);vBlankOn!==b&&(changeVBlankAtClockPlus1(),vBlankOn=b),0!=(64&a)?controlsButtonsLatched=!0:(controlsButtonsLatched=!1,controlsJOY0ButtonPressed?INPT4&=127:INPT4|=128,controlsJOY1ButtonPressed?INPT5&=127:INPT5|=128),0!=(128&a)?(paddleCapacitorsGrounded=!0,paddle0CapacitorCharge=paddle1CapacitorCharge=0,INPT0&=127,INPT1&=127,INPT2&=127,INPT3&=127):paddleCapacitorsGrounded=!1},initLatchesAtPowerOn=function(){collisions=0,INPT0=INPT1=INPT2=INPT3=0,INPT4=INPT5=128},debugPixel=function(a){debugPixels[clock]=a},processDebugPixelsInLine=function(){if(jt.Util.arrayFillSegment(linePixels,0,HBLANK_DURATION+(hMoveHitBlank?8:0),hBlankColor), debugLevel>=3&&videoSignal.monitor.currentLine()%10==0)for(var a=0;a=2)for(a=0;a=1?DEBUG_HBLANK_COLOR:HBLANK_COLOR,vBlankColor=debugLevel>=1?DEBUG_VBLANK_COLOR:VBLANK_COLOR},debugRestoreColors=function(){hBlankColor=HBLANK_COLOR,vBlankColor=VBLANK_COLOR,playfieldBackground=palette[0],jt.Util.arrayFill(linePixels,hBlankColor),changeAtClock()},info=function(a){console.error("Line: "+videoSignal.monitor.currentLine()+", Pixel: "+clock+". "+a)},debugInfo=function(a){debug&&console.error("Line: "+videoSignal.monitor.currentLine()+", Pixel: "+clock+". "+a)},controls=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case controls.JOY0_BUTTON:return void(b?(controlsJOY0ButtonPressed=!0,INPT4&=127):(controlsJOY0ButtonPressed=!1,controlsButtonsLatched||(INPT4|=128)));case controls.JOY1_BUTTON:return void(b?(controlsJOY1ButtonPressed=!0,INPT5&=127):(controlsJOY1ButtonPressed=!1,controlsButtonsLatched||(INPT5|=128)))}if(b)switch(a){case controls.DEBUG:return self.debug(debugLevel+1),void self.showDebugMessage();case controls.SHOW_INFO:return void videoSignal.toggleShowInfo();case controls.NO_COLLISIONS:self.debugNoCollisions(!debugNoCollisions),videoSignal.showOSD(debugNoCollisions?"No Collisions: ON":"No Collisions: OFF",!0)}},this.controlValueChanged=function(a,b){switch(a){case controls.PADDLE0_POSITION:return void(paddle0Position=b);case controls.PADDLE1_POSITION:return void(paddle1Position=b)}},this.saveState=function(a){var b={ccp:changeClockPrevLine,lpx:jt.Util.storeInt32BitArrayToStringBase64(linePixels),vs:vSyncOn,vb:vBlankOn,pfe:playfieldEnabled,pfl:playfieldPatternL,pfr:playfieldPatternR,pfc:playfieldColor,pflc:playfieldLeftColor,pfrc:playfieldRightColor,pfb:playfieldBackground,pfrl:playfieldReflected,pfsc:playfieldScoreMode,pfp:playfieldPriority,be:ballEnabled,bx:ballPixel,blp:ballLineSpritePointer,bc:ballColor,p0e:player0Enabled,p0x:player0Pixel,p0lp:player0LineSpritePointer,p0a:player0Alt,p0af:player0AltFrom,p0al:player0AltLength,p0ao:player0AltCopyOffset,p0c:player0Color,p1e:player1Enabled,p1x:player1Pixel,p1lp:player1LineSpritePointer,p1a:player1Alt,p1af:player1AltFrom,p1al:player1AltLength,p1ao:player1AltCopyOffset,p1c:player1Color,m0e:missile0Enabled,m0x:missile0Pixel,m0lp:missile0LineSpritePointer,m0a:missile0Alt,m0af:missile0AltFrom,m0al:missile0AltLength,m0ao:missile0AltCopyOffset,m0c:missile0Color,m1e:missile1Enabled,m1x:missile1Pixel,m1lp:missile1LineSpritePointer,m1a:missile1Alt,m1af:missile1AltFrom,m1al:missile1AltLength,m1ao:missile1AltCopyOffset,m1c:missile1Color,hmh:hMoveHitBlank,hmc:hMoveHitClock,hmlh:hMoveLateHit,hmlb:hMoveLateHitBlank,co:collisions,cop:collisionsPossible,cod:debugNoCollisions,cbl:controlsButtonsLatched,j0p:controlsJOY0ButtonPressed,j1p:controlsJOY1ButtonPressed,pcg:paddleCapacitorsGrounded,pd0:paddle0Position,pd0c:paddle0CapacitorCharge,pd1:paddle1Position,pd1c:paddle1CapacitorCharge,CTRLPF:CTRLPF,COLUPF:COLUPF,COLUBK:COLUBK,PF0:PF0,PF1:PF1,PF2:PF2,ENABL:ENABL,ENABLd:ENABLd,VDELBL:VDELBL,NUSIZ0:NUSIZ0,COLUP0:COLUP0,REFP0:REFP0,GRP0:GRP0,GRP0d:GRP0d,VDELP0:VDELP0,NUSIZ1:NUSIZ1,COLUP1:COLUP1,REFP1:REFP1,GRP1:GRP1,GRP1d:GRP1d,VDELP1:VDELP1,ENAM0:ENAM0,RESMP0:RESMP0,ENAM1:ENAM1,RESMP1:RESMP1,HMP0:HMP0,HMP1:HMP1,HMM0:HMM0,HMM1:HMM1,HMBL:HMBL,AUDC0:AUDC0,AUDC1:AUDC1,AUDF0:AUDF0,AUDF1:AUDF1,AUDV0:AUDV0,AUDV1:AUDV1};return a&&(b.dl=debugLevel),b},this.loadState=function(a){changeClockPrevLine=a.ccp,jt.Util.restoreStringBase64ToInt32BitArray(a.lpx,linePixels),vSyncOn=a.vs,vBlankOn=a.vb,playfieldEnabled=a.pfe,playfieldPatternL=0|a.pfl,playfieldPatternR=0|a.pfr,playfieldColor=0|a.pfc,playfieldLeftColor=0|a.pflc,playfieldRightColor=0|a.pfrc,playfieldBackground=0|a.pfb,playfieldReflected=a.pfrl,playfieldScoreMode=a.pfsc,playfieldPriority=a.pfp,ballEnabled=a.be,ballPixel=0|a.bx,ballLineSpritePointer=0|a.blp,ballColor=0|a.bc,player0Enabled=a.p0e,player0Pixel=0|a.p0x,player0LineSpritePointer=0|a.p0lp,player0Alt=0|a.p0a,player0AltFrom=0|a.p0af,player0AltLength=0|a.p0al,player0AltCopyOffset=0|a.p0ao,jt.Util.arrayFill(player0AltControl,0),player0Color=0|a.p0c,player1Enabled=a.p1e,player1Pixel=0|a.p1x,player1LineSpritePointer=0|a.p1lp,player1Alt=0|a.p1a,player1AltFrom=0|a.p1af,player1AltLength=0|a.p1al,player1AltCopyOffset=0|a.p1ao,jt.Util.arrayFill(player1AltControl,0),player1Color=0|a.p1c,missile0Enabled=a.m0e,missile0Pixel=0|a.m0x,missile0LineSpritePointer=0|a.m0lp,missile0Alt=0|a.m0a,missile0AltFrom=0|a.m0af,missile0AltLength=0|a.m0al,missile0AltCopyOffset=0|a.m0ao,jt.Util.arrayFill(missile0AltControl,0),missile0Color=0|a.m0c,missile1Enabled=a.m1e,missile1Pixel=0|a.m1x,missile1LineSpritePointer=0|a.m1lp,missile1Alt=0|a.m1a,missile1AltFrom=0|a.m1af,missile1AltLength=0|a.m1al,missile1AltCopyOffset=0|a.m1ao,jt.Util.arrayFill(missile1AltControl,0),missile1Color=0|a.m1c,hMoveHitBlank=a.hmh,hMoveHitClock=0|a.hmc,hMoveLateHit=a.hmlh,hMoveLateHitBlank=a.hmlb,collisions=0|a.co,collisionsPossible=0|a.cop,void 0!==a.cod&&(debugNoCollisions=a.cod),void 0!==a.cbl&&(controlsButtonsLatched=a.cbl,controlsJOY0ButtonPressed=a.j0p,controlsJOY1ButtonPressed=a.j1p,paddleCapacitorsGrounded=a.pcg,paddle0Position=a.pd0,paddle0CapacitorCharge=a.pd0c,paddle1Position=a.pd1,paddle1CapacitorCharge=a.pd1c),CTRLPF=0|a.CTRLPF,COLUPF=0|a.COLUPF,COLUBK=0|a.COLUBK,PF0=0|a.PF0,PF1=0|a.PF1,PF2=0|a.PF2,ENABL=0|a.ENABL,ENABLd=0|a.ENABLd,VDELBL=0|a.VDELBL,NUSIZ0=0|a.NUSIZ0,COLUP0=0|a.COLUP0,REFP0=0|a.REFP0,GRP0=0|a.GRP0,GRP0d=0|a.GRP0d,VDELP0=0|a.VDELP0,NUSIZ1=0|a.NUSIZ1,COLUP1=0|a.COLUP1,REFP1=0|a.REFP1,GRP1=0|a.GRP1,GRP1d=0|a.GRP1d,VDELP1=0|a.VDELP1,ENAM0=0|a.ENAM0,RESMP0=0|a.RESMP0,ENAM1=0|a.ENAM1,RESMP1=0|a.RESMP1,HMP0=0|a.HMP0,HMP1=0|a.HMP1,HMM0=0|a.HMM0,HMM1=0|a.HMM1,HMBL=0|a.HMBL,AUDC0=0|a.AUDC0,audioSignal.getChannel0().setControl(15&AUDC0),AUDC1=0|a.AUDC1,audioSignal.getChannel1().setControl(15&AUDC1),AUDF0=0|a.AUDF0,audioSignal.getChannel0().setDivider(1+(31&AUDF0)),AUDF1=0|a.AUDF1,audioSignal.getChannel1().setDivider(1+(31&AUDF1)),AUDV0=0|a.AUDV0,audioSignal.getChannel0().setVolume(15&AUDV0),AUDV1=0|a.AUDV1,audioSignal.getChannel1().setVolume(15&AUDV1),void 0!==a.dl?this.debug(a.dl):debug&&debugSetColors()} ;var HBLANK_DURATION=68,LINE_WIDTH=228,VBLANK_COLOR=4278190080,HBLANK_COLOR=4261412864,VSYNC_COLOR=4292730333,DEBUG_P0_COLOR=4278190335,DEBUG_P0_RES_COLOR=4280427195,DEBUG_P0_GR_COLOR=4279308663,DEBUG_P1_COLOR=4294901760,DEBUG_P1_RES_COLOR=4290454050,DEBUG_P1_GR_COLOR=4285993233,DEBUG_M0_COLOR=4284901119,DEBUG_M1_COLOR=4294927974,DEBUG_PF_COLOR=4282681412,DEBUG_PF_GR_COLOR=4281589043,DEBUG_BK_COLOR=4281549875,DEBUG_BL_COLOR=4278255615,DEBUG_MARKS_COLOR=4280295456,DEBUG_HBLANK_COLOR=4282664004,DEBUG_VBLANK_COLOR=4280953386,DEBUG_WSYNC_COLOR=4287103112,DEBUG_HMOVE_COLOR=4294967295,DEBUG_ALT_COLOR=4289374720,READ_ADDRESS_MASK=15,WRITE_ADDRESS_MASK=63,P0C=-63489,P1C=-34689,M0C=-17521,M1C=-8781,PFC=-4395,BLC=-2199,cpu=pCpu,pia=pPia,bus,powerOn=!1,clock,changeClock,changeClockPrevLine,renderClock,linePixels=new Uint32Array(LINE_WIDTH),vSyncOn=!1,vBlankOn=!1,vBlankColor=VBLANK_COLOR,hBlankColor=HBLANK_COLOR,playfieldEnabled=!1,playfieldPatternL=0,playfieldPatternR=0,playfieldColor=4278190080,playfieldLeftColor=4278190080,playfieldRightColor=4278190080,playfieldBackground=4278190080,playfieldReflected=!1,playfieldScoreMode=!1,playfieldPriority=!1,ballEnabled=!1,ballPixel=0,ballLineSpritePointer=0,ballColor=4278190080,player0Enabled=!1,player0Pixel=0,player0LineSpritePointer=0,player0Alt=0,player0AltFrom=0,player0AltLength=0,player0AltCopyOffset=0,player0AltControl=new Uint32Array(4096),player0Color=4278190080,player1Enabled=!1,player1Pixel=0,player1LineSpritePointer=0,player1Alt=0,player1AltFrom=0,player1AltLength=0,player1AltCopyOffset=0,player1AltControl=new Uint32Array(4096),player1Color=4278190080,missile0Enabled=!1,missile0Pixel=0,missile0LineSpritePointer=0,missile0Alt=0,missile0AltFrom=0,missile0AltLength=0,missile0AltCopyOffset=0,missile0AltControl=new Uint32Array(32),missile0Color=4278190080,missile1Enabled=!1,missile1Pixel=0,missile1LineSpritePointer=0,missile1Alt=0,missile1AltFrom=0,missile1AltLength=0,missile1AltCopyOffset=0,missile1AltControl=new Uint32Array(32),missile1Color=4278190080,hMoveHitBlank=!1,hMoveHitClock=0,hMoveLateHit=!1,hMoveLateHitBlank=!1,collisions=0,collisionsPossible=0,controlsButtonsLatched=!1,controlsJOY0ButtonPressed=!1,controlsJOY1ButtonPressed=!1,paddleCapacitorsGrounded=!1,paddle0Position=-1,paddle0CapacitorCharge=0,paddle1Position=-1,paddle1CapacitorCharge=0,debug=!1,debugLevel=0,debugNoCollisions=!1,debugPixels=new Uint32Array(LINE_WIDTH),playerLineSprites=new Uint8Array(262144),missileBallLineSprites=new Uint8Array(2048),playerCopyLengthPerShape=new Uint8Array([13,13,13,13,13,22,13,38]),playerScanStartPerShape=new Uint8Array([5,5,5,5,5,6,5,6]),playerPixelSizePerShape=new Uint8Array([1,1,1,1,1,2,1,4]),playerCopyOffsetsReset=new Uint8Array(1280),playerScanOffsetsShape=new Uint8Array(1280),missileCopyOffsetsReset=new Uint8Array(5120),missileScanOffsetsShape=new Uint8Array(5120),objectsLineSpritePointerDeltaToSingleCopy=new Uint16Array([0,64,128,192,256,0,384,0]),missileCenterOffsetsPerPlayerSize=new Uint8Array([5,5,5,5,5,10,5,18]),videoSignal=new jt.VideoSignal,palette,audioSignal=new jt.TiaAudio(audioSocket),INPT0=0,INPT1=0,INPT2=0,INPT3=0,INPT4=0,INPT5=0,CTRLPF=0,COLUPF=0,COLUBK=0,PF0=0,PF1=0,PF2=0,ENABL=0,ENABLd=0,VDELBL=0,NUSIZ0=0,COLUP0=0,REFP0=0,GRP0=0,GRP0d=0,VDELP0=0,NUSIZ1=0,COLUP1=0,REFP1=0,GRP1=0,GRP1d=0,VDELP1=0,ENAM0=0,RESMP0=0,ENAM1=0,RESMP1=0,HMP0=0,HMP1=0,HMM0=0,HMM1=0,HMBL=0,AUDC0=0,AUDC1=0,AUDF0=0,AUDF1=0,AUDV0=0,AUDV1=0;init(),self.eval=function(code){return eval(code)}},jt.Bus=function(a,b,c,d){"use strict";this.powerOn=function(){null!=i&&i.powerOn(),h.powerOn(),g.powerOn(),e.powerOn(),f.powerOn()},this.powerOff=function(){f.powerOff(),e.powerOff(),g.powerOff(),h.powerOff()},this.setCartridge=function(a){i=a,i&&(k=0,i.connectBus(this)),j=i&&i.needsBusMonitoring()},this.getCartridge=function(){return i},this.getTia=function(){return f},this.clockPulse=function(){g.clockPulse(),e.clockPulse()},this.read=function(a){return j&&i.monitorBusBeforeRead(a),(a&l)===m?i?k=i.read(a):k:k=(a&n)===o?h.read(a):(a&r)===s?g.read(a):63&k|f.read(a)},this.write=function(a,b){j&&i.monitorBusBeforeWrite(a,b),k=b,(a&p)===q?f.write(a,b):(a&n)===o?h.write(a,b):(a&r)===s?g.write(a,b):i&&i.write(a,b)},this.saveState=function(){return{d:k}},this.loadState=function(a){k=a.d};var e,f,g,h,i,j=!1,k=256*Math.random()|0,l=4096,m=4096,n=4736,o=128,p=4224,q=0,r=4736,s=640;!function(i){e=a,f=b,g=c,h=d,e.connectBus(i),f.connectBus(i),g.connectBus(i)}(this)},jt.AtariConsole=function(mainVideoClock){"use strict";function init(){mainComponentsCreate(),socketsCreate()}function videoFrame(){userPaused&&userPauseMoreFrames--<=0||(videoStandardAutoDetectionInProgress&&videoStandardAutoDetectionTry(),tia.frame())}function vSynchToggleMode(){if(-1===vSynchMode)return void self.showOSD("V-Synch is DISABLED / UNSUPPORTED",!0,!0);vSynchMode=vSynchMode?0:1,updateVideoSynchronization(),self.showOSD("V-Synch: "+(vSynchMode?"ON":"OFF"),!0),Javatari.userPreferences.current.vSynch=vSynchMode,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save()}function showVideoStandardMessage(){self.showOSD((videoStandardIsAuto?"AUTO: ":"")+videoStandard.name,!0)}function updateVideoSynchronization(){videoPulldown=1===vSynchMode?videoStandard.pulldowns[videoClockSocket.getVSynchNativeFrequency()]||videoStandard.pulldowns.TIMER:videoStandard.pulldowns.TIMER,videoPulldownStep=0,videoClockUpdateSpeed()}function setDefaults(){setVideoStandardAuto(!0),speedControl=1,alternateSpeed=null,videoClockUpdateSpeed(),tia.debug(0),tia.debugNoCollisions(!1)}function videoClockUpdateSpeed(){videoClockSocket.setVSynch(1===vSynchMode);var a=videoPulldown.frequency*(alternateSpeed||speedControl)|0;videoClockSocket.setFrequency(a,videoPulldown.divider),audioSocket.setFps(a/videoPulldown.divider)}function VideoClockSocket(){this.connectClock=function(b){a=b},this.getVSynchNativeFrequency=function(){return a.getVSynchNativeFrequency()},this.setVSynch=function(b){a.setVSynch(b)},this.setFrequency=function(b,c){a.setFrequency(b,c)};var a}function CartridgeSocket(){this.insert=function(a,b){b&&self.powerIsOn&&self.powerOff(),setCartridge(a),b&&!self.powerIsOn&&self.powerOn(),saveStateSocket.externalStateChange()},this.inserted=function(){return getCartridge()},this.cartridgeInserted=function(a,b){tia.getAudioOutput().cartridgeInserted(a,b),consoleControlsSocket.cartridgeInserted(a,b),saveStateSocket.cartridgeInserted(a,b),tia.getVideoOutput().monitor.cartridgeInserted(a,b)},this.loadCartridgeData=function(a,b,c){},this.saveCartridgeDataFile=function(a){}}function ConsoleControlsSocket(){this.connectControls=function(b){a=b},this.cartridgeInserted=function(b,c){a&&a.cartridgeInserted(b,c)},this.controlStateChanged=function(a,b){self.controlStateChanged(a,b),pia.controlStateChanged(a,b),tia.controlStateChanged(a,b),tia.getVideoOutput().monitor.controlStateChanged(a,b)},this.controlValueChanged=function(a,b){tia.controlValueChanged(a,b)},this.controlsStateReport=function(a){self.controlsStateReport(a),pia.controlsStateReport(a)},this.controlsStatesRedefined=function(){tia.getVideoOutput().monitor.controlsStatesRedefined()},this.firePowerAndUserPauseStateUpdate=function(){a.consolePowerAndUserPauseStateUpdate(self.powerIsOn,userPaused),tia.getVideoOutput().monitor.consolePowerAndUserPauseStateUpdate(self.powerIsOn,userPaused)},this.releaseControllers=function(){a.releaseControllers()},this.controlsClockPulse=function(){a.controlsClockPulse()},this.getControlReport=function(a){switch(a){case jt.ConsoleControls.VIDEO_STANDARD:return{label:videoStandardIsAuto?"Auto":videoStandard.name,active:!videoStandardIsAuto};case jt.ConsoleControls.VSYNCH:return{label:-1===vSynchMode?"DISABL":vSynchMode?"ON":"OFF",active:1===vSynchMode};case jt.ConsoleControls.NO_COLLISIONS:return{label:tia.getDebugNoCollisions()?"ON":"OFF",active:tia.getDebugNoCollisions()};default:return{label:"Unknown",active:!1 }}};var a}function SaveStateSocket(){this.connectMedia=function(b){a=b},this.getMedia=function(){return a},this.cartridgeInserted=function(a){a&&a.connectSaveStateSocket(this)},this.externalStateChange=function(){a.externalStateChange()},this.saveState=function(c){if(self.powerIsOn){var d=saveState();d.v=b,a.saveState(c,d)?self.showOSD("State "+c+" saved",!0):self.showOSD("State "+c+" save failed",!0)}},this.loadState=function(c){var d=a.loadState(c);return d?d.v!==b?void self.showOSD("State "+c+" load failed, wrong version",!0):(self.powerIsOn||self.powerOn(!0),loadState(d),void self.showOSD("State "+c+" loaded",!0)):void self.showOSD("State "+c+" not found",!0)},this.saveStateFile=function(){if(self.powerIsOn){var c=cartridgeSocket.inserted()&&cartridgeSocket.inserted().rom.info.l,d=saveState();d.v=b,a.saveStateFile(c,d)?self.showOSD("State Cartridge saved",!0):self.showOSD("State file save failed",!0)}},this.loadStateFile=function(c){var d=a.loadStateFile(c);if(d)return d.v!==b?(self.showOSD("State file load failed, wrong version",!0),!0):(self.powerIsOn||self.powerOn(),loadState(d),self.showOSD("State file loaded",!0),!0)};var a,b=2}function AudioSocket(){this.connectMonitor=function(b){a=b;for(var d=c.length-1;d>=0;d--)a.connectAudioSignal(c[d])},this.connectAudioSignal=function(d){c.indexOf(d)>=0||(jt.Util.arrayAdd(c,d),this.flushAllSignals(),d.setFps(b),a&&a.connectAudioSignal(d))},this.disconnectAudioSignal=function(b){jt.Util.arrayRemoveAllElement(c,b),a&&a.disconnectAudioSignal(b)},this.audioClockPulse=function(){for(var a=c.length-1;a>=0;--a)c[a].audioClockPulse()},this.audioFinishFrame=function(){for(var a=c.length-1;a>=0;--a)c[a].audioFinishFrame()},this.muteAudio=function(){a&&a.mute()},this.unMuteAudio=function(){a&&a.unMute()},this.setFps=function(a){b=a;for(var d=c.length-1;d>=0;--d)c[d].setFps(b)},this.pauseAudio=function(){a&&a.pause()},this.unpauseAudio=function(){a&&a.unpause()},this.flushAllSignals=function(){for(var a=c.length-1;a>=0;--a)c[a].flush()};var a,b,c=[]}var self=this;this.socketsConnected=function(){setDefaults()},this.powerOn=function(a){this.powerIsOn&&this.powerOff(),bus.powerOn(),this.powerIsOn=!0,consoleControlsSocket.controlsStatesRedefined(),updateVideoSynchronization(),videoStandardAutoDetectionStart(),a||consoleControlsSocket.firePowerAndUserPauseStateUpdate()},this.powerOff=function(){bus.powerOff(),this.powerIsOn=!1,consoleControlsSocket.controlsStatesRedefined(),userPaused?this.userPause(!1):consoleControlsSocket.firePowerAndUserPauseStateUpdate()},this.userPowerOn=function(){isLoading||(this.powerOn(),bus.getCartridge()||this.showOSD("NO CARTRIDGE INSERTED!",!1,!0))},this.setLoading=function(a){isLoading=a},this.userPause=function(a,b){var c=userPaused;return userPaused!==a&&(userPaused=!!a,userPauseMoreFrames=-1,userPaused&&!b?audioSocket.muteAudio():audioSocket.unMuteAudio(),consoleControlsSocket.firePowerAndUserPauseStateUpdate()),c},this.systemPause=function(a){var b=systemPaused;return systemPaused!==a&&(systemPaused=!!a,systemPaused?audioSocket.pauseAudio():audioSocket.unpauseAudio()),b},this.isSystemPaused=function(){return systemPaused},this.videoClockPulse=function(){this.videoClockPulseApplyPulldowns(self.videoClockPulseGetNextPulldowns())},this.videoClockPulseApplyPulldowns=function(a){if(self.powerIsOn){for(;a-- >0;)videoFrame();userPaused||audioSocket.audioFinishFrame()}},this.videoClockPulseGetNextPulldowns=function(){return 1===videoPulldown.steps?1:(--videoPulldownStep<0&&(videoPulldownStep=videoPulldown.steps-1),videoPulldown.cadence[videoPulldownStep])},this.getCartridgeSocket=function(){return cartridgeSocket},this.getConsoleControlsSocket=function(){return consoleControlsSocket},this.getVideoOutput=function(){return tia.getVideoOutput()},this.getAudioOutput=function(){return tia.getAudioOutput()},this.getSavestateSocket=function(){return saveStateSocket},this.getVideoClockSocket=function(){return videoClockSocket},this.getAudioSocket=function(){return audioSocket},this.showOSD=function(a,b,c){this.getVideoOutput().showOSD(a,b,c)},this.vSynchSetSupported=function(a){var b=Javatari.userPreferences.current.vSynch;vSynchMode=-1!==Javatari.SCREEN_VSYNCH_MODE&&a?Javatari.SCREEN_VSYNCH_MODE>=0?Javatari.SCREEN_VSYNCH_MODE:null!==b&&b>=0?b:1:-1};var setCartridge=function(a){Javatari.cartridge=a;var b=getCartridge();bus.setCartridge(a),cartridgeSocket.cartridgeInserted(a,b)},getCartridge=function(){return bus.getCartridge()},setVideoStandard=function(a){videoStandard!==a&&(videoStandard=a,tia.setVideoStandard(videoStandard),updateVideoSynchronization())},setVideoStandardAuto=function(a){videoStandardIsAuto=a,a&&(self.powerIsOn?videoStandardAutoDetectionStart():setVideoStandard(jt.VideoStandard.NTSC))},videoStandardAutoDetectionStart=function(){if(videoStandardIsAuto&&!videoStandardAutoDetectionInProgress)return bus.getCartridge()?void(tia.getVideoOutput().monitor&&(videoStandardAutoDetectionInProgress=!0,videoStandardAutoDetectionTries=0,tia.getVideoOutput().monitor.videoStandardDetectionStart())):void setVideoStandard(jt.VideoStandard.NTSC)},videoStandardAutoDetectionTry=function(){videoStandardAutoDetectionTries++;var a=tia.getVideoOutput().monitor.getVideoStandardDetected();!a&&videoStandardAutoDetectionTries0?--c:a===controls.MIN_SPEED?c=0:a===controls.NORMAL_SPEED&&(c=SPEEDS.indexOf(1)),speedControl=SPEEDS[c],self.showOSD("Speed: "+(100*speedControl|0)+"%",!0),videoClockUpdateSpeed();break;case controls.SAVE_STATE_0:case controls.SAVE_STATE_1:case controls.SAVE_STATE_2:case controls.SAVE_STATE_3:case controls.SAVE_STATE_4:case controls.SAVE_STATE_5:case controls.SAVE_STATE_6:case controls.SAVE_STATE_7:case controls.SAVE_STATE_8:case controls.SAVE_STATE_9:case controls.SAVE_STATE_10:case controls.SAVE_STATE_11:case controls.SAVE_STATE_12:var d=self.systemPause(!0);saveStateSocket.saveState(255&a),d||self.systemPause(!1);break;case controls.SAVE_STATE_FILE:d=self.systemPause(!0),saveStateSocket.saveStateFile(),d||self.systemPause(!1);break;case controls.LOAD_STATE_0:case controls.LOAD_STATE_1:case controls.LOAD_STATE_2:case controls.LOAD_STATE_3:case controls.LOAD_STATE_4:case controls.LOAD_STATE_5:case controls.LOAD_STATE_6:case controls.LOAD_STATE_7:case controls.LOAD_STATE_8:case controls.LOAD_STATE_9:case controls.LOAD_STATE_10:case controls.LOAD_STATE_11:case controls.LOAD_STATE_12:d=self.systemPause(!0),saveStateSocket.loadState(255&a),d||self.systemPause(!1);break;case controls.VIDEO_STANDARD:videoStandardIsAuto?setVideoStandardForced(jt.VideoStandard.NTSC):videoStandard==jt.VideoStandard.NTSC?setVideoStandardForced(jt.VideoStandard.PAL):setVideoStandardAuto(!0),showVideoStandardMessage();break;case controls.VSYNCH:vSynchToggleMode();break;case controls.CARTRIDGE_FORMAT:cycleCartridgeFormat();break;case controls.DEFAULTS:setDefaults(),self.showOSD("Default Settings",!0)}},this.controlsStateReport=function(a){a[controls.POWER]=self.powerIsOn},this.eval=function(str){return eval(str)},init()},jt.JoystickButtons={J_UP:{button:"J_UP",mask:1,n:"UP"},J_DOWN:{button:"J_DOWN",mask:2,n:"DOWN"},J_LEFT:{button:"J_LEFT",mask:4,n:"LEFT"},J_RIGHT:{button:"J_RIGHT",mask:8,n:"RIGHT"},J_A:{button:"J_A",mask:16,n:"A"},J_B:{button:"J_B",mask:32,n:"B"},J_AB:{button:"J_AB",mask:48,n:"AB"},J_X:{button:"J_X",n:"X"},J_Y:{button:"J_Y",n:"Y"},J_L:{button:"J_L",n:"L"},J_R:{button:"J_R",n:"R"},J_BACK:{button:"J_BACK",n:"BACK"},J_START:{button:"J_START",n:"START"}},jt.ConsoleControls={JOY0_UP:11,JOY0_DOWN:12,JOY0_LEFT:13,JOY0_RIGHT:14,JOY0_BUTTON:15,JOY1_UP:21,JOY1_DOWN:22,JOY1_LEFT:23,JOY1_RIGHT:24,JOY1_BUTTON:25,PADDLE0_BUTTON:41,PADDLE1_BUTTON:42,PADDLE0_POSITION:16384,PADDLE1_POSITION:16896,POWER:51,BLACK_WHITE:52,SELECT:53,RESET:54,DIFFICULTY0:55,DIFFICULTY1:56,POWER_OFF:57,POWER_FRY:58,CARTRIDGE_FORMAT:91,DEBUG:101,TRACE:102,SHOW_INFO:103,NO_COLLISIONS:104,PAUSE:105,PAUSE_AUDIO_ON:106,FRAME:107,FAST_SPEED:111,SLOW_SPEED:112,INC_SPEED:113,DEC_SPEED:114,NORMAL_SPEED:115,MIN_SPEED:116,VIDEO_STANDARD:123,VSYNCH:124,DEFAULTS:130,SAVE_STATE_0:256,SAVE_STATE_1:257,SAVE_STATE_2:258,SAVE_STATE_3:259,SAVE_STATE_4:260,SAVE_STATE_5:261,SAVE_STATE_6:262,SAVE_STATE_7:263,SAVE_STATE_8:264,SAVE_STATE_9:265,SAVE_STATE_10:266,SAVE_STATE_11:267,SAVE_STATE_12:268,LOAD_STATE_0:512,LOAD_STATE_1:513,LOAD_STATE_2:514,LOAD_STATE_3:515,LOAD_STATE_4:516,LOAD_STATE_5:517,LOAD_STATE_6:518,LOAD_STATE_7:519,LOAD_STATE_8:520,LOAD_STATE_9:521,LOAD_STATE_10:522,LOAD_STATE_11:523,LOAD_STATE_12:524,SAVE_STATE_FILE:201},jt.ROM=function(a,b,c,d){"use strict";this.source=a,this.content=b,this.info=c||jt.CartridgeCreator.produceInfo(this,d),this.saveState=function(a){return{s:this.source,i:this.info,c:a?jt.Util.compressInt8BitArrayToStringBase64(this.content):null}}},jt.ROM.loadState=function(a){"use strict";var b=a.c?jt.Util.uncompressStringBase64ToInt8BitArray(a.c):null;return new jt.ROM(a.s,b,a.i)},jt.CartridgeDatabase={uncompress:function(){jt.CartridgeDatabase=JSON.parse(jt.Util.uncompressStringBase64ToString(this.data))}, data:"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" },jt.Cartridge=function(){"use strict";this.powerOn=function(){},this.powerOff=function(){},this.connectBus=function(a){},this.connectSaveStateSocket=function(a){},this.read=function(a){},this.write=function(a,b){},this.getDataDesc=function(){return null},this.needsBusMonitoring=function(){return!1},this.monitorBusBeforeRead=function(a){},this.monitorBusBeforeWrite=function(a,b){},this.needsAudioClock=function(){return!1},this.audioClockPulse=function(){},this.reinsertROMContent=function(){this.rom.content||(this.rom.content=this.bytes||[])},this.format=null,this.rom=null,this.bytes=null,this.saveState=function(){},this.loadState=function(a){}},jt.Cartridge.base=new jt.Cartridge,jt.Cartridge4K=function(a,b){"use strict";this.read=function(a){return c[a&d]},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c};var c,d=4095;a&&function(d){d.rom=a,d.format=b,c=new Array(4096),d.bytes=c;for(var e=a.content.length,f=0;f=1024&&d<=2047&&(e[d-1024]=b)};var c=function(a){return a&f};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),ra:jt.Util.compressInt8BitArrayToStringBase64(e)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,e=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,e)};var d,e=jt.Util.arrayFill(new Array(1024),0),f=4095;a&&function(c){c.rom=a,c.format=b,d=new Array(4096),c.bytes=d;for(var e=a.content.length,f=0;f=k&&b<2*k?l[b-k]:g[m+b]},this.write=function(a,b){var c=f(a);c=h&&b<=i&&(m=p*(b-h)),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(g),bo:m,bb:h,es:k,tb:i,s:0|n,sa:0|j,e:l&&jt.Util.compressInt8BitArrayToStringBase64(l)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),g=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,g),this.bytes=g,m=a.bo,h=a.bb,k=a.es,i=a.tb,n=!!a.s,j=!!a.sa,l=a.e&&jt.Util.uncompressStringBase64ToInt8BitArray(a.e,l)};var g,h,i,j,k,l,m=0,n=!1,o=4095,p=4096;a&&function(f){f.rom=a,f.format=b,g=a.content,f.bytes=g;var m=g.length/p;h=c,i=h+m-1,k=e,null==d||void 0==d?(n=!1,j=!0):(n=!!d,j=!1),l=!1!==d?jt.Util.arrayFill(new Array(k),0):null}(this)},jt.CartridgeBankedByMaskedRange.prototype=jt.Cartridge.base,jt.CartridgeBankedByMaskedRange.recreateFromSaveState=function(a,b){var c=b||new jt.CartridgeBankedByMaskedRange;return c.loadState(a),c},jt.Cartridge8K_E0=function(a,b){"use strict";this.read=function(a){var b=c(a);return b<1024?d[e+b]:b<2048?d[f+b-1024]:b<3072?d[g+b-2048]:d[4096+b]},this.write=function(a,b){c(a)};var c=function(a){var b=a&h;return b>=4064&&b<=4087&&(b<=4071?e=1024*(b-4064):b<=4079?f=1024*(b-4072):b<=4087&&(g=1024*(b-4080))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),s0:e,s1:f,s2:g}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,e=a.s0,f=a.s1,g=a.s2};var d,e=0,f=0,g=0,h=4095;a&&function(c){c.rom=a,c.format=b,d=a.content,c.bytes=d}(this)},jt.Cartridge8K_E0.prototype=jt.Cartridge.base,jt.Cartridge8K_E0.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_E0;return c.loadState(a),c},jt.Cartridge64K_F0=function(a,b){"use strict";this.read=function(a){var b=c(a);return d[e+b]},this.write=function(a,b){c(a)};var c=function(a){var b=a&f;return b==i&&(e+=h)>=g&&(e=0),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,e=a.bo};var d,e=0,f=4095,g=65536,h=4096,i=4080;a&&function(c){c.rom=a,c.format=b,d=a.content,c.bytes=d}(this)},jt.Cartridge64K_F0.prototype=jt.Cartridge.base,jt.Cartridge64K_F0.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge64K_F0;return c.loadState(a),c},jt.Cartridge8K_FE=function(a,b){"use strict";this.read=function(a){var b=c(a);return d[e+b]},this.write=function(a,b){c(a)};var c=function(a){return 0!=(8192&a)?0!==e&&(e=0):e!=g&&(e=g),a&f};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,e=a.bo};var d,e=0,f=4095,g=4096;a&&function(c){c.rom=a,c.format=b,d=a.content,c.bytes=d}(this)},jt.Cartridge8K_FE.prototype=jt.Cartridge.base,jt.Cartridge8K_FE.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_FE;return c.loadState(a),c},jt.Cartridge16K_E7=function(a,b){"use strict";this.read=function(a){var b=c(a);return b>=2304&&b<=2559?g[i+b-2304]:h&&b>=1024&&b<=2047?g[b-1024]:b=2048&&d<=2303?g[i+d-2048]=b:h&&d<=1023&&(g[d]=b)};var c=function(a){var b=a&j;return b>=4064&&b<=4075&&(b<=4070?e=k*(b-4064):4071==b?h=!0:b<=4075&&(i=f+n*(b-4072))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:e,rs:h,ro:i,ra:jt.Util.compressInt8BitArrayToStringBase64(g)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,e=a.bo,h=a.rs,i=a.ro,g=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,g)};var d,e=0,f=1024,g=jt.Util.arrayFill(new Array(2048),0),h=!1,i=f,j=4095,k=2048,l=2048,m=16384-k-l,n=256;a&&function(c){c.rom=a,c.format=b,d=a.content,c.bytes=d}(this)},jt.Cartridge16K_E7.prototype=jt.Cartridge.base,jt.Cartridge16K_E7.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge16K_E7;return c.loadState(a),c},jt.Cartridge10K_DPCa=function(a,b){"use strict";this.powerOn=function(){x=o,y=0},this.connectBus=function(a){k=a.getTia().getAudioOutput().getChannel0()},this.needsAudioClock=function(){return!0},this.read=function(a){var b=c(a);return b<=63||b>=2048&&b<=2111?e(255&b):l[q+b]},this.write=function(a,b){var d=c(a);(d>=64&&d<=127||d>=2112&&d<=2175)&&f(255&d,b)},this.audioClockPulse=function(){if((y+x|0)>(0|y))for(var a=5;a<=7;a++)w[a]&&(s[a]--,255==(255&s[a])&&g(a,65280&s[a]|t[a]),i(a),z||(z=!0));y+=x,z&&(d(),k.setVolume(A))};var c=function(a){var b=a&n;return 4088===b?q=0:4089===b&&(q=4096),b},d=function(){A=m[(w[5]?4&v[5]:0)|(w[6]?2&v[6]:0)|(w[7]?1&v[7]:0)],z=!1},e=function(a){var b;return a>=0&&a<=3?(j(),r):a>=4&&a<=7?(z&&d(),A):a>=8&&a<=15?(b=l[p-s[a-8]],h(a-8),b):a>=16&&a<=23?(b=l[p-s[a-16]]&v[a-16],h(a-16),b):a>=24&&a<=31?(b=l[p-s[a-24]]&v[a-24],h(a-24), b=240&b|15&b):a>=32&&a<=39?(b=l[p-s[a-32]]&v[a-32],h(a-32),b=128&b|64&b|32&b|16&b|8&b|4&b|2&b|1&b):a>=40&&a<=47?(b=l[p-s[a-40]]&v[a-40],h(a-40),b=255&(b>>>1|b<<7)):a>=48&&a<=55?(b=l[p-s[a-48]]&v[a-48],h(a-48),b=255&(b<<1|b>>7&1)):a>=56&&a<=63?v[a-56]:0},f=function(a,b){if(a>=64&&a<=71){var c=a-64;return t[c]=b,void((255&s[c])===t[c]&&(v[c]=255))}return a>=72&&a<=79?(u[a-72]=b,void(v[a-72]=0)):a>=80&&a<=87?void g(a-80,65280&s[a-80]|255&b):a>=88&&a<=91?void g(a-88,255&s[a-88]|(7&b)<<8):92==a?void g(4,255&s[4]|(7&b)<<8):a>=93&&a<=95?(g(a-88,(255&s[a-88])+((7&b)<<8)),void(w[a-88]=(16&b)>>>4)):void(a>=96&&a<=103||a>=112&&a<=119&&(r=0))},g=function(a,b){s[a]=b},h=function(a){var b=s[a]-1;b<0&&(b=2047),g(a,b),i(a)},i=function(a){var b=255&s[a];b==t[a]?v[a]=255:b==u[a]&&(v[a]=0)},j=function(){255===(r=255&(r<<1|1&~(r>>7^r>>5^r>>4^r>>3)))&&(r=0)};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(l),bo:q,rn:r,fp:jt.Util.compressInt8BitArrayToStringBase64(s),fs:jt.Util.compressInt8BitArrayToStringBase64(t),fe:jt.Util.compressInt8BitArrayToStringBase64(u),fm:jt.Util.compressInt8BitArrayToStringBase64(v),a:jt.Util.compressInt8BitArrayToStringBase64(w)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),l=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,l),this.bytes=l,q=a.bo,r=a.rn,s=jt.Util.uncompressStringBase64ToInt8BitArray(a.fp,s),t=jt.Util.uncompressStringBase64ToInt8BitArray(a.fs,t),u=jt.Util.uncompressStringBase64ToInt8BitArray(a.fe,u),v=jt.Util.uncompressStringBase64ToInt8BitArray(a.fm,v),w=jt.Util.uncompressStringBase64ToInt8BitArray(a.a,w)};var k,l,m=[0,5,5,10,5,10,10,15],n=4095,o=.62,p=10239,q=0,r=0,s=jt.Util.arrayFill(new Array(8),0),t=jt.Util.arrayFill(new Array(8),0),u=jt.Util.arrayFill(new Array(8),0),v=jt.Util.arrayFill(new Array(8),0),w=jt.Util.arrayFill(new Array(8),0),x=o,y=0,z=!0,A=0;a&&function(c){c.rom=a,c.format=b,l=a.content,c.bytes=l}(this)},jt.Cartridge10K_DPCa.prototype=jt.Cartridge.base,jt.Cartridge10K_DPCa.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge10K_DPCa;return c.loadState(a),c},jt.Cartridge24K_28K_32K_FA2=function(a,b,c){"use strict";var d=this;this.connectBus=function(a){k=a},this.connectSaveStateSocket=function(a){l=a},this.read=function(a){var b,c=e(a);if(b=c>=256&&c<512?r[c-256]:m[p+c],c!==x)return b;if(0===t){var d=r[y];if(1===d||2===d)return f(d),64|b}return 0===t?191&b:(i(),0!==t?64|b:191&b)},this.write=function(a,b){var c=e(a);c<256&&(r[c]=b)};var e=function(a){var b=a&v;return b>=q&&b<=n&&(p=o+w*(b-q)),b},f=function(a){t=a,s=0,1===a?g():2===a&&h()},g=function(){if(k.getTia().getVideoOutput().showOSD("Reading from Cartridge Flash Memory...",!0),l){var a=l.getMedia().loadResource(j());a&&(u=jt.Util.uncompressStringBase64ToInt8BitArray(a,u))}jt.Util.arrayCopy(u,0,r)},h=function(){k.getTia().getVideoOutput().showOSD("Writing to Cartridge Flash Memory...",!0),jt.Util.arrayCopy(r,0,u),l&&l.getMedia().saveResource(j(),jt.Util.compressInt8BitArrayToStringBase64(u))},i=function(){++s>140&&(s=0,t=0,r[y]=0,k.getTia().getVideoOutput().showOSD("Done.",!0),l&&l.externalStateChange())},j=function(){return"hfm"+d.rom.info.h};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(m),rs:o,bo:p,tb:n,e:jt.Util.compressInt8BitArrayToStringBase64(r),ho:t,ht:s}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),m=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,m),this.bytes=m,o=a.rs||0,p=a.bo,n=a.tb,r=jt.Util.uncompressStringBase64ToInt8BitArray(a.e,r),t=a.ho||0,s=a.ht||0};var k,l,m,n,o=0,p=0,q=4085,r=jt.Util.arrayFill(new Array(256),0),s=0,t=0,u=jt.Util.arrayFill(new Array(256),0),v=4095,w=4096,x=4084,y=255;a&&function(d){d.rom=a,d.format=b,m=a.content,d.bytes=m,o=c||0,p=o;var e=(m.length-o)/w;n=q+e-1}(this)},jt.Cartridge24K_28K_32K_FA2.prototype=jt.Cartridge.base,jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge24K_28K_32K_FA2;return c.loadState(a),c},jt.CartridgeBankedByBusMonitoring=function(a,b){"use strict";this.needsBusMonitoring=function(){return!0},this.monitorBusBeforeRead=function(a){this.performBankSwitchOnMonitoredAccess(a)},this.monitorBusBeforeWrite=function(a,b){this.performBankSwitchOnMonitoredAccess(a)},this.performBankSwitchOnMonitoredAccess=function(a){}},jt.CartridgeBankedByBusMonitoring.prototype=jt.Cartridge.base,jt.CartridgeBankedByBusMonitoring.base=new jt.CartridgeBankedByBusMonitoring,jt.Cartridge8K_512K_3F=function(a,b){"use strict";this.read=function(a){var b=a&g;return b>=i?c[e+b]:c[f+b]},this.monitorBusBeforeWrite=function(a,b){if(a<=63){var c=255&b;c<=d&&(f=c*h)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c),bo:f,sm:d,fo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c,f=a.bo,d=a.sm,e=a.fo};var c,d,e,f=0,g=4095,h=2048,i=2048;a&&function(f){f.rom=a,f.format=b,c=a.content,f.bytes=c,d=(c.length-h)/h-1,e=c.length-2*h}(this)},jt.Cartridge8K_512K_3F.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3F.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_512K_3F;return c.loadState(a),c},jt.Cartridge8K_512K_3E=function(a,b){"use strict";this.read=function(a){var b=c(a);return b>=m?d[f+b]:i>=0&&b<1024?j[i+b]||0:d[h+b]},this.write=function(a,b){if(!(i<0)){var d=c(a);d>=1024&&d<=2047&&(j[i+d-1024]=b)}};var c=function(a){return a&k};this.monitorBusBeforeWrite=function(a,b){if(63===a){var c=255&b;return void(c<=e&&(h=c*l,i=-1))}if(62===a){i=(255&b)*g}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(d),bo:h,sm:e,fo:f,ro:i,ra:jt.Util.compressInt8BitArrayToStringBase64(j)}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,d),this.bytes=d,h=a.bo,e=a.sm,f=a.fo,i=a.ro,j=jt.Util.uncompressStringBase64ToInt8BitArray(a.ra,j)};var d,e,f,g=1024,h=0,i=-1,j=jt.Util.arrayFill(new Array(g),0),k=4095,l=2048,m=2048;a&&function(c){c.rom=a,c.format=b,d=a.content,c.bytes=d,e=(d.length-l)/l-1,f=d.length-2*l}(this)},jt.Cartridge8K_512K_3E.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3E.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_512K_3E;return c.loadState(a),c},jt.Cartridge8K_256K_SB=function(a,b){"use strict";this.read=function(a){return c[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){if(2048==(6144&a)){var b=127&a;b>d||(e=b*g)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c),bo:e,m:d}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c,e=a.bo,d=a.m};var c,d,e=0,f=4095,g=4096;a&&function(e){e.rom=a,e.format=b,c=a.content,e.bytes=c,d=c.length/g-1}(this)},jt.Cartridge8K_256K_SB.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_256K_SB.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_256K_SB;return c.loadState(a),c},jt.Cartridge8K_64K_AR=function(a,b){"use strict";this.powerOn=function(){g(0),D=0},this.connectBus=function(a){c=a},this.read=function(a){return f=K&&f0?void(a!==s&&(s=a,0==--t&&(a&R)===S&&(f>2&7){case 0:o=2*M,p=N;break;case 1: o=0*M,p=N;break;case 2:o=2*M,p=0*M;break;case 3:o=0*M,p=2*M;break;case 4:o=2*M,p=N;break;case 5:o=1*M,p=N;break;case 6:o=2*M,p=1*M;break;case 7:o=1*M,p=2*M;break;default:throw new Error("Invalid bank configuration")}t=0,r=0!=(2&a),u=0==(1&a)},h=function(b){for(var d=!1;;){if(D>a.content.length-1){if(d)return 0===b?c.getTia().getVideoOutput().showOSD("Could not load Tape from Start. Not a Start Tape ROM!",!0):c.getTia().getVideoOutput().showOSD("Could not find next Part to load in Tape!",!0),void m(!1);D=0,d=!0}if(jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,D)===b)return 0===b?c.getTia().getVideoOutput().showOSD("Loaded Tape from Start",!0):c.getTia().getVideoOutput().showOSD("Loaded next Part from Tape",!0),void i();D+=O}},i=function(){j(),k(),l()},j=function(){jt.Util.arrayCopy(a.content,D+4*M,E,0,E.length),v=E[1]<<8|255&E[0],w=E[2],x=E[3],y=E[4],z=E[5],A=E[7]<<8|255&E[6],e=jt.Util.arrayFill(new Array(x),0),jt.Util.arrayCopy(E,16,e,0,x)},k=function(){jt.Util.arrayFillSegment(d,7*L,8*L-1,0);for(var b=D,c=0,f=e.length;c>2)*L;h+i+25530&&(C=0),d[N+H-63488]=255&v,d[N+H+1-63488]=v>>8&255,m(!0)},m=function(a){d[N+J-63488]=a?1:0},n=function(){var a=jt.Util.uncompressStringBase64ToInt8BitArray(P);jt.Util.arrayCopy(a,0,d,N,M)},o=0,p=0,q=0,r=!1,s=-1,t=0,u=!1,v=0,w=0,x=0,y=0,z=0,A=0,B=new Array(31),C=0,D=0,E=jt.Util.arrayFill(new Array(256),0),F=64256,G=64257,H=64258,I=64260,J=64261,K=3072,L=256,M=8*L,N=3*M,O=4*M+256,P="7dSxCsIwEAbgv6niGkeddPVZ8kCOXc43yCIokkGIUN+gLxAoZHTxHRxjYq2xk7vSIPS75bb7uYNTuOJWu/bod3iU42BzUTiBe9sTzSjToBnNBVxfQz/nQ+2NhA2a05KYmhhjmxhoQZymxGil8gpeesOdyioW5DN25yxsiri3chQOUO1WeCSI/hPx9AJ/m/576KROMUhlfdE4dQ+AfJoPNBikgOZdLw==",Q=4095,R=4096,S=4096;this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(!0),b:jt.Util.compressInt8BitArrayToStringBase64(d),b0o:o,b1o:p,vw:q,we:r,la:s,ac:t,bp:u,rs:v,rc:w,rp:x,rk:y,rm:z,rb:A,ro:e,to:D,rnd:jt.Util.storeInt8BitArrayToStringBase64(B),rnc:C}},this.loadState=function(b){this.format=jt.CartridgeFormats[b.f],this.rom=a=jt.ROM.loadState(b.r),d=jt.Util.uncompressStringBase64ToInt8BitArray(b.b,d),this.bytes=d,o=b.b0o,p=b.b1o,q=b.vw,r=b.we,s=b.la,t=b.ac,u=b.bp,v=b.rs,w=b.rc,x=b.rp,y=b.rk,z=b.rm,A=b.rb,e=b.ro,D=b.to,jt.Util.restoreStringBase64ToInt8BitArray(b.rnd,B),C=b.rnc},a&&function(c){c.rom=a,c.format=b,d=jt.Util.arrayFill(new Array(4*M)),c.bytes=d,n();for(var e=0;e<31;++e)B[e]=256*Math.random()|0}(this)},jt.Cartridge8K_64K_AR.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_64K_AR.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_64K_AR;return c.loadState(a),c},jt.Cartridge8K_64K_AR.HEADER_SIZE=256,jt.Cartridge8K_64K_AR.PAGE_SIZE=256,jt.Cartridge8K_64K_AR.BANK_SIZE=8*jt.Cartridge8K_64K_AR.PAGE_SIZE,jt.Cartridge8K_64K_AR.PART_SIZE=4*jt.Cartridge8K_64K_AR.BANK_SIZE+jt.Cartridge8K_64K_AR.HEADER_SIZE,jt.Cartridge8K_64K_AR.peekPartNoOnTape=function(a,b){return a[b+4*jt.Cartridge8K_64K_AR.BANK_SIZE+5]},jt.Cartridge8K_64K_AR.checkTape=function(a){return 0===jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,0)||(jt.Util.warning("Wrong Supercharger Tape Part ROM! Please load a Full Tape ROM file"),!1)},jt.Cartridge64K_X07=function(a,b){"use strict";this.read=function(a){return c[d+(a&e)]},this.performBankSwitchOnMonitoredAccess=function(a){2061==(6159&a)?d=((240&a)>>4)*f:d>=g&&0==(6272&a)&&(d=(0==(64&a)?14:15)*f)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c),bo:d}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c,d=a.bo};var c,d=0,e=4095,f=4096,g=14*f;a&&function(d){d.rom=a,d.format=b,c=a.content,d.bytes=c}(this)},jt.Cartridge64K_X07.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge64K_X07.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge64K_X07;return c.loadState(a),c},jt.Cartridge8K_0840=function(a,b){"use strict";this.read=function(a){return c[d+(a&e)]},this.performBankSwitchOnMonitoredAccess=function(a){var b=6208&a;2048===b?0!==d&&(d=0):2112===b&&d!==f&&(d=f)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c),bo:d}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c,d=a.bo};var c,d=0,e=4095,f=4096;a&&function(d){d.rom=a,d.format=b,c=a.content,d.bytes=c}(this)},jt.Cartridge8K_0840.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_0840.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_0840;return c.loadState(a),c},jt.Cartridge8K_UA=function(a,b){"use strict";this.read=function(a){return c[d+(a&e)]},this.performBankSwitchOnMonitoredAccess=function(a){544===a?0!==d&&(d=0):576===a&&d!==f&&(d=f)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:jt.Util.compressInt8BitArrayToStringBase64(c),bo:d}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),c=jt.Util.uncompressStringBase64ToInt8BitArray(a.b,c),this.bytes=c,d=a.bo};var c,d=0,e=4095,f=4096;a&&function(d){d.rom=a,d.format=b,c=a.content,d.bytes=c}(this)},jt.Cartridge8K_UA.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_UA.recreateFromSaveState=function(a,b){var c=b||new jt.Cartridge8K_UA;return c.loadState(a),c},jt.CartridgeFormats={"4K":{name:"4K",desc:"4K Atari",priority:101,tryFormat:function(a){if(a.content.length>=8&&a.content.length<=4096&&4096%a.content.length==0)return this},createCartridgeFromRom:function(a){return new jt.Cartridge4K(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge4K.recreateFromSaveState(a,b)}},CV:{name:"CV",desc:"2K Commavid +RAM",priority:102,tryFormat:function(a){if(2048===a.content.length||4096===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge2K_CV(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge2K_CV.recreateFromSaveState(a,b)}},E0:{name:"E0",desc:"8K Parker Bros.",priority:102,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_E0(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_E0.recreateFromSaveState(a,b)}},F0:{name:"F0",desc:"64K Dynacom Megaboy",priority:101,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_F0(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge64K_F0.recreateFromSaveState(a,b)}},FE:{name:"FE",desc:"8K Robotank/Decathlon",priority:103,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_FE(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_FE.recreateFromSaveState(a,b)}},E7:{name:"E7",desc:"16K M-Network",priority:102,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge16K_E7(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge16K_E7.recreateFromSaveState(a,b)}},F8:{name:"F8",desc:"8K Atari (+RAM)",priority:101,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},F6:{name:"F6",desc:"16K Atari (+RAM)",priority:101,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){ return new jt.CartridgeBankedByMaskedRange(a,this,4086,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},F4:{name:"F4",desc:"32K Atari (+RAM)",priority:101,tryFormat:function(a){if(32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4084,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},FA2cu:{name:"FA2cu",desc:"32K CBS RAM+ CU Image",priority:103,tryFormat:function(a){if(32768===a.content.length){var b=jt.Util.arraysEqual(a.content.slice(32,36),this.cuMagicWord);return this.priority=103-(b?30:0),this}},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this,1024)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(a,b)},cuMagicWord:[30,171,173,16]},FA2:{name:"FA2",desc:"24K/28K/32K CBS RAM+",priority:102,tryFormat:function(a){if(24576===a.content.length||28672===a.content.length||32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(a,b)}},FA:{name:"FA",desc:"12K CBS RAM Plus",priority:101,tryFormat:function(a){if(12288===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,!0,256)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},EF:{name:"EF",desc:"8K-64K H. Runner (+RAM)",priority:114,tryFormat:function(a){if(a.content.length%4096==0&&a.content.length>=8192&&a.content.length<=65536)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4064,null,128)},recreateCartridgeFromSaveState:function(a,b){return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(a,b)}},DPC:{name:"DPC",desc:"10K DPC Pitfall 2 (Enhanced)",priority:101,tryFormat:function(a){if(a.content.length>=10240&&a.content.length<=10496)return this},createCartridgeFromRom:function(a){return new jt.Cartridge10K_DPCa(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge10K_DPCa.recreateFromSaveState(a,b)}},"3F":{name:"3F",desc:"8K-512K Tigervision",priority:112,tryFormat:function(a){if(a.content.length%2048==0&&a.content.length>=2048&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3F(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_512K_3F.recreateFromSaveState(a,b)}},"3E":{name:"3E",desc:"8K-512K Tigervision (+RAM)",priority:111,tryFormat:function(a){if(a.content.length%2048==0&&a.content.length>=2048&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3E(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_512K_3E.recreateFromSaveState(a,b)}},X07:{name:"X07",desc:"64K AtariAge",priority:102,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_X07(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge64K_X07.recreateFromSaveState(a,b)}},"0840":{name:"0840",desc:"8K Econobanking",priority:116,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_0840(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_0840.recreateFromSaveState(a,b)}},UA:{name:"UA",desc:"8K UA Limited",priority:115,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_UA(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_UA.recreateFromSaveState(a,b)}},SB:{name:"SB",desc:"8K-256K Superbanking",priority:113,tryFormat:function(a){if(a.content.length%4096==0&&a.content.length>=8192&&a.content.length<=262144)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_256K_SB(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_256K_SB.recreateFromSaveState(a,b)}},AR:{name:"AR",desc:"8K-64K Arcadia/Supercharger",priority:101,tryFormat:function(a){if(a.content.length%jt.Cartridge8K_64K_AR.PART_SIZE==0&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE>=1&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE<=8&&jt.Cartridge8K_64K_AR.checkTape(a))return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_64K_AR(a,this)},recreateCartridgeFromSaveState:function(a,b){return jt.Cartridge8K_64K_AR.recreateFromSaveState(a,b)}}},jt.CartridgeFormatsUserOptions=["4K","CV","E0","F0","FE","E7","F8","F6","F4","FA2cu","FA2","FA","EF","DPC","3F","3E","X07","0840","UA","SB","AR"],jt.CartridgeCreatorImpl=function(){"use strict";this.createCartridgeFromRom=function(b){var c=a.getForROM(b);if(c){var d=jt.CartridgeFormats[c];if(d.tryFormat(b))return jt.Util.log("USER Format selected: "+d.desc),d.createCartridgeFromRom(b)}var e=this.getBestFormatOption(b);if(e)return jt.Util.log("AUTO Format selected: "+e.name+": "+e.desc+", priority: "+e.priority+(e.priorityBoosted?" ("+e.priorityBoosted+")":"")),e.createCartridgeFromRom(b)},this.recreateCartridgeFromSaveState=function(a,b){var c=jt.CartridgeFormats[a.f];if(!c)throw new Error("Unsupported ROM Format: "+a.f);return b&&b.format!==c&&(b=null),c.recreateCartridgeFromSaveState(a,b)},this.changeCartridgeFormat=function(a,b){return b.createCartridgeFromRom(a.rom)},this.getBestFormatOption=function(a){var c=b(a);return 0===c.length?void 0:c[0]},this.getUserFormatOptionNames=function(a){for(var b=[],c=0,d=jt.CartridgeFormatsUserOptions.length;ce&&a.content.splice(e);var g=jt.CartridgeDatabase[f];return g?jt.Util.log(g.n+" ("+f+")"):(g=c(a.source),jt.Util.log("Unknown ROM: "+g.n+" ("+f+")")),d(g,a.source,f,b),g},this.setUserROMFormats=function(b){a=b};var a,b=function(a){var b,c,d=[];for(var f in jt.CartridgeFormats)try{if(!(b=jt.CartridgeFormats[f].tryFormat(a)))continue;e(b,a.info),d.push(b)}catch(a){if(!a.formatDenial)throw a;c||(c=a)}return d.sort(function(a,b){return(a.priorityBoosted||a.priority)-(b.priorityBoosted||b.priority)}),d},c=function(a){var b={n:"Unknown"};if(!a||!a.trim())return b;var c=a,d=c.lastIndexOf("/"),e=c.lastIndexOf("\\"),f=c.lastIndexOf("?"),g=Math.max(d,Math.max(e,f));g>=0&&g=0&&(c=c.substring(0,h)),b.n=c.trim()||"Unknown",b},d=function(a,b,c,d){a.h=c,a.l||(a.l=f(a.n));var e=a.n.toUpperCase();a:if(!a.p&&(a.p=0,!e.match(l+"JOYSTICK(S)?"+m)))if(e.match(l+"PADDLE(S)?"+m))a.p=1;else for(var n=0;n=1?b:1,dividerCounter>divider&&(dividerCounter=divider)},pulse=function(){animationFrame=null,divider>1?--dividerCounter<=0&&(dividerCounter=divider,clockPulse()):clockPulse(),useRequestAnimationFrame&&!animationFrame&&(animationFrame=requestAnimationFrame(pulse))};this.detectHostNativeFPSAndCallback=function(a){function b(){vSynchNativeFrequency=-1,jt.Util.error("Could not detect video native frequency. V-Synch DISABLED!"),a&&a(vSynchNativeFrequency)}if(-1===Javatari.SCREEN_VSYNCH_MODE)return jt.Util.warning("Video native V-Synch disabled in configuration"),void(a&&a(vSynchNativeFrequency));if(-1!==Javatari.SCREEN_FORCE_HOST_NATIVE_FPS)return jt.Util.warning("Host video frequency forced in configuration: "+Javatari.SCREEN_FORCE_HOST_NATIVE_FPS),void(a&&a(vSynchNativeFrequency));if(!window.requestAnimationFrame)return b();var c=0,d=0,e=0,f=0,g=0,h=0,i=function(){if(e>=12||f>=18||g>=14||h>=18)return vSynchNativeFrequency=e>=12?60:f>=18?50:g>=14?120:100,jt.Util.log("Video native frequency detected: "+vSynchNativeFrequency+"Hz"),void(a&&a(vSynchNativeFrequency));if(!(++c<=70))return b();var j=jt.Util.performanceNow(),k=1e3/(j-d);d=j,k>=47&&k<=53&&f++,k>=56.4&&k<=63.6&&e++,k>=112.8&&k<=127.2&&g++,k>=94&&k<=106&&h++,requestAnimationFrame(i)};i()},this.eval=function(str){return eval(str)};var running=!1,cyclesPerSecond=1,cycleTimeMs=1e3,divider=1,dividerCounter=1,useRequestAnimationFrame,animationFrame=null,interval=null,vSynch=!0,vSynchNativeFrequency=-1===Javatari.SCREEN_VSYNCH_MODE?-1:Javatari.SCREEN_FORCE_HOST_NATIVE_FPS,vSynchAltNativeFrequency=void 0},jt.RecentStoredROMs=function(){function a(){if(!e){try{e=JSON.parse(localStorage.javataristoredromsdata)}catch(a){}e||b()}return e}function b(){d=[],localStorage.javataristoredromsicatalog=JSON.stringify(d),e=[],localStorage.javataristoredromsdata=JSON.stringify(e)}this.getCatalog=function(){if(!d){try{d=JSON.parse(localStorage.javataristoredromsicatalog)}catch(a){}d||b()}return d},this.storeROM=function(b){this.getCatalog();var c=d.find(function(a){return a&&a.h===b.info.h});if(c&&c.n==b.info.l&&c.f==b.info.f)this.lastROMLoadedIndex=d.indexOf(c);else{if(a(),c){var g=d.indexOf(c);d.splice(g,1),e.splice(g,1)}else d.length>=f&&(d=d.slice(0,f-1),e=e.slice(0,f-1));d.unshift({n:b.info.l,h:b.info.h,f:b.info.f});for(var h=0;h0&&(1===b.length?l.readFromFile(b[0],r,s,t,u,d):l.readFromFiles(b,r,s,t,u,d)),!1}}function h(a){a.returnValue=!1,a.preventDefault(),a.stopPropagation(), a.dataTransfer&&(Javatari.CARTRIDGE_CHANGE_DISABLED?a.dataTransfer.dropEffect="none":a.ctrlKey?a.dataTransfer.dropEffect="copy":a.altKey&&(a.dataTransfer.dropEffect="link")),v=a.buttons>0?a.buttons:w}function i(a){if(a.returnValue=!1,a.preventDefault(),a.stopPropagation(),a.target.focus(),a.dataTransfer&&!c.mediaChangeDisabledWarning()){var b=m.systemPause(!0),d=a.shiftKey?1:0,e=v&x,f=a.ctrlKey,g=y.AUTO,h=a.dataTransfer&&a.dataTransfer.files,i=function(a){b||m.systemPause(!1)};if(h&&h.length>0)1===h.length?l.readFromFile(h[0],g,d,e,f,i):l.readFromFiles(h,g,d,e,f,i);else{var j=a.dataTransfer.getData("text");j&&j.length>0?l.readFromURL(j,g,d,e,f,i):i()}}}function j(a){jt.Util.message("Could not load file(s):\n\n"+a+"\n")}function k(){p=document.createElement("input"),p.id="jt-file-loader-input",p.type="file",p.multiple=!0,p.accept=z.AUTO,p.style.display="none",p.addEventListener("change",g),q.appendChild(p)}var l=this;this.connect=function(a){m=a,n=m.getCartridgeSocket(),o=m.getSavestateSocket()},this.registerForDnD=function(a){a.addEventListener("dragover",h,!1),a.addEventListener("drop",i,!1)},this.registerForFileInputElement=function(a){q=a},this.openFileChooserDialog=function(a,b,c,d){p||k(),p.multiple=A[y[a]||y.AUTO],p.accept=z[y[a]||y.AUTO],r=a,s=c?1:0,t=b,u=d,p.click()},this.openURLChooserDialog=function(a,b,c,d){var e,f=c?1:0;try{e=localStorage&&localStorage[C]}catch(a){}var g=m.systemPause(!0);if(e=prompt("Load file from URL:",e||""),e=e&&e.toString().trim()){try{localStorage[C]=e}catch(a){}this.readFromURL(e,a,f,b,d,function(){g||m.systemPause(!1)})}else g||m.systemPause(!1)},this.readFromFile=function(a,b,c,d,e,f){jt.Util.log("Reading file: "+a.name);var g=new FileReader;g.onload=function(g){var h=new Uint8Array(g.target.result),i={name:a.name,content:h,lastModifiedDate:a.lastModified?new Date(a.lastModified):a.lastModifiedDate};l.loadFromFile(i,b,c,d,e),f&&f(!0)},g.onerror=function(a){j("File reading error: "+a.target.error.name+D),f&&f(!1)},g.readAsArrayBuffer(a)},this.readFromURL=function(a,b,c,d,e,f){new jt.MultiDownloader([{url:a}],function(g){var h={name:a,content:g[0].content,lastModifiedDate:null};l.loadFromFile(h,b,c,d,e),f&&f(!0)},function(a){j("URL reading error: "+a[0].error),f&&f(!1)}).start()},this.readFromFiles=function(a,b,c,d,e,f){new jt.MultiFileReader(a,function(a){l.loadFromFiles(a,b,c,d,e),f&&f(!0)},function(a,b,c){c||(b+=D),j("File reading error: "+b),f&&f(!1)}).start()},this.loadFromContent=function(a,b,c,d,e,f,g){return this.loadFromFile({name:a,content:b},c,d,e,f,g)},this.loadFromFile=function(a,b,c,e,f,g){var h;if(h=jt.Util.checkContentIsZIP(a.content))try{if(d(jt.Util.getZIPFilesSorted(h),b,c,e,f,g,!0))return}catch(a){jt.Util.error(a)}else if(d([a],b,c,e,f,g,!1))return;j("No valid "+B[b]+" found.")},this.loadFromFiles=function(a,b,c,e,f){a=jt.Util.asNormalArray(a).slice(0),a.sort(function(a,b){return a.nameb.name?1:0}),d(a,b,c,e,f,null,!1)||j("No valid "+B[b]+" found.")},this.loadROM=function(a,c,d,e){var f=jt.CartridgeCreator.createCartridgeFromRom(a);return!!f&&(n.insert(f,!d),b.storeROM(a),!0)};var m,n,o,p,q,r,s=0,t=!1,u=!1,v=1,w=1,x=2,y=jt.FileLoader.OPEN_TYPE;this.OPEN_TYPE=y;var z={ROM:".bin,.BIN,.rom,.ROM,.a26,.A26,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP",STATE:".jst,.JST",CART_DATA:".dat,.DAT,.sram,.SRAM",AUTO:".bin,.BIN,.rom,.ROM,.a26,.A26,.jst,.JST,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP"},A={ROM:!1,STATE:!1,CART_DATA:!1,AUTO:!1},B={ROM:"ROM",STATE:"Savestate",CART_DATA:"Cartridge Data",AUTO:"ROM"},C="javatarilasturl",D="\n\nIMPORTANT: Directories are not supported for loading!";Javatari.fileLoader=this},jt.FileLoader.OPEN_TYPE={AUTO:"AUTO",ROM:"ROM",STATE:"STATE",CART_DATA:"CART_DATA"},jt.FileDownloader=function(){"use strict";function a(){if("NONE"===c)return alert("Unfortunately file saving in WebApps is broken in this version of iOS. The file could not be saved. If you really need to save a file, you must run Javatari on the official homepage."),!0}function b(){"NONE"!==(c=jt.Util.isIOSDevice()?jt.Util.isBrowserStandaloneMode()?"NONE":"DATA":"SAFARI"===jt.Util.browserInfo().name?"DATA":"BLOB")&&(d=document.createElement("a"),d.style.display="none",d.target="_blank",d.href="#",e.appendChild(d))}this.connectPeripherals=function(a){f=a},this.registerForDownloadElement=function(a){e=a},this.startDownloadBinary=function(e,g,h){try{if(c||b(),a())return;var i;if("BLOB"===c){d.href&&(window.URL||window.webkitURL).revokeObjectURL(d.href);var j=new Blob([g],{type:"data:application/octet-stream"});i=(window.URL||window.webkitURL).createObjectURL(j)}else i="data:application/octet-stream;base64,"+btoa("string"==typeof g?g:jt.Util.int8BitArrayToByteString(g));d.download=e&&e.trim(),d.href=i,d.click(),f.showOSD(h+" saved",!0)}catch(a){f.showOSD(h+" save FAILED!",!0,!0),jt.Util.error(a)}},this.startDownloadURL=function(e,g,h){try{if(c||b(),a())return;"BLOB"===c&&d.href&&(window.URL||window.webkitURL).revokeObjectURL(d.href),d.download=e&&e.trim(),d.href=g,d.click(),f.showOSD(h+" saved",!0)}catch(a){f.showOSD(h+" save FAILED!",!0,!0),jt.Util.error(a)}};var c,d,e,f},jt.DOMKeys={},jt.DOMKeys.MOD_SHIFT=16,jt.DOMKeys.LOC_SHIFT=24,jt.DOMKeys.SHIFT=65536,jt.DOMKeys.CONTROL=131072,jt.DOMKeys.ALT=262144,jt.DOMKeys.META=524288,jt.DOMKeys.LOCNONE=0,jt.DOMKeys.LOCLEFT=16777216,jt.DOMKeys.LOCRIGHT=33554432,jt.DOMKeys.LOCNUM=50331648,jt.DOMKeys.IGNORE_ALL_MODIFIERS_MASK=~(jt.DOMKeys.SHIFT|jt.DOMKeys.CONTROL|jt.DOMKeys.ALT|jt.DOMKeys.META),function(a,b,c,d){a.VK_F1={c:112,n:"F1"},a.VK_F2={c:113,n:"F2"},a.VK_F3={c:114,n:"F3"},a.VK_F4={c:115,n:"F4"},a.VK_F5={c:116,n:"F5"},a.VK_F6={c:117,n:"F6"},a.VK_F7={c:118,n:"F7"},a.VK_F8={c:119,n:"F8"},a.VK_F9={c:120,n:"F9"},a.VK_F10={c:121,n:"F10"},a.VK_F11={c:122,n:"F11"},a.VK_F12={c:123,n:"F12"},a.VK_1={c:49,n:"1"},a.VK_2={c:50,n:"2"},a.VK_3={c:51,n:"3"},a.VK_4={c:52,n:"4"},a.VK_5={c:53,n:"5"},a.VK_6={c:54,n:"6"},a.VK_7={c:55,n:"7"},a.VK_8={c:56,n:"8"},a.VK_9={c:57,n:"9"},a.VK_0={c:48,n:"0"},a.VK_Q={c:81,n:"Q"},a.VK_W={c:87,n:"W"},a.VK_E={c:69,n:"E"},a.VK_R={c:82,n:"R"},a.VK_T={c:84,n:"T"},a.VK_Y={c:89,n:"Y"},a.VK_U={c:85,n:"U"},a.VK_I={c:73,n:"I"},a.VK_O={c:79,n:"O"},a.VK_P={c:80,n:"P"},a.VK_A={c:65,n:"A"},a.VK_S={c:83,n:"S"},a.VK_D={c:68,n:"D"},a.VK_F={c:70,n:"F"},a.VK_G={c:71,n:"G"},a.VK_H={c:72,n:"H"},a.VK_J={c:74,n:"J"},a.VK_K={c:75,n:"K"},a.VK_L={c:76,n:"L"},a.VK_Z={c:90,n:"Z"},a.VK_X={c:88,n:"X"},a.VK_C={c:67,n:"C"},a.VK_V={c:86,n:"V"},a.VK_B={c:66,n:"B"},a.VK_N={c:78,n:"N"},a.VK_M={c:77,n:"M"},a.VK_ESCAPE={c:27,n:"Esc"},a.VK_ENTER={c:13,n:"Enter"},a.VK_SPACE={c:32,n:"Space"},a.VK_TAB={c:9,n:"Tab"},a.VK_BACKSPACE={c:8,n:"BackSpc"},a.VK_CONTEXT={c:93,n:"Context"},a.VK_LSHIFT={c:16|b,n:"L-Shift"},a.VK_LCONTROL={c:17|b,n:"L-Control"},a.VK_LALT={c:18|b,n:"L-Alt"},a.VK_LMETA={c:91|b,n:"L-Meta"},a.VK_RSHIFT={c:16|c,n:"R-Shift"},a.VK_RCONTROL={c:17|c,n:"R-Control"},a.VK_RALT={c:18|c,n:"R-Alt"},a.VK_RMETA={c:91|c,n:"R-Meta"},a.VK_CAPS_LOCK={c:20,n:"CapsLock"},a.VK_PRINT_SCREEN={c:44,n:"PrtScr"},a.VK_SCROLL_LOCK={c:145,n:"ScrLck"},a.VK_PAUSE={c:19,n:"Pause"},a.VK_BREAK={c:3,n:"Break"},a.VK_INSERT={c:45,n:"Ins"},a.VK_DELETE={c:46,n:"Del"},a.VK_HOME={c:36,n:"Home"},a.VK_END={c:35,n:"End"},a.VK_PAGE_UP={c:33,n:"PgUp"},a.VK_PAGE_DOWN={c:34,n:"PgDown"},a.VK_NUM_INSERT={c:45|d,n:"Num Ins"},a.VK_NUM_DELETE={c:46|d,n:"Num Del"},a.VK_NUM_HOME={c:36|d,n:"Num Home"},a.VK_NUM_END={c:35|d,n:"Num End"},a.VK_NUM_PAGE_UP={c:33|d,n:"Num PgUp"},a.VK_NUM_PAGE_DOWN={c:34|d,n:"Num PgDown"},a.VK_UP={c:38,n:"Up"},a.VK_DOWN={c:40,n:"Down"},a.VK_LEFT={c:37,n:"Left"},a.VK_RIGHT={c:39,n:"Right"},a.VK_NUM_UP={c:38|d,n:"Num Up"},a.VK_NUM_DOWN={c:40|d,n:"Num Down"},a.VK_NUM_LEFT={c:37|d,n:"Num Left"},a.VK_NUM_RIGHT={c:39|d,n:"Num Right"},a.VK_NUMLOCK={c:144,n:"NumLock"},a.VK_NUM_COMMA={c:110|d,n:"Num ,"},a.VK_NUM_DIVIDE={c:111|d,n:"Num /"},a.VK_NUM_MULTIPLY={c:106|d,n:"Num *"},a.VK_NUM_MINUS={c:109|d,n:"Num -"},a.VK_NUM_PLUS={ c:107|d,n:"Num +"},a.VK_NUM_PERIOD={c:194|d,n:"Num ."},a.VK_NUM_0={c:96|d,n:"Num 0"},a.VK_NUM_1={c:97|d,n:"Num 1"},a.VK_NUM_2={c:98|d,n:"Num 2"},a.VK_NUM_3={c:99|d,n:"Num 3"},a.VK_NUM_4={c:100|d,n:"Num 4"},a.VK_NUM_5={c:101|d,n:"Num 5"},a.VK_NUM_6={c:102|d,n:"Num 6"},a.VK_NUM_7={c:103|d,n:"Num 7"},a.VK_NUM_8={c:104|d,n:"Num 8"},a.VK_NUM_9={c:105|d,n:"Num 9"},a.VK_NUM_CLEAR={c:12|d,n:"Num Clear"},a.VK_NUM_ENTER={c:13|d,n:"Num Enter"},a.VK_QUOTE={c:222,n:"'"},a.VK_BACKQUOTE={c:192,n:"`"},a.VK_MINUS={c:189,n:"-"},a.VK_EQUALS={c:187,n:"="},a.VK_OPEN_BRACKET={c:219,n:"["},a.VK_CLOSE_BRACKET={c:221,n:"]"},a.VK_COMMA={c:188,n:","},a.VK_PERIOD={c:190,n:"."},a.VK_SEMICOLON={c:186,n:";"},a.VK_SLASH={c:191,n:"/"},a.VK_BACKSLASH={c:220,n:"\\"},a.VK_ALTERNATE_ESC={c:a.VK_F1.c|jt.DOMKeys.ALT,n:["Alt","F1"]},a.VK_FF_MINUS={c:173,n:"-"},a.VK_FF_EQUALS={c:61,n:"="},a.VK_FF_SEMICOLON={c:59,n:";"},a.VK_BR_QUOTE={c:192,n:"'"},a.VK_BR_OPEN_BRACKET={c:221,n:"["},a.VK_BR_CLOSE_BRACKET={c:220,n:"]"},a.VK_BR_SEMICOLON={c:191,n:";"},a.VK_BR_SLASH={c:193,n:"/"},a.VK_BR_BACKSLASH={c:226,n:"\\"},a.VK_BR_CEDILLA={c:186,n:"Ç"},a.VK_BR_TILDE={c:222,n:"~"},a.VK_BR_ACUTE={c:219,n:"´"},a.VK_FF_BR_TILDE={c:176,n:"~"},a.VK_VOID={c:-1,n:""}}(jt.DOMKeys,jt.DOMKeys.LOCLEFT,jt.DOMKeys.LOCRIGHT,jt.DOMKeys.LOCNUM),jt.DOMKeys.forcedNames={27:"Esc",13:"Enter",32:"Space",9:"Tab",8:"BkSpc",16:"Shift",17:"Ctrl",18:"Alt",91:"Meta",93:"Context",20:"Caps",44:"PrtScr",145:"ScrLck",19:"Pause",3:"Break",45:"Ins",46:"Del",36:"Home",35:"End",33:"PgUp",34:"PgDown",38:"Up",40:"Down",37:"Left",39:"Right"},jt.DOMKeys.isModifierKeyCode=function(a){return 16===a||17===a||18===a||91===a},jt.DOMKeys.codeForKeyboardEvent=function(a){var b=a.keyCode;return this.isModifierKeyCode(b)?b&this.IGNORE_ALL_MODIFIERS_MASK|a.location<12&&(c=c.substr(0,12)),a.location){case 1:c="L-"+c;break;case 2:c="R-"+c;break;case 3:c="Num "+c}return(a.shiftKey||a.ctrlKey||a.altKey||a.metaKey)&&(c=[c],a.metaKey&&c.unshift("Meta"),a.altKey&&c.unshift("Alt"),a.ctrlKey&&c.unshift("Ctrl"),a.shiftKey&&c.unshift("Shift")),c},jt.DOMKeys.nameForKeyboardEventSingle=function(a){var b=a.keyCode,c=this.forcedNames[b]||a.key,d=c&&c.toUpperCase();switch(d&&"UNIDENTIFIED"!==d&&"UNDEFINED"!==d&&"UNKNOWN"!==d?"DEAD"===d&&(c="Dead#"+b):c="#"+b,1===c.length?c=c.toUpperCase():c.length>12&&(c=c.substr(0,12)),a.location){case 1:c="L-"+c;break;case 2:c="R-"+c;break;case 3:c="Num "+c}return c},jt.GamepadButtons={GB_1:{b:0,n:"1"},GB_2:{b:1,n:"2"},GB_3:{b:2,n:"3"},GB_4:{b:3,n:"4"},GB_L1:{b:4,n:"L1"},GB_R1:{b:5,n:"R1"},GB_L2:{b:6,n:"L2"},GB_R2:{b:7,n:"R2"},GB_BACK:{b:8,n:"BACK"},GB_START:{b:9,n:"START"},GB_S1:{b:10,n:"S1"},GB_S2:{b:11,n:"S2"},GB_UP:{b:12,n:"▲"},GB_DOWN:{b:13,n:"▼"},GB_LEFT:{b:14,n:"◄"},GB_RIGHT:{b:15,n:"►"},GB_LOGO:{b:16,n:"LOGO"},GB_VOID:{b:-1,n:"Unbound"}},jt.TouchControls={buttons:["T_B","T_A"]},jt.GamepadConsoleControls=function(a){"use strict";function b(a,b){this.index=a,this.update=function(b){return!!(c=b[a])},this.hasMoved=function(){var a=c.timestamp;return!a||a>m&&(m=a,!0)},this.getButtonDigital=function(a){var b=c.buttons[a];return"object"==typeof b?b.pressed||b.value>.5:b>.5},this.getDPadDirection=function(){return this.getButtonDigital(12)?this.getButtonDigital(15)?1:this.getButtonDigital(14)?7:0:this.getButtonDigital(13)?this.getButtonDigital(15)?3:this.getButtonDigital(14)?5:4:this.getButtonDigital(14)?6:this.getButtonDigital(15)?2:-1},this.getStickDirection=function(){var a=c.axes[d],b=c.axes[e];if((a<0?-a:a)=1&&(h-=1),8*h|0},this.getPaddlePosition=function(){var a=c.axes[h]*i*j+k|0;return a<0?a=0:a>380&&(a=380),a};var c,d=b.xAxis,e=b.yAxis,f=b.xAxisSig,g=b.yAxisSig,h=b.paddleAxis,i=b.paddleAxisSig,j=-190*b.paddleSens,k=-190*b.paddleCenter+190-5,l=b.deadzone,m=Number.MIN_VALUE}this.connect=function(a){h=a},this.connectScreen=function(a){i=a},this.powerOn=function(){(r=!!navigator.getGamepads)&&(this.applyPreferences(),e())},this.powerOff=function(){r=!1},this.toggleMode=function(){if(!r)return void i.showOSD("Joysticks unavailable (not supported by browser)",!0,!0);++u,u>0&&(u=-2),-2===u?j=k=null:-1===u&&(s=60,this.controlsClockPulse()),w=0===u,this.applyPreferences(),e(),i.showOSD("Gamepads "+this.getModeDesc(),!0)},this.setPaddleMode=function(a){r&&(v=a,l.xPosition=m.xPosition=-1)},this.setP1ControlsMode=function(a){x=a,this.applyPreferences()},this.controlsClockPulse=function(){if(r&&-2!==u&&(++s>=60&&(s=0),j||k||0===s)){var a=navigator.getGamepads();j?j.update(a)?j.hasMoved()&&f(j,l,n,p):(j=null,c(!0,!1)):0===s&&(j=d(n,o,a))&&c(!0,!0),k?k.update(a)?k.hasMoved()&&f(k,m,o,q):(k=null,c(!1,!1)):0===s&&(k=d(o,n,a))&&c(!1,!0)}};var c=function(a,b){i.showOSD((a^x^w?"P1":"P2")+" Gamepad "+(b?"connected":"disconnected"),a)},d=function(a,c,d){if(d&&0!==d.length){var e=a.device;if(e>=0)return d[e]&&d[e].buttons.length>0?new b(e,a):null;for(var f=0,g=d.length;f0&&!(f===c.device||j&&j.index===f||k&&k.index===f))return new b(f,a)}},e=function(){l=g(),m=g()},f=function(b,c,d,e){if(v&&0!==d.paddleSens){var f=b.getPaddlePosition();f!==c.xPosition&&(c.xPosition=f,a.processControlValue(d.player?t.PADDLE1_POSITION:t.PADDLE0_POSITION,f))}var g=b.getDPadDirection();if(-1!==g||v&&0!==d.paddleSens||(g=b.getStickDirection()),g!==c.direction){var h=!1,i=!1,j=!1,k=!1;switch(g){case 0:h=!0;break;case 1:h=i=!0;break;case 2:i=!0;break;case 3:j=i=!0;break;case 4:j=!0;break;case 5:j=k=!0;break;case 6:k=!0;break;case 7:h=k=!0}a.processKey(e.up.c,h),a.processKey(e.right.c,i),a.processKey(e.down.c,j),a.processKey(e.left.c,k),c.direction=g}var l=b.getButtonDigital(d.button);l!==c.button&&(a.processKey(e.button.c,l),c.button=l),(l=b.getButtonDigital(d.buttonT))!==c.buttonT&&(a.processKey(e.buttonT.c,l),c.buttonT=l);var m=b.getButtonDigital(d.select);m!==c.select&&(a.processControlState(t.SELECT,m),c.select=m);var n=b.getButtonDigital(d.reset);n!==c.reset&&(a.processControlState(t.RESET,n),c.reset=n);var o=b.getButtonDigital(d.pause);o!==c.pause&&(a.processControlState(t.PAUSE,o),c.pause=o);var p=b.getButtonDigital(d.fastSpeed);p!==c.fastSpeed&&(a.processControlState(t.FAST_SPEED,p),c.fastSpeed=p);var q=b.getButtonDigital(d.slowSpeed);q!==c.slowSpeed&&(a.processControlState(t.SLOW_SPEED,q),c.slowSpeed=q)},g=function(){return{direction:-1,button:!1,buttonT:!1,select:!1,reset:!1,fastSpeed:!1,pause:!1,xPosition:-1}};this.getModeDesc=function(){switch(u){case-1:return"AUTO";case 0:return"AUTO (swapped)";default:return r?"DISABLED":"NOT SUPPORTED"}},this.applyPreferences=function(){var a=w?1:0,b=a?0:1;n=y.joystickGamepads[a],n.player=x^w?1:0,o=y.joystickGamepads[b],o.player=x^w?0:1,p=y.joystickKeys[a],q=y.joystickKeys[b]};var h,i,j,k,l,m,n,o,p,q,r=!1,s=-1,t=jt.ConsoleControls,u=-1,v=!1,w=!1,x=!1,y=Javatari.userPreferences.current},jt.DOMTouchControls=function(a){"use strict";function b(){w.classList.toggle("jt-poweroff",!J),w.classList.toggle("jt-paused",K)}function c(){var a=A>0;document.documentElement.classList.toggle("jt-touch-active",a),document.documentElement.classList.toggle("jt-dir-big",C),t.touchControlsActiveUpdate(a,C)}function d(a){if(jt.Util.blockEvent(a),null===E){void 0===u&&i();var b=a.changedTouches[0];E=b.identifier,g(b.pageX,b.pageY)}}function e(a){jt.Util.blockEvent(a),null!==E&&(E=null,h(-1))}function f(a){if(jt.Util.blockEvent(a), null!==E)for(var b=a.changedTouches,c=0;cG&&(c=(1-Math.atan2(d,e)/Math.PI)/2,c+=1/16,c>=1&&(c-=1),c=8*c|0),h(c)}function h(b){if(F!==b){b>=0&&a.hapticFeedback();var c=!1,d=!1,e=!1,f=!1;switch(b){case 0:c=!0;break;case 1:c=d=!0;break;case 2:d=!0;break;case 3:e=d=!0;break;case 4:e=!0;break;case 5:e=f=!0;break;case 6:f=!0;break;case 7:c=f=!0}a.processKey(x.up.c,c),a.processKey(x.right.c,d),a.processKey(x.down.c,e),a.processKey(x.left.c,f),F=b}}function i(){var a=D.getBoundingClientRect();G=.14*(a.right-a.left)|0,u=((a.left+a.right)/2|0)+window.pageXOffset,v=((a.top+a.bottom)/2|0)+window.pageYOffset}function j(a){jt.Util.blockEvent(a),l(a.target.jtControl,!0)}function k(a){jt.Util.blockEvent(a),l(a.target.jtControl,!1)}function l(b,c){b&&(c&&a.hapticFeedback(),a.processKey(x[b].c,c))}function m(b){jt.Util.blockEvent(b),a.hapticFeedback(),a.processControlState(J?jt.ConsoleControls.PAUSE:jt.ConsoleControls.POWER,!0)}function n(b){jt.Util.blockEvent(b),a.processControlState(J?jt.ConsoleControls.PAUSE:jt.ConsoleControls.POWER,!1)}function o(b){jt.Util.blockEvent(b),a.processControlState(K?jt.ConsoleControls.FRAME:jt.ConsoleControls.FAST_SPEED,!0)}function p(b){jt.Util.blockEvent(b),a.processControlState(K?jt.ConsoleControls.FRAME:jt.ConsoleControls.FAST_SPEED,!1)}function q(){I.reset(),u=v=void 0,E=null,h(-1)}function r(){this.reset=function(){this.portValue=63},this.reset()}this.connect=function(a){s=a},this.connectScreen=function(a){t=a},this.powerOn=function(){this.applyPreferences(),q(),c()},this.powerOff=function(){},this.releaseControllers=function(){q()},this.updateConsolePanelSize=function(a,b,c,d,e){if(w&&d){var f=!e&&(a-b-10)/22&&(A=0),q(),this.applyPreferences(),c(),t.showOSD("Touch Controls "+this.getModeDesc(),!0)},this.setP1ControlsMode=function(a){B=a,this.applyPreferences()},this.getModeDesc=function(){switch(A){case-1:return"AUTO";case 0:return"DISABLED";case 1:return"ENABLED";case 2:return"ENABLED (swapped)"}},this.toggleTouchDirBig=function(){C=!C,L.touch.directionalBig=C,Javatari.userPreferences.setDirty(),c()},this.isDirBig=function(){return C},this.setupTouchControlsIfNeeded=function(a){function c(a,b){var c=document.createElement("div");c.id="jt-touch-"+b,c.classList.add("jt-touch-button"),c.classList.add("jt-touch-button-joy"),c.classList.add("jt-touch-button-joy-"+b),c.jtControl=b,c.addEventListener("touchstart",j),c.addEventListener("touchmove",jt.Util.blockEvent),c.addEventListener("touchend",k),c.addEventListener("touchcancel",k),c.addEventListener("mousedown",j),c.addEventListener("mouseup",k),H[b]=c,a.appendChild(c)}if(!(D||A<=0)){w=document.createElement("div"),w.id="jt-touch-speed";var g=document.createElement("div");g.id="jt-touch-pause",g.addEventListener("touchstart",m),g.addEventListener("touchend",n),w.appendChild(g);var h=document.createElement("div");h.id="jt-touch-fast",h.addEventListener("touchstart",o),h.addEventListener("touchend",p),w.appendChild(h),a.appendChild(w);var i=document.createElement("div");i.id="jt-touch-left",D=function(){function a(a){var c=document.createElement("div");c.classList.add("jt-touch-dir-"+a),b.appendChild(c);var d=document.createElement("div");d.classList.add("jt-arrow-"+a),b.appendChild(d)}var b=document.createElement("div");return b.classList.add("jt-touch-dir"),b.classList.add("jt-touch-dir-joy"),a("left"),a("right"),a("up"),a("down"),b}(),D.addEventListener("touchstart",d),D.addEventListener("touchmove",f),D.addEventListener("touchend",e),D.addEventListener("touchcancel",e),i.appendChild(D),a.appendChild(i),i=document.createElement("div"),i.id="jt-touch-right",c(i,"buttonT"),c(i,"button"),a.appendChild(i),b()}},this.consolePowerAndUserPauseStateUpdate=function(a,c){J=a,K=c,w&&b()},this.applyPreferences=function(){C=!!L.touch.directionalBig;var a=2===A?1:0;x=L.joystickKeys[a]};var s,t,u,v,w,x,y=jt.Util.isTouchDevice(),z=jt.Util.isMobileDevice(),A=Javatari.TOUCH_MODE>=0?Javatari.TOUCH_MODE:y&&z?1:0,B=!1,C=!1,D=null,E=null,F=-1,G=0,H={},I=new r,J=!1,K=!1,L=Javatari.userPreferences.current,M=84;this.saveState=function(){return{}},this.loadState=function(a){q()}},jt.DOMConsoleControls=function(a,b){"use strict";function c(a){E=a,F=E?60/I[E]|0:0,H=F/2|0,G=0}function d(a,b){a.returnValue=!1,a.preventDefault(),a.stopPropagation();var c=jt.DOMKeys.codeForKeyboardEvent(a);return j.processKey(c,b),!1}function e(b,c){if(!B||(b=l(b),!m(b,c))){if(2===a.netPlayMode&&Ca.has(b))return a.showOSD("Function not available in NetPlay Client mode",!0,!0);1===a.netPlayMode&&Ca.has(b)||R.push(b<<4|c),2!==a.netPlayMode&&f(b,c)}}function f(a,b){q.controlStateChanged(a,b)}function g(b,c){R.push(b+(c+10)),2!==a.netPlayMode&&h(b,c)}function h(a,b){q.controlValueChanged(a,b)}function i(){r.controlsModeStateUpdate()}var j=this;this.connect=function(a){q=a,q.connectControls(this),v.connect(a),w.connect(a)},this.connectPeripherals=function(a){r=a,v.connectScreen(a),w.connectScreen(a)},this.addKeyInputElement=function(a){a.addEventListener("keydown",this.keyDown),a.addEventListener("keyup",this.keyUp)},this.setupTouchControlsIfNeeded=function(a){w.setupTouchControlsIfNeeded(a)},this.powerOn=function(){k(),v.powerOn(),w.powerOn(),0===S?n(!1,!1):1===S&&n(!0,!1)},this.powerOff=function(){n(!1,!1),v.powerOff(),w.powerOff()},this.releaseControllers=function(){for(var a in t)t[a]&&(e(a,!1),t[a]=!1);L=M=P=Q=!1,y[x.JOY0_BUTTON]=y[x.JOY1_BUTTON]=!1,w.releaseControllers()},this.getTouchControls=function(){return w},this.toggleP1ControlsMode=function(){this.setP1ControlsMode(!A),o(),i()},this.setP1ControlsMode=function(a){A=a,v.setP1ControlsMode(a),w.setP1ControlsMode(a),this.releaseControllers(),p()},this.isP1ControlsMode=function(){return A},this.togglePaddleMode=function(){n(!B,!0),i()},this.isPaddleMode=function(){return B},this.setP1ControlsAndPaddleMode=function(a,b){this.setP1ControlsMode(a),n(b,!1),i()},this.toggleGamepadMode=function(){v.toggleMode(),i()},this.getGamepadModeDesc=function(){return v.getModeDesc()},this.toggleTouchControlsMode=function(){w.toggleMode(),i()},this.toggleTouchDirBig=function(){w.toggleTouchDirBig()},this.toggleTurboFireSpeed=function(){c((E+1)%11),r.showOSD("Turbo Fire"+(E?" speed: "+this.getTurboFireSpeedDesc():": OFF"),!0),z.turboFireSpeed=E,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save()},this.getTurboFireSpeedDesc=function(){return E?E+"x":"OFF"},this.getControlReport=function(a){switch(a){case jt.PeripheralControls.P1_CONTROLS_TOGGLE:return{label:A?"ON":"OFF",active:A};case jt.PeripheralControls.PADDLES_TOGGLE_MODE:return{label:B?"ON":"OFF",active:B};case jt.PeripheralControls.TOUCH_TOGGLE_DIR_BIG:return{label:w.isDirBig()?"ON":"OFF",active:w.isDirBig()};case jt.PeripheralControls.HAPTIC_FEEDBACK_TOGGLE_MODE:return{label:D?"ON":"OFF",active:!!D};case jt.PeripheralControls.TURBO_FIRE_TOGGLE:return{label:this.getTurboFireSpeedDesc(),active:!!E}}return{label:"Unknown",active:!1}},this.consolePowerAndUserPauseStateUpdate=function(a,b){w.consolePowerAndUserPauseStateUpdate(a,b)},this.keyDown=function(a){return d(a,!0)},this.keyUp=function(a){return d(a,!1)},this.controlsClockPulse=function(){if(F){if(--G===H||0===G){var a=G>0;y[x.JOY0_BUTTON]&&e(x.JOY0_BUTTON,a),y[x.JOY1_BUTTON]&&e(x.JOY1_BUTTON,a)}G<=0&&(G=F)}v.controlsClockPulse(),B&&(M?L||(J-=K,J<0&&(J=0),g(x.PADDLE0_POSITION,J)):L&&(J+=K,J>380&&(J=380),g(x.PADDLE0_POSITION,J)),Q?P||(N-=O,N<0&&(N=0),g(x.PADDLE1_POSITION,N)):P&&(N+=O,N>380&&(N=380),g(x.PADDLE1_POSITION,N)))},this.toggleHapticFeedback=function(){C?(D=!D,z.hapticFeedback=D, Javatari.userPreferences.setDirty()):r.showOSD("Haptic Feedback not available",!0,!0)},this.hapticFeedback=function(){D&&navigator.vibrate(8)},this.hapticFeedbackOnTouch=function(a){!D||"touchstart"!==a.type&&"touchend"!==a.type&&"touchmove"!==a.type||navigator.vibrate(8)},this.cartridgeInserted=function(a){if(a&&!(S>=0)){var b=1===a.rom.info.p;B!==b&&n(b,!1)}},this.processKey=function(a,c){var d=u[a];if(d){if(c===y[d])return;c&&(G=H),y[d]=c}else{if(!(d=s[a]))return b.processKey(a,c);if(c===t[d])return;t[d]=c}e(d,c)},this.applyPreferences=function(){p(),c(z.turboFireSpeed),w.applyPreferences(),v.applyPreferences()},this.processControlState=e,this.processControlValue=g;var k=function(){window.onhelp=function(){return!1}},l=function(a){switch(a){case x.JOY0_BUTTON:return x.PADDLE0_BUTTON;case x.JOY1_BUTTON:return x.PADDLE1_BUTTON;default:return a}},m=function(a,b){if(b)switch(a){case x.JOY0_LEFT:return L=!0,!0;case x.JOY0_RIGHT:return M=!0,!0;case x.JOY0_UP:return K<10&&K++,r.showOSD("P1 Paddle speed: "+K,!0),!0;case x.JOY0_DOWN:return K>1&&K--,r.showOSD("P1 Paddle speed: "+K,!0),!0;case x.JOY1_LEFT:return P=!0,!0;case x.JOY1_RIGHT:return Q=!0,!0;case x.JOY1_UP:return O<10&&O++,r.showOSD("P2 Paddle speed: "+O,!0),!0;case x.JOY1_DOWN:return O>1&&O--,r.showOSD("P2 Paddle speed: "+O,!0),!0}else switch(a){case x.JOY0_LEFT:return L=!1,!0;case x.JOY0_RIGHT:return M=!1,!0;case x.JOY1_LEFT:return P=!1,!0;case x.JOY1_RIGHT:return Q=!1,!0}return!1},n=function(b,c){B!==b&&j.releaseControllers(),B=b,K=O=2,J=N=B?190:-1,2!==a.netPlayMode&&(g(x.PADDLE0_POSITION,J),g(x.PADDLE1_POSITION,N)),v.setPaddleMode(B),c&&o()},o=function(){r.showOSD("Controllers: "+(B?"Paddles":"Joysticks")+(A?", Swapped":""),!0)},p=function(){var a=jt.DOMKeys;s={},t={},u={},s[T]=x.POWER,s[T|a.ALT]=x.POWER,s[T|a.SHIFT]=x.POWER_FRY,s[T|a.SHIFT|a.ALT]=x.POWER_FRY,s[U]=x.BLACK_WHITE,s[U|a.ALT]=x.BLACK_WHITE,s[V]=x.SELECT,s[V|a.ALT]=x.SELECT,s[W]=x.RESET,s[W|a.ALT]=x.RESET,s[X]=x.DIFFICULTY0,s[X|a.ALT]=x.DIFFICULTY0,s[Y]=x.DIFFICULTY1,s[Y|a.ALT]=x.DIFFICULTY1,s[Z]=x.FAST_SPEED,s[Z|a.ALT]=x.FAST_SPEED,s[Z|a.SHIFT]=x.SLOW_SPEED,s[Z|a.SHIFT|a.ALT]=x.SLOW_SPEED,s[$|a.SHIFT|a.ALT]=x.INC_SPEED,s[_|a.SHIFT|a.ALT]=x.DEC_SPEED,s[aa|a.SHIFT|a.ALT]=x.NORMAL_SPEED,s[ba|a.SHIFT|a.ALT]=x.MIN_SPEED,s[ca|a.ALT]=x.PAUSE,s[ca|a.SHIFT|a.ALT]=x.PAUSE_AUDIO_ON,s[da|a.ALT]=x.FRAME,s[ea|a.ALT]=x.FRAME,s[ga|a.ALT]=x.TRACE,s[ha|a.ALT]=x.SHOW_INFO,s[fa|a.ALT]=x.DEBUG,s[ia|a.ALT]=x.NO_COLLISIONS,s[ja|a.ALT]=x.VIDEO_STANDARD,s[ka|a.ALT]=x.VIDEO_STANDARD,s[la|a.ALT]=x.VSYNCH,s[ma|a.CONTROL]=x.SAVE_STATE_0,s[na|a.CONTROL]=x.SAVE_STATE_0,s[ma|a.CONTROL|a.ALT]=x.SAVE_STATE_0,s[na|a.CONTROL|a.ALT]=x.SAVE_STATE_0,s[oa|a.CONTROL]=x.SAVE_STATE_1,s[oa|a.CONTROL|a.ALT]=x.SAVE_STATE_1,s[pa|a.CONTROL]=x.SAVE_STATE_2,s[pa|a.CONTROL|a.ALT]=x.SAVE_STATE_2,s[qa|a.CONTROL]=x.SAVE_STATE_3,s[qa|a.CONTROL|a.ALT]=x.SAVE_STATE_3,s[ra|a.CONTROL]=x.SAVE_STATE_4,s[ra|a.CONTROL|a.ALT]=x.SAVE_STATE_4,s[sa|a.CONTROL]=x.SAVE_STATE_5,s[sa|a.CONTROL|a.ALT]=x.SAVE_STATE_5,s[ta|a.CONTROL]=x.SAVE_STATE_6,s[ta|a.CONTROL|a.ALT]=x.SAVE_STATE_6,s[ua|a.CONTROL]=x.SAVE_STATE_7,s[ua|a.CONTROL|a.ALT]=x.SAVE_STATE_7,s[va|a.CONTROL]=x.SAVE_STATE_8,s[va|a.CONTROL|a.ALT]=x.SAVE_STATE_8,s[wa|a.CONTROL]=x.SAVE_STATE_9,s[wa|a.CONTROL|a.ALT]=x.SAVE_STATE_9,s[xa|a.CONTROL]=x.SAVE_STATE_10,s[xa|a.CONTROL|a.ALT]=x.SAVE_STATE_10,s[ya|a.CONTROL]=x.SAVE_STATE_11,s[za|a.CONTROL]=x.SAVE_STATE_11,s[ya|a.CONTROL|a.ALT]=x.SAVE_STATE_11,s[za|a.CONTROL|a.ALT]=x.SAVE_STATE_11,s[Aa|a.CONTROL]=x.SAVE_STATE_12,s[Ba|a.CONTROL]=x.SAVE_STATE_12,s[Aa|a.CONTROL|a.ALT]=x.SAVE_STATE_12,s[Ba|a.CONTROL|a.ALT]=x.SAVE_STATE_12,s[ma|a.ALT]=x.LOAD_STATE_0,s[na|a.ALT]=x.LOAD_STATE_0,s[oa|a.ALT]=x.LOAD_STATE_1,s[pa|a.ALT]=x.LOAD_STATE_2,s[qa|a.ALT]=x.LOAD_STATE_3,s[ra|a.ALT]=x.LOAD_STATE_4,s[sa|a.ALT]=x.LOAD_STATE_5,s[ta|a.ALT]=x.LOAD_STATE_6,s[ua|a.ALT]=x.LOAD_STATE_7,s[va|a.ALT]=x.LOAD_STATE_8,s[wa|a.ALT]=x.LOAD_STATE_9,s[xa|a.ALT]=x.LOAD_STATE_10,s[ya|a.ALT]=x.LOAD_STATE_11,s[za|a.ALT]=x.LOAD_STATE_11,s[Aa|a.ALT]=x.LOAD_STATE_12,s[Ba|a.ALT]=x.LOAD_STATE_12,s[ma|a.SHIFT|a.CONTROL]=x.SAVE_STATE_0,s[na|a.SHIFT|a.CONTROL]=x.SAVE_STATE_0,s[ma|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_0,s[na|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_0,s[oa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_1,s[oa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_1,s[pa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_2,s[pa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_2,s[qa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_3,s[qa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_3,s[ra|a.SHIFT|a.CONTROL]=x.SAVE_STATE_4,s[ra|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_4,s[sa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_5,s[sa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_5,s[ta|a.SHIFT|a.CONTROL]=x.SAVE_STATE_6,s[ta|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_6,s[ua|a.SHIFT|a.CONTROL]=x.SAVE_STATE_7,s[ua|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_7,s[va|a.SHIFT|a.CONTROL]=x.SAVE_STATE_8,s[va|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_8,s[wa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_9,s[wa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_9,s[xa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_10,s[xa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_10,s[ya|a.SHIFT|a.CONTROL]=x.SAVE_STATE_11,s[za|a.SHIFT|a.CONTROL]=x.SAVE_STATE_11,s[ya|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_11,s[za|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_11,s[Aa|a.SHIFT|a.CONTROL]=x.SAVE_STATE_12,s[Ba|a.SHIFT|a.CONTROL]=x.SAVE_STATE_12,s[Aa|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_12,s[Ba|a.SHIFT|a.CONTROL|a.ALT]=x.SAVE_STATE_12,s[ma|a.SHIFT|a.ALT]=x.LOAD_STATE_0,s[na|a.SHIFT|a.ALT]=x.LOAD_STATE_0,s[oa|a.SHIFT|a.ALT]=x.LOAD_STATE_1,s[pa|a.SHIFT|a.ALT]=x.LOAD_STATE_2,s[qa|a.SHIFT|a.ALT]=x.LOAD_STATE_3,s[ra|a.SHIFT|a.ALT]=x.LOAD_STATE_4,s[sa|a.SHIFT|a.ALT]=x.LOAD_STATE_5,s[ta|a.SHIFT|a.ALT]=x.LOAD_STATE_6,s[ua|a.SHIFT|a.ALT]=x.LOAD_STATE_7,s[va|a.SHIFT|a.ALT]=x.LOAD_STATE_8,s[wa|a.SHIFT|a.ALT]=x.LOAD_STATE_9,s[xa|a.SHIFT|a.ALT]=x.LOAD_STATE_10,s[ya|a.SHIFT|a.ALT]=x.LOAD_STATE_11,s[za|a.SHIFT|a.ALT]=x.LOAD_STATE_11,s[Aa|a.SHIFT|a.ALT]=x.LOAD_STATE_12,s[Ba|a.SHIFT|a.ALT]=x.LOAD_STATE_12;var b=A?1:0,c=A?0:1;s[z.joystickKeys[b].left.c]=x.JOY0_LEFT,s[z.joystickKeys[b].up.c]=x.JOY0_UP,s[z.joystickKeys[b].right.c]=x.JOY0_RIGHT,s[z.joystickKeys[b].down.c]=x.JOY0_DOWN,s[z.joystickKeys[b].button.c]=x.JOY0_BUTTON,s[z.joystickKeys[c].left.c]=x.JOY1_LEFT,s[z.joystickKeys[c].up.c]=x.JOY1_UP,s[z.joystickKeys[c].right.c]=x.JOY1_RIGHT,s[z.joystickKeys[c].down.c]=x.JOY1_DOWN,s[z.joystickKeys[c].button.c]=x.JOY1_BUTTON,u[z.joystickKeys[b].buttonT.c]=x.JOY0_BUTTON,u[z.joystickKeys[c].buttonT.c]=x.JOY1_BUTTON};this.netGetControlsToSend=function(){return R.length?R:void 0},this.netClearControlsToSend=function(){R.length=0},this.netServerProcessControlsChanges=function(a){for(var b=0,c=a.length;b>4)||R.push(d),f(d>>4,1&d)):h(-16384&d,(16383&d)-10)}},this.netClientApplyControlsChanges=function(a){for(var b=0,c=a.length;b>4,1&d):h(-16384&d,(16383&d)-10)}};var q,r,s,t,u,v,w,x=jt.ConsoleControls,y={},z=Javatari.userPreferences.current,A=!1,B=!1,C=!!navigator.vibrate,D=C&&!!z.hapticFeedback,E=0,F=0,G=0,H=0,I=[0,1,2,2.4,3,4,5,6,7.5,10,12],J=0,K=3,L=!1,M=!1,N=0,O=3,P=!1,Q=!1,R=new Array(100);R.length=0 ;var S=Javatari.PADDLES_MODE,T=jt.DOMKeys.VK_F1.c,U=jt.DOMKeys.VK_F2.c,V=jt.DOMKeys.VK_F11.c,W=jt.DOMKeys.VK_F12.c,X=jt.DOMKeys.VK_F4.c,Y=jt.DOMKeys.VK_F9.c,Z=jt.DOMKeys.VK_TAB.c,$=jt.DOMKeys.VK_UP.c,_=jt.DOMKeys.VK_DOWN.c,aa=jt.DOMKeys.VK_RIGHT.c,ba=jt.DOMKeys.VK_LEFT.c,ca=jt.DOMKeys.VK_P.c,da=jt.DOMKeys.VK_O.c,ea=jt.DOMKeys.VK_F.c,fa=jt.DOMKeys.VK_D.c,ga=jt.DOMKeys.VK_VOID,ha=jt.DOMKeys.VK_I.c,ia=jt.DOMKeys.VK_C.c,ja=jt.DOMKeys.VK_V.c,ka=jt.DOMKeys.VK_Q.c,la=jt.DOMKeys.VK_W.c,ma=jt.DOMKeys.VK_QUOTE.c,na=jt.DOMKeys.VK_BACKQUOTE.c,oa=jt.DOMKeys.VK_1.c,pa=jt.DOMKeys.VK_2.c,qa=jt.DOMKeys.VK_3.c,ra=jt.DOMKeys.VK_4.c,sa=jt.DOMKeys.VK_5.c,ta=jt.DOMKeys.VK_6.c,ua=jt.DOMKeys.VK_7.c,va=jt.DOMKeys.VK_8.c,wa=jt.DOMKeys.VK_9.c,xa=jt.DOMKeys.VK_0.c,ya=jt.DOMKeys.VK_MINUS.c,za=jt.DOMKeys.VK_FF_MINUS.c,Aa=jt.DOMKeys.VK_EQUALS.c,Ba=jt.DOMKeys.VK_FF_EQUALS.c,Ca=new Set([x.SAVE_STATE_0,x.SAVE_STATE_1,x.SAVE_STATE_2,x.SAVE_STATE_3,x.SAVE_STATE_4,x.SAVE_STATE_5,x.SAVE_STATE_6,x.SAVE_STATE_7,x.SAVE_STATE_8,x.SAVE_STATE_9,x.SAVE_STATE_10,x.SAVE_STATE_11,x.SAVE_STATE_12,x.SAVE_STATE_FILE,x.LOAD_STATE_0,x.LOAD_STATE_1,x.LOAD_STATE_2,x.LOAD_STATE_3,x.LOAD_STATE_4,x.LOAD_STATE_5,x.LOAD_STATE_6,x.LOAD_STATE_7,x.LOAD_STATE_8,x.LOAD_STATE_9,x.LOAD_STATE_10,x.LOAD_STATE_11,x.LOAD_STATE_12,x.POWER_FRY,x.VSYNCH,x.TRACE,x.CARTRIDGE_FORMAT]);!function(){v=new jt.GamepadConsoleControls(j),w=new jt.DOMTouchControls(j),j.applyPreferences()}(),jt.DOMConsoleControls.hapticFeedback=this.hapticFeedback,jt.DOMConsoleControls.hapticFeedbackOnTouch=this.hapticFeedbackOnTouch},jt.ScreenGUI=jt.Util.isMobileDevice()?{BAR_HEIGHT:29,BAR_MENU_WIDTH:150,BAR_MENU_ITEM_HEIGHT:33,BAR_MENU_ITEM_FONT_SIZE:14,LOGO_SCREEN_WIDTH:618,LOGO_SCREEN_HEIGHT:455,TOUCH_CONTROLS_LEFT_WIDTH:119,TOUCH_CONTROLS_LEFT_WIDTH_BIG:143,TOUCH_CONTROLS_RIGHT_WIDTH:80}:{BAR_HEIGHT:29,BAR_MENU_WIDTH:140,BAR_MENU_ITEM_HEIGHT:29,BAR_MENU_ITEM_FONT_SIZE:13,LOGO_SCREEN_WIDTH:618,LOGO_SCREEN_HEIGHT:455,TOUCH_CONTROLS_LEFT_WIDTH:119,TOUCH_CONTROLS_LEFT_WIDTH_BIG:143,TOUCH_CONTROLS_RIGHT_WIDTH:80},jt.ScreenGUI.html=function(){return'
Swipe up/down on the Screen
to hide the browser bars!
'},jt.ScreenGUI.htmlConsolePanel='
',jt.ScreenGUI.css=function(){ return"html.jt-full-screen-scroll-hack body { position: absolute; width: 100%; height: "+Math.max(1280,1.4*Math.max(screen.width,screen.height)|0)+"px; top: 0; left: 0; margin: 0; padding: 0; border: none; overflow-x: hidden; overflow-y: auto; } #jt-screen-fs, #jt-screen-fs div, #jt-screen-fs canvas { outline: none; } #"+Javatari.SCREEN_ELEMENT_ID+" { display: inline-block; visibility: hidden; font-family: sans-serif; font-weight: normal; margin: 0; padding: 0; border: 1px solid black; background: black; overflow: visible; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; touch-callout: none; -webkit-tap-highlight-color: transparent; tap-highlight-color: transparent; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; } html.jt-full-screen #"+Javatari.SCREEN_ELEMENT_ID+" { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; box-shadow: none; z-index: 2147483646; /* one behind fsElement */ } html.jt-started #"+Javatari.SCREEN_ELEMENT_ID+" { visibility: visible; } #jt-screen-scroll-message { position: absolute; bottom: 150%; left: 50%; height: 0; width: 0; margin: 0; padding: 0; font-size: 16px; line-height: 28px; white-space: nowrap; color: hsl(0, 0%, 4%); background: hsl(0, 0%, 92%); border-radius: 15px; transform: translate(-50%, 0); box-shadow: 2px 2px 9px rgba(0, 0, 0, 0.7); transition: all 1.7s step-end, opacity 1.6s linear; overflow: hidden; opacity: 0; z-index: -1; } html.jt-full-screen-scroll-hack #jt-screen-fs.jt-scroll-message #jt-screen-scroll-message { opacity: 1; bottom: 23%; width: 215px; height: 56px; padding: 13px 20px; z-index: 60; transition: none; } #jt-screen-fs { position: relative; background: black; text-align: center; -webkit-tap-highlight-color: rgba(0,0,0,0); tap-highlight-color: rgba(0,0,0,0) } html.jt-full-screen #jt-screen-fs { position: absolute; width: 100%; height: 100%; left: 0; bottom: 0; right: 0; z-index: 2147483647; } html.jt-full-screen-scroll-hack #jt-screen-fs { position: fixed; bottom: 0; height: 100vh; } html.jt-full-screen #jt-screen-fs-center { /* Used to center and move things horizontally in Landscape Full Screen */ position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #jt-screen-canvas-outer { display: inline-block; position: relative; overflow: hidden; vertical-align: top; line-height: 1px; z-index: 3; } #jt-screen-canvas { display: block; } #jt-bar { position: relative; left: 0; right: 0; height: "+this.BAR_HEIGHT+'px; margin: 0 auto; border-top: 1px solid black; background: hsl(0, 0%, 16%); overflow: visible; /* for the Menu to show through */ box-sizing: content-box; z-index: 40; } #jt-bar-inner { position: absolute; overflow: hidden; top: 0; bottom: 0; left: 0; right: 0; text-align: left; } html.jt-bar-auto-hide #jt-bar, html.jt-full-screen #jt-bar { position: absolute; bottom: 0; transition: height 0.08s ease-in-out; } html.jt-bar-auto-hide #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } @media only screen and (orientation: landscape) { html.jt-full-screen #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } } #jt-bar.jt-narrow .jt-narrow-hidden { display: none; } .jt-bar-button { display: inline-block; width: 24px; height: 28px; margin: 0 1px; background-image: url("'+jt.Images.urls.iconSprites+'"); background-repeat: no-repeat; background-size: 264px 82px; cursor: pointer; } /* Firefox-specific rules */ @-moz-document url-prefix() { .jt-bar-button { image-rendering: optimizequality; } } /* .jt-bar-button { border: 1px solid yellow; background-origin: border-box; box-sizing: border-box; } */ #jt-bar-power { margin: 0 3px 0 6px; } #jt-bar-netplay.jt-hidden { display: none; } #jt-bar-select { margin: 0 2px 0 9px; width: 50px; } #jt-bar-reset { margin: 0 2px; width: 50px; } html.jt-console-panel-active #jt-bar-select, html.jt-console-panel-active #jt-bar-reset { display: none; } #jt-bar-settings, #jt-bar-full-screen, #jt-bar-scale-plus, #jt-bar-scale-minus { float: right; margin: 0; } #jt-bar-settings { margin-right: 5px; } #jt-bar-full-screen.jt-mobile { margin: 0 6px; } #jt-bar-scale-plus { width: 21px; } #jt-bar-scale-minus { width: 18px; } #jt-bar-text { float: right; width: 32px; } #jt-bar-text.jt-mobile { margin: 0 0 0 6px; } #jt-bar-console-panel { position: absolute; left: 2px; right: 0; width: 39px; margin: 0 auto; } #jt-bar.jt-narrow #jt-bar-console-panel { position: static; float: right; margin-right: 3px; } #jt-bar-logo { position: absolute; left: 0; right: 0; width: 34px; margin: 0 auto; } html:not(.jt-console-panel-active) #jt-bar.jt-narrow #jt-bar-logo { display: none; } #jt-bar-menu { position: absolute; display: none; bottom: '+this.BAR_HEIGHT+"px; font-size: "+this.BAR_MENU_ITEM_FONT_SIZE+"px; line-height: 1px; overflow: hidden; transform-origin: bottom center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-bar-menu-inner { display: inline-block; padding-bottom: 2px; border: 1px solid black; background: hsl(0, 0%, 16%); } .jt-bar-menu-item, #jt-bar-menu-title { position: relative; display: none; width: "+this.BAR_MENU_WIDTH+"px; height: "+this.BAR_MENU_ITEM_HEIGHT+"px; color: rgb(205, 205, 205); border: none; padding: 0; line-height: "+this.BAR_MENU_ITEM_HEIGHT+'px; text-shadow: 1px 1px 1px black; background: transparent; outline: none; overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden; cursor: pointer; box-sizing: border-box; } #jt-bar-menu-title { display: block; color: white; font-weight: bold; border-bottom: 1px solid black; margin-bottom: 1px; text-align: center; background: rgb(70, 70, 70); cursor: auto; } .jt-bar-menu-item.jt-hover:not(.jt-bar-menu-item-disabled):not(.jt-bar-menu-item-divider) { color: white; background: hsl(358, 67%, 46%); } .jt-bar-menu-item-disabled { color: rgb(110, 110, 110); } .jt-bar-menu-item-divider { height: 1px; margin: 1px 0; background: black; } .jt-bar-menu-item-toggle { text-align: left; padding-left: 30px; } .jt-bar-menu-item-toggle::after { content: ""; position: absolute; width: 6px; height: 19px; top: '+((this.BAR_MENU_ITEM_HEIGHT-21)/2|0)+"px; left: 10px; background: rgb(70, 70, 70); box-shadow: black 1px 1px 1px; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked { color: white; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked::after { background: rgb(248, 33, 28); } #jt-console-panel { display: none; position: absolute; bottom: -"+(jt.ConsolePanel.DEFAULT_HEIGHT+2)+"px; left: 50%; transform: translate(-50%, 0); transform-origin: center top; margin: 0 auto; border: 1px solid black; z-index: 30; } html.jt-console-panel-active #jt-console-panel { display: block; } html.jt-full-screen #jt-console-panel { bottom: "+(jt.ScreenGUI.BAR_HEIGHT+2)+'px; border: none; transform-origin: center bottom; } .jt-select-dialog { position: absolute; overflow: hidden; display: none; top: 0; bottom: 0; left: 0; right: 0; width: 540px; max-width: 92%; height: 297px; margin: auto; color: white; font-size: 18px; line-height: 21px; background: hsl(0, 0%, 16%); padding: 11px 0 0; text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } .jt-select-dialog.jt-show { display: block; } .jt-select-dialog > .jt-footer { position: absolute; width: 100%; bottom: 7px; font-size: 13px; text-align: center; color: rgb(170, 170, 170); } .jt-select-dialog > ul { position: relative; width: 88%; top: 5px; margin: auto; padding: 0; list-style: none; font-size: 14px; color: hsl(0, 0%, 88%); } .jt-select-dialog > ul li { display: none; position: relative; overflow: hidden; height: 26px; background: rgb(70, 70, 70); margin: 7px 0; padding: 11px 10px 0 18px; /* Space on the left for the toggle mark for all lines */ line-height: 0; text-align: left; text-overflow: ellipsis; border: 2px dashed transparent; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); white-space: nowrap; box-sizing: border-box; cursor: pointer; } .jt-select-dialog > ul li.jt-visible { display: block; } .jt-select-dialog > ul li.jt-selected { color: white; background: hsl(358, 67%, 46%); } .jt-select-dialog > ul li.jt-droptarget { color: white; border-color: lightgray; } .jt-select-dialog > ul li.jt-toggle::after { content: ""; position: absolute; width: 6px; height: 17px; top: 2px; left: 6px; background: rgb(60, 60, 60); box-shadow: black 1px 1px 1px; } .jt-select-dialog > ul li.jt-toggle-checked::after { background: rgb(248, 33, 28); } #jt-cartridge-format.jt-select-dialog > ul { width: 100%; height: 226px; margin: 7px auto 0; padding: 0 0 0 30px; overflow-y: auto; box-sizing: border-box; } #jt-cartridge-format.jt-select-dialog > ul li { width: 280px; margin: 7px 0 2px 0; } #jt-cartridge-format.jt-select-dialog > ul li:first-child { margin-top: 0; } #jt-cartridge-format ::-webkit-scrollbar { width: 12px; } #jt-cartridge-format ::-webkit-scrollbar-track { background: transparent; } #jt-cartridge-format ::-webkit-scrollbar-thumb { border: solid transparent; border-width: 1px 1px 1px 2px; background: rgb(80, 80, 80); background-clip: content-box; } #jt-cartridge-format ul.jt-quick-options-list { width: 230px; margin: 18px 0 0 52px; } #jt-cartridge-format ul.jt-quick-options-list li div { height: 24px; line-height: 24px; } #jt-cartridge-format .jt-control { width: 60px; line-height: 24px; } /* Firefox-specific rules */ @-moz-document url-prefix() { /* Try to hide scrollbar, since we cant style it :-( */ #jt-cartridge-format.jt-select-dialog > ul { width: 304px; } } #jt-logo { position: absolute; display: none; top: 0; bottom: 0; left: 0; right: 0; background: black; } #jt-logo.jt-show { display: block; } #jt-logo-center { position: absolute; top: 50%; left: 50%; width: 598px; height: 456px; transform: translate(-50%, -50%); } #jt-logo-image { position: absolute; top: 50%; left: 50%; width: 335px; max-width: 57%; transform: translate(-50%, -50%); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-image { top: 128px; width: 37%; max-width: initial; } #jt-logo-loading-icon, #jt-canvas-loading-icon { display: none; position: absolute; top: 79%; left: 0; right: 0; width: 14%; height: 3%; margin: 0 auto; background-color: rgba(0, 0, 0, .8); border: solid transparent; border-width: 8px 30px; border-radius: 3px; box-sizing: content-box; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-loading-icon { top: 204px; } #jt-unmute-message { display: none; position: absolute; left: 50%; bottom: 5px; height: 30px; padding: 0 10px; margin: 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; font-size: 15px; line-height: 30px; color: rgb(210, 210, 210); background: rgba(0, 0, 0, 0.7); transform-origin: bottom center; transform: translate(-50%, 0); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-unmute-message::before { content: ""; display: inline-block; width: 24px; height: 20px; margin: 5px 9px 0 0; background-image: url("'+jt.Images.urls.muteIcon+'"); background-repeat: no-repeat; background-size: 24px 20px; vertical-align: top; } #jt-unmute-message::after { content: "Audio is muted. Click to unmute"; } #jt-unmute-message.jt-show { display: inline-block; } #jt-logo-message { display: none; position: absolute; top: 226px; width: 100%; color: hsl(0, 0%, 97%); font-size: 29px; line-height: 34px; } #jt-screen-fs.jt-logo-message-active #jt-logo-message { display: block; } #jt-logo-message-ok { display: block; position: absolute; top: 91px; left: 193px; width: 214px; height: 130px; } #jt-logo-message-ok.jt-higher { top: 74px; } #jt-logo-message-ok-text { position: absolute; top: 49%; left: 50%; width: 120px; height: 47px; font-size: 23px; line-height: 47px; background: hsl(358, 67%, 46%); border-radius: 6px; color: white; transform: translate(-50%, -50%); } #jt-osd { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: -29px; right: 16px; height: 29px; padding: 0 12px; margin: 0; font-weight: bold; font-size: 15px; line-height: 29px; color: rgb(0, 255, 0); background: rgba(0, 0, 0, 0.7); transform-origin: top right; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; opacity: 0; } .jt-arrow-up, .jt-arrow-down, .jt-arrow-left, .jt-arrow-right { border: 0px solid transparent; box-sizing: border-box; } .jt-arrow-up { border-bottom-color: inherit; } .jt-arrow-down { border-top-color: inherit; } .jt-arrow-left { border-right-color: inherit; } .jt-arrow-right { border-left-color: inherit; } .jt-quick-options-list { margin-top: 12px; padding: 0; list-style: none; color: hsl(0, 0%, 88%); } .jt-quick-options-list li { margin-top: 8px; line-height: 1px; text-align: left; } .jt-quick-options-list li div { display: inline-block; overflow: hidden; height: 26px; font-size: 14px; line-height: 26px; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; } .jt-quick-options-list .jt-control { float: right; width: 86px; font-size: 15px; line-height: 25px; color: hsl(0, 0%, 70%); background: black; text-align: center; cursor: pointer; } .jt-quick-options-list .jt-control.jt-selected { color: white; background: hsl(358, 67%, 46%); box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); } .jt-quick-options-list .jt-control.jt-selected.jt-inactive { line-height: 21px; border: 2px dashed hsl(358, 67%, 46%); background: black; } #jt-quick-options { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 233px; height: 345px; margin: auto; padding: 11px 14px 0; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-quick-options.jt-show { display: block; } #jt-quick-options::before { content: "Quick Options"; display: block; } #jt-netplay { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 390px; height: 220px; margin: auto; padding-top: 11px; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform-origin: left center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-netplay.jt-show { display: block; } #jt-netplay::before { content: "Net Play!"; display: block; } #jt-netplay-status-box { position: relative; margin-top: 17px; } #jt-netplay-status { display: inline-block; position: relative; width: 340px; font-size: 15px; line-height: 27px; background: black; vertical-align: top; text-shadow: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; box-sizing: border-box; cursor: auto; } #jt-netplay-status-box.jt-active #jt-netplay-status { padding: 0 16px 0 12px; } #jt-netplay-status-box.jt-active #jt-netplay-status::after { content: ""; position: absolute; width: 6px; height: 18px; top: 4px; left: 7px; background: rgb(248, 33, 28); } #jt-netplay-link { display: none; position: absolute; right: 25px; top: 0; width: 26px; height: 27px; color: white; font-size: 15px; font-weight: 600; line-height: 27px; text-decoration: none; background: black; text-align: center; } #jt-netplay-link:hover { background: hsl(358, 67%, 46%); cursor: pointer; } #jt-netplay-status-box.jt-active #jt-netplay-link { display: block; } .jt-netplay-button { display: inline-block; width: 86px; padding: 0; margin: 0; font-size: 15px; line-height: 26px; color: white; background: hsl(358, 67%, 46%); text-shadow: 1px 1px 1px black; border: none; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); cursor: pointer; } #jt-netplay-session-box { margin-top: 18px; } #jt-netplay-session-label, #jt-netplay-nick-label { font-size: 15px; margin-bottom: 4px; } #jt-netplay-session-label::before { content: "Session Name"; } #jt-netplay-session-box input { width: 150px; height: 26px; padding: 0 10px; margin: 0 8px; font-size: 15px; line-height: 26px; background: rgb(240, 240, 240); border: none; border-radius: 0; box-sizing: border-box; outline: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; cursor: auto; } #jt-netplay-nick-label { margin-top: 10px; } #jt-netplay-nick-label::before { content: "User Nickname"; } .jt-netplay-button:disabled { color: rgb(130, 130, 130); background: rgb(70, 70, 70); cursor: default; } #jt-netplay input:disabled { color: black; background: rgb(180, 180, 180); cursor: default; } #jt-netplay-session-box.jt-disabled div { color: rgb(130, 130, 130); } input#jt-netplay-link-text { position: absolute; top: 8px; left: 50px; width: 1px; height: 1px; padding: 0; margin: 0; border: none; color: transparent; background: transparent; opacity: 0; z-index: -10; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } #jt-touch-left, #jt-touch-right, #jt-touch-speed { display: none; position: absolute; z-index: 1; } html.jt-full-screen.jt-touch-active #jt-touch-left, html.jt-full-screen.jt-touch-active #jt-touch-right, html.jt-full-screen.jt-touch-active #jt-touch-speed { display: block; } .jt-touch-dir { width: 130px; height: 130px; color: hsl(0, 0%, 75%); border-radius: 100%; } .jt-touch-dir::before { content: ""; position: absolute; top: 14px; left: 14px; right: 14px; bottom: 14px; border: 1px solid hsl(0, 0%, 26%); border-radius: 100%; } .jt-touch-dir-joy .jt-touch-dir-up, .jt-touch-dir-joy .jt-touch-dir-left { position: absolute; background: hsl(0, 0%, 31%); border-radius: 2px 2px 0 0; box-shadow: inset 1px 2px 0px hsl(0, 0%, 43%), inset -1px -1px hsl(0, 0%, 19%), 0 3px 0 1px hsl(0, 0%, 21%); } .jt-touch-dir-joy .jt-touch-dir-up { width: 26px; height: 78px; top: 24px; left: 52px; } .jt-touch-dir-joy .jt-touch-dir-left { width: 78px; height: 25px; top: 51px; left: 26px; } .jt-touch-dir-joy .jt-touch-dir-left::before { content: ""; position: absolute; top: 2px; left: 23px; width: 33px; height: 22px; background: inherit; z-index: 1; } .jt-touch-dir-joy .jt-touch-dir-left::after { content: ""; position: absolute; top: 4px; left: 30px; height: 17px; width: 17px; border-radius: 100%; box-shadow: inset 0 0 2px hsl(0, 0%, 22%), inset 1px 2px 3px 1px hsl(0, 0%, 26%), inset -1px -2px 1px hsl(0, 0%, 64%); z-index: 2; } .jt-touch-dir .jt-arrow-up, .jt-touch-dir .jt-arrow-down, .jt-touch-dir .jt-arrow-left, .jt-touch-dir .jt-arrow-right { position: absolute; border-width: 5px; z-index: 2; } .jt-touch-dir .jt-arrow-up { top: 26px; left: 60px; border-bottom-width: 11px; } .jt-touch-dir .jt-arrow-down { bottom: 29px; left: 60px; border-top-width: 11px; } .jt-touch-dir .jt-arrow-left { top: 58px; left: 26px; border-right-width: 11px; } .jt-touch-dir .jt-arrow-right { top: 58px; right: 26px; border-left-width: 11px; } .jt-touch-button { position: relative; display: block; width: 72px; height: 72px; font-size: 20px; line-height: 67px; color: hsl(0, 0%, 79%); border-radius: 100%; cursor: default; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; z-index: 0; } .jt-touch-button::before { content: ""; position: absolute; box-sizing: border-box; z-index: -1; } .jt-touch-button-joy::before, .jt-touch-button-none::before { width: 50px; height: 48px; top: 9px; left: 11px; border-radius: 100%; } #jt-screen-fs.jt-touch-config-active .jt-touch-button-none::before { border: 2px solid hsl(0, 0%, 30%); } .jt-touch-button-joy.jt-touch-button-joy-button::before { border: none; background: hsl(1, 70%, 37%); box-shadow: inset -2px -7px 3px 1px hsl(1, 68%, 43%), inset 0px 0px 1px 9px hsl(1, 72%, 33%), 0px -1px 0px 1px hsl(1, 70%, 47%), 0px 1px 0px 2px hsl(1, 70%, 29%); } .jt-touch-button-joy.jt-touch-button-joy-buttonT::before { border: none; background: hsl(220, 72%, 39%); box-shadow: inset -2px -7px 3px 1px hsl(220, 70%, 43%), inset 0px 0px 1px 9px hsl(220, 75%, 34%), 0px -1px 0px 1px hsl(220, 72%, 50%), 0px 1px 0px 2px hsl(220, 72%, 28%); } #jt-touch-button { z-index: 7 } #jt-touch-buttonT { z-index: 6 } #jt-touch-speed.jt-center { width: 84px; left: 0; right: 0; margin: 0 auto; } #jt-touch-speed.jt-center.jt-poweroff #jt-touch-pause { margin-left: 21px } #jt-touch-pause, #jt-touch-fast { float: left; width: 42px; height: 42px; border-color: hsl(0, 0%, 70%); } #jt-touch-pause::after, #jt-touch-fast::before, #jt-touch-fast::after { content: ""; display: inline-block; border: 0 solid transparent; box-sizing: border-box; } #jt-touch-pause::after { margin-top: 14px; width: 13px; height: 14px; border-width: 0; border-left-width: 4px; border-left-color: inherit; border-right-width: 4px; border-right-color: inherit; } #jt-touch-fast::before, #jt-touch-fast::after { margin-top: 14px; width: 11px; height: 14px; border-width: 7px; border-left-width: 11px; border-left-color: inherit; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-pause::after, #jt-touch-speed.jt-poweroff #jt-touch-pause::after { margin: 12px 0 0 3px; width: 15px; height: 18x; border-width: 9px; border-left-width: 15px; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-fast::after { width: 7px; border-width: 0; border-left-width: 3px; } #jt-touch-speed.jt-poweroff #jt-touch-fast { display: none; } .jt-console-panel { width:'+jt.ConsolePanel.DEFAULT_WIDTH+"px; height:"+jt.ConsolePanel.DEFAULT_HEIGHT+'px; background: black url("'+jt.Images.urls.panel+'") no-repeat; background-size: 460px 134px; box-shadow: '+jt.ConsolePanel.sameBoxShadowAsScreen()+'; outline: none; } html.jt-full-screen .jt-console-panel { box-shadow: none; } .jt-console-panel-icon { position: absolute; background: url("'+jt.Images.urls.iconSprites+'") center no-repeat; background-size: 264px 82px; } .jt-console-panel-switch { position: absolute; bottom: 107px; width: 50px; height: 26px; opacity: 0; cursor: pointer; } .jt-console-panel-switch:after { content: ""; position: absolute; left: 11px; bottom: 5px; width: 27px; height: 16px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; } .jt-console-panel-lever { position: absolute; bottom: 30px; width: 44px; height: 72px; cursor: pointer; } .jt-console-panel-lever:after { content: ""; position: absolute; left: 12px; bottom: 8px; width: 20px; height: 46px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; } .jt-console-panel-power { left: 19px; } .jt-console-panel-power:after { background-position: 0px 0px; } .jt-console-panel-color { left: 84px; } .jt-console-panel-color:after { background-position: -21px 0px; } .jt-console-panel-select { left: 340px; } .jt-console-panel-select:after { background-position: 0px -47px; } .jt-console-panel-reset { left: 403px; } .jt-console-panel-reset:after { background-position: -21px -47px; } .jt-console-panel-p0-diff { left: 152px; } .jt-console-panel-p0-diff:after { background-position: -229px -17px; } .jt-console-panel-p1-diff { left: 265px; } .jt-console-panel-p1-diff:after { background-position: -229px 0px; } .jt-console-panel-cart-image { position: absolute; left: 140px; bottom: 9px; width: 186px; height: 82px; background: url("'+jt.Images.urls.panelSprites+'") center no-repeat; background-size: 256px 93px; background-position: -42px 0px; } .jt-console-panel-cart-load { position: absolute; left: 141px; bottom: 36px; width: 184px; height: 55px; cursor: pointer; } .jt-console-panel-cart-file { left: 170px; bottom: 3px; width: 31px; height: 30px; background-position: -132px -6px; cursor: pointer; } .jt-console-panel-cart-url { left: 266px; bottom: 3px; width: 31px; height: 30px; background-position: -161px -6px; cursor: pointer; } .jt-console-panel-cart-label { position: absolute; top: 51px; left: 156px; width: 148px; height: 25px; padding: 0px 2px; margin: 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: normal; font-variant: normal; font-weight: bold; font-stretch: normal; font-size: 14px; line-height: 25px; font-family: sans-serif; text-align: center; color: black; background: black; border: 1px solid transparent; opacity: 1; cursor: pointer; } .jt-console-panel-power-labels { left: 31px; bottom: 9px; width: 88px; height: 15px; background-position: -135px -37px; } .jt-console-panel-reset-labels { right: 16px; bottom: 9px; width: 96px; height: 15px; background-position: -135px -55px; } .jt-console-panel-p0-diff-label { left: 128px; top: 8px; width: 29px; height: 15px; background-position: -233px -37px; } .jt-console-panel-p1-diff-label { left: 313px; top: 8px; width: 28px; height: 15px; background-position: -233px -55px; } .jt-hide-labels .jt-console-panel-p0-diff-label, .jt-hide-labels .jt-console-panel-p1-diff-label, .jt-hide-labels .jt-console-panel-power-labels, .jt-hide-labels .jt-console-panel-reset-labels, .jt-hide-labels .jt-console-panel-cart-file, .jt-hide-labels .jt-console-panel-cart-url { visibility: hidden; } @media only screen and (orientation: landscape) { /* Landscape */ #jt-touch-left { left: calc(-6px - '+this.TOUCH_CONTROLS_LEFT_WIDTH+"px); bottom: 50%; transform: translateY(50%); } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { left: calc(-6px - "+this.TOUCH_CONTROLS_LEFT_WIDTH_BIG+"px); transform: translateY(50%) scale(1.2); transform-origin: left center; } #jt-touch-right { right: calc(5px - "+this.TOUCH_CONTROLS_RIGHT_WIDTH+"px); bottom: 50%; transform: translateY(50%); } #jt-touch-speed { position: absolute; left: -103px; top: 10px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-speed { left: -118px; } /* Adjust centered elements leaving space to the touch controls on both sides */ html.jt-full-screen.jt-touch-active #jt-screen-fs-center { left: "+this.TOUCH_CONTROLS_LEFT_WIDTH+"px; right: "+this.TOUCH_CONTROLS_RIGHT_WIDTH+"px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-screen-fs-center { left: "+this.TOUCH_CONTROLS_LEFT_WIDTH_BIG+"px; } } @media only screen and (orientation: portrait) { /* Portrait */ #jt-touch-left { left: 2px; bottom: 200px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { transform: scale(1.2); transform-origin: left center; } #jt-touch-right { right: 5px; bottom: 144px; width: 112px; height: 112px; } #jt-touch-speed { position: absolute; left: 19px; bottom: "+(this.BAR_HEIGHT+12)+"px; } .jt-touch-button { position: absolute; } #jt-touch-button { bottom: 50%; right: 50%; } #jt-touch-buttonT { bottom: 100%; right: 0%; } } @media only screen and (orientation: portrait) and (max-device-height: 638px) { /* Medium Portrait. Like iPhone 5 */ #jt-touch-left { bottom: 156px; } #jt-touch-right { bottom: 100px; } } @media only screen and (orientation: portrait) and (max-device-height: 518px) { /* Short Portrait. Like iPhone 4 */ #jt-touch-left { bottom: 98px; } #jt-touch-right { bottom: 42px; } html.jt-console-panel-active #jt-touch-left { bottom: 106px; } html.jt-console-panel-active #jt-touch-right { bottom: 52px; } html.jt-full-screen.jt-console-panel-active #jt-touch-speed { display: none; } } " },jt.Monitor=function(a){"use strict";function b(a){var b=a<.5?.5:a>2.5?2.5:a;return Math.round(10*b)/10}function c(a){var b=a<.5?.5:a;return Math.round(10*b)/10}var d=this;this.connect=function(a){r=a,r.connectMonitor(this)},this.nextLine=function(a,b){var c=!1;return H=A&&Hv&&e()};this.setVideoStandard=function(a){G=a,s=a.totalWidth,t=a.totalHeight,u=t-Q,v=t+Q+R,J&&(y=G.defaultHeightPct,B=G.defaultOriginYPct),j(w,y),i(z,B)};var g=function(){var a=K;K=0,(a>=250&&a<=281||a>=300&&a<=325)&&++F>=5&&h(a)},h=function(a){E=a<290?jt.VideoStandard.NTSC:jt.VideoStandard.PAL;var b=L,c=a-E.totalHeight;(c=c>2?(c>6?6:c)-2:0)!=b&&(L=c,d.setVideoStandard(E))};this.videoSignalOff=function(){H=0,a.videoSignalOff()};var i=function(a,b){z=a,z<0?z=0:z>s-w&&(z=s-w),B=b,B<0?B=0:B/100*t>t-x&&(B=(t-x)/t*100),(A=B/100*t+L/2|0)+x>t&&(A=t-x)},j=function(a,b){w=a,w<10?w=10:w>s&&(w=s),y=b,y<10?y=10:y>100&&(y=100),x=y/100*(t+L)|0,x>t&&(x=t),n.width=w,n.height=x,i(z,B),k()},k=function(){a&&a.displayMetrics(w,x)},l=function(){J=!0,z=P,B=G.defaultOriginYPct,j(N,G.defaultHeightPct)},m=function(){n=document.createElement("canvas"),n.width=N,n.height=O,o=n.getContext("2d",{alpha:!1,antialias:!1}),o.globalCompositeOperation="copy",o.globalAlpha=1,p=o.createImageData(jt.VideoStandard.PAL.totalWidth,jt.VideoStandard.PAL.totalHeight),q=new Uint32Array(p.data.buffer)};this.currentLine=function(){return H},this.refresh=function(){o.putImageData(p,-z,0,z,0,w,x),a.refresh(n,w,x)},this.videoStandardDetectionStart=function(){E=null,F=0,K=0},this.getVideoStandardDetected=function(){return E},this.toggleShowInfo=function(){(M=!M)||a.showOSD(null,!0)},this.signalOff=function(){a.videoSignalOff()},this.showOSD=function(b,c,d){a.showOSD(b,c,d)},this.setDefaults=function(){l(),a.crtModeSetDefault(),a.crtFilterSetDefault(),a.requestReadjust(!0)},this.setDebugMode=function(b){a.setDebugMode(b)},this.crtModeToggle=function(){a.crtModeToggle()},this.crtFilterToggle=function(){a.crtFilterToggle()},this.fullscreenToggle=function(){a.displayToggleFullscreen()},this.displayAspectDecrease=function(){this.displayScale(b(C-S),D),this.showOSD("Display Aspect: "+C.toFixed(2)+"x",!0)},this.displayAspectIncrease=function(){this.displayScale(b(C+S),D),this.showOSD("Display Aspect: "+C.toFixed(2)+"x",!0)},this.displayScaleDecrease=function(){this.displayScale(C,c(D-S)),this.showOSD("Display Size: "+D.toFixed(2)+"x",!0)},this.displayScaleIncrease=function(){this.displayScale(C,c(D+S)),this.showOSD("Display Size: "+D.toFixed(2)+"x",!0)},this.viewportOriginDecrease=function(){J=!1,i(z,B+T),this.showOSD("Viewport Origin: "+A,!0)},this.viewportOriginIncrease=function(){J=!1,i(z,B-T),this.showOSD("Viewport Origin: "+A,!0)},this.viewportSizeDecrease=function(){l(),this.showOSD("Viewport Size: Standard",!0)},this.viewportSizeIncrease=function(){J=!1,j(s,100),this.showOSD("Viewport Size: Full Signal",!0)},this.displayScale=function(b,c){C=b,D=c,a.displayScale(C,D)},this.controlStateChanged=function(b,c){a.controlStateChanged(b,c)},this.controlsStatesRedefined=function(){a.controlsStatesRedefined()},this.consolePowerAndUserPauseStateUpdate=function(b,c){a.consolePowerAndUserPauseStateUpdate(b,c)},this.cartridgeInserted=function(b){a.cartridgeInserted(b)};var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G=jt.VideoStandard.NTSC,H=0,I=0,J=!0,K=0,L=0,M=!1,N=160,O=213,P=68,Q=16,R=5,S=.1,T=.4;!function(){m(),l(),d.setVideoStandard(G)}()},jt.ConsolePanel=function(a,b){"use strict";function c(){k(),l(),q()}function d(b){jt.Util.blockEvent(b),J||(s.hapticFeedbackOnTouch(b),a.closeAllOverlays(),b.target.jtPressed=!0,s.processControlState(b.target.jtControl,!0))}function e(a){jt.Util.blockEvent(a),a.target.jtPressed=!1,J||(s.hapticFeedbackOnTouch(a),s.processControlState(a.target.jtControl,!1))}function f(a){a.target.jtPressed&&e(a)}function g(b,c,d){d||s.hapticFeedbackOnTouch(b),c||(a.closeAllOverlays(),t.controlActivated(b.target.jtControl))}this.connectPeripherals=function(a,c,d){s=c,t=d,a.registerForDnD(b)},this.connect=function(a){u=a},this.setActive=function(a){H=a,H&&(w||c(),i(),j()),document.documentElement.classList.toggle("jt-console-panel-active",H)},this.setLogoMessageActive=function(a){J=a},this.updateScale=function(a,c,d){var e=0,f=0;if(H){a=c?d?.85*a:a-36:.85*a;var g=Math.min(1,a/jt.ConsolePanel.DEFAULT_WIDTH);b.style.transform=g<1?"translateX(-50%) scale("+g.toFixed(8)+")":"translateX(-50%)",e=Math.ceil(g*jt.ConsolePanel.DEFAULT_HEIGHT),f=Math.ceil(g*jt.ConsolePanel.DEFAULT_WIDTH)}return s&&s.getTouchControls().updateConsolePanelSize(a,f,e,c,d),e};var h=function(){o(w,!I[r.POWER]),o(x,I[r.BLACK_WHITE]),o(y,I[r.SELECT]),o(z,I[r.RESET]),o(A,I[r.DIFFICULTY0]),o(B,I[r.DIFFICULTY1]),i()},i=function(){if(o(C,v),o(G,v),G.innerHTML=v&&v.rom.info.l||L,v&&v.rom.info.lc){var a=v.rom.info.lc.trim().split(/\s+/);G.style.color=a[0]||M,G.style.background=a[1]||N,G.style.borderColor=a[2]||O}else G.style.color=M,G.style.background=N,G.style.borderColor=O},j=function(){u.controlsStateReport(I),h()},k=function(){b.innerHTML=jt.ScreenGUI.htmlConsolePanel,delete jt.ScreenGUI.htmlConsolePanel,jt.Util.isMobileDevice()&&b.classList.add("jt-hide-labels")},l=function(){w=document.getElementById("jt-console-panel-power"),m(w,r.POWER,!0),x=document.getElementById("jt-console-panel-color"),m(x,r.BLACK_WHITE,!0),y=document.getElementById("jt-console-panel-select"),m(y,r.SELECT,!0),z=document.getElementById("jt-console-panel-reset"),m(z,r.RESET,!0),A=document.getElementById("jt-console-panel-p0-diff"),m(A,r.DIFFICULTY0,!0),B=document.getElementById("jt-console-panel-p1-diff"),m(B,r.DIFFICULTY1,!0),C=document.getElementById("jt-console-panel-cart-image"),D=document.getElementById("jt-console-panel-cart-load"),n(D,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT),E=document.getElementById("jt-console-panel-cart-file"),F=document.getElementById("jt-console-panel-cart-url"),Javatari.CARTRIDGE_CHANGE_DISABLED?(p(E),p(F)):(n(E,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT),n(F,jt.PeripheralControls.AUTO_LOAD_URL))},m=function(a,b,c){a.jtControl=b,c?(a.jtPressed=!1,jt.Util.addEventsListener(a,"mousedown touchstart",d),jt.Util.addEventsListener(a,"mouseup touchend touchcancel",e),jt.Util.addEventsListener(a,"mouseleave",f)):jt.Util.onTapOrMouseDown(a,d)},n=function(a,b){a.jtControl=b,a.jtNeedsUIG=!0,jt.Util.onTapOrMouseDownWithBlockUIG(a,g)},o=function(a,b){a.style.opacity=b?1:0},p=function(a,b){a.style.display="none"},q=function(){var a=(Javatari.CARTRIDGE_LABEL_COLORS||"").trim().split(/\s+/);a[0]&&(M=a[0]),a[1]&&(N=a[1]),a[2]&&(O=a[2]),G=document.getElementById("jt-console-panel-cart-label"),n(G,jt.PeripheralControls.CARTRIDGE_LOAD_RECENT)},r=jt.ConsoleControls;this.controlStateChanged=function(a,b){H&&K[a]&&j()},this.controlsStatesRedefined=function(){H&&j()},this.cartridgeInserted=function(a){v=a,H&&i()};var s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H=!1,I={},J=!1,K={};K[r.POWER]=1,K[r.BLACK_WHITE]=1,K[r.SELECT]=1,K[r.RESET]=1,K[r.DIFFICULTY0]=1,K[r.DIFFICULTY1]=1;var L="JAVATARI",M="#fa2525",N="#101010",O="transparent"},jt.ConsolePanel.DEFAULT_WIDTH=460,jt.ConsolePanel.DEFAULT_HEIGHT=134,jt.ConsolePanel.shouldStartActive=function(){return!Javatari.SCREEN_CONSOLE_PANEL_DISABLED&&(-1===Javatari.CONSOLE_PANEL_ELEMENT_ID||document.getElementById(Javatari.CONSOLE_PANEL_ELEMENT_ID))},jt.ConsolePanel.sameBoxShadowAsScreen=function(){var a=document.getElementById(Javatari.SCREEN_ELEMENT_ID);return a?window.getComputedStyle(a,null).getPropertyValue("box-shadow"):"none"},jt.CanvasDisplay=function(room,mainElement){"use strict";function init(){jt.Util.insertCSS(jt.ScreenGUI.css()),delete jt.ScreenGUI.css,setupMain(),setupBar(),setupFullscreen(),consolePanel=new jt.ConsolePanel(self,consolePanelElement), monitor=new jt.Monitor(self)}function consolePanelUpdateForOrientation(){setConsolePanelActive(isFullscreen&&isLandscape?consolePanelActiveLandscape:consolePanelActivePortrait)}function setConsolePanelActive(a){consolePanelActive!==a&&(consolePanelActive=a,consolePanel.setActive(consolePanelActive),updateScale(),consolePanelActive?showBar():cursorHideFrameCountdown=CURSOR_HIDE_FRAMES)}function hideOSD(){osd.style.transition="all 0.15s linear",osd.style.top="-29px",osd.style.opacity=0,osdShowing=!1}function releaseControllersOnLostFocus(){consoleControlsSocket.releaseControllers()}function hideCursorAndBar(){hideCursor(),hideBar(),cursorHideFrameCountdown=-1}function showCursorAndBar(a){showCursor(),!a&&mousePointerLocked||showBar(),cursorHideFrameCountdown=CURSOR_HIDE_FRAMES}function showCursor(){cursorShowing||(fsElement.style.cursor=cursorType,cursorShowing=!0)}function hideCursor(){cursorShowing&&(fsElement.style.cursor="none",cursorShowing=!1)}function fullscreenByAPIChanged(){var a=isFullscreen,b=isFullScreenByAPI();b||fullScreenAPIExitUserRequested||!isBrowserStandalone?setFullscreenState(b):self.requestReadjust(),a&&!b&&!fullScreenAPIExitUserRequested&&isMobileDevice&&(isBrowserStandalone?setEnterFullscreenByAPIOnFirstTouch():(atariConsole.systemPause(!0),showLogoMessage("
Emulation suspended","RESUME",!0,function(){self.setFullscreen(!0),atariConsole.systemPause(!1)}))),fullScreenAPIExitUserRequested=!1}function isFullScreenByAPI(){return!!document[fullScreenAPIQueryProp]}function enterFullScreenByAPI(){if(fullscreenAPIEnterMethod)try{fullscreenAPIEnterMethod.call(fsElement)}catch(a){}}function exitFullScreenByAPI(){if(fullScreenAPIExitMethod)try{fullScreenAPIExitUserRequested=!0,fullScreenAPIExitMethod.call(document)}catch(a){}}function updateScale(){var a=Math.round(targetWidth*scaleY*aspectX*2),b=Math.round(targetHeight*scaleY);canvas.style.width=a+"px",canvas.style.height=b+"px",updateBarWidth(a),signalIsOn||updateLogoScale(),settingsDialog&&settingsDialog.isVisible()&&settingsDialog.position(),updateConsolePanelScale(a)}function updateBarWidth(a){var b=buttonsBarDesiredWidth>0?buttonsBarDesiredWidth:a;buttonsBar.style.width=-1===buttonsBarDesiredWidth?"100%":b+"px",buttonsBar.classList.toggle("jt-narrow",b0?Math.ceil(b+3)+"px":"initial"}function updateCanvasContentSize(){var a=crtFilterEffective>0?CANVAS_SIZE_FACTOR:1;canvas.width=targetWidth*a,canvas.height=targetHeight*a,canvasContext=null}function setCRTFilter(a){crtFilter=a,crtFilterEffective=-2===crtFilter?null:-1===crtFilter?crtFilterAutoValue():a,updateCanvasContentSize()}function crtFilterAutoValue(){return isMobileDevice&&!isIOSDevice&&"FIREFOX"===browserName?0:1}function setCRTMode(a){crtMode=a,crtModeEffective=-1===crtMode?crtModeAutoValue():crtMode,canvasContext=null}function crtModeAutoValue(){return isMobileDevice?0:1}function updateLogo(){signalIsOn||(updateLogoScale(),showCursorAndBar(!0),canvasContext&&canvasContext.clearRect(0,0,canvas.width,canvas.height)),logo.classList.toggle("jt-show",!signalIsOn)}function updateLoading(){var a=isLoading?"block":"none";logoLoadingIcon.style.display=a,canvasLoadingIcon.style.display=a}function createCanvasContext(){canvasContext=canvas.getContext("2d",{alpha:!1,antialias:!1}),setImageComposition(),setImageSmoothing()}function setImageComposition(){crtModeEffective>0&&!debugMode?(canvasContext.globalCompositeOperation="source-over",canvasContext.globalAlpha=.8):(canvasContext.globalCompositeOperation="copy",canvasContext.globalAlpha=1)}function setImageSmoothing(){if(canvas.style.imageRendering=0===crtFilterEffective||2===crtFilterEffective?canvasImageRenderingValue:"initial",null!==crtFilterEffective){var a=crtFilterEffective>=2;void 0!==canvasContext.imageSmoothingEnabled?canvasContext.imageSmoothingEnabled=a:(canvasContext.webkitImageSmoothingEnabled=a,canvasContext.mozImageSmoothingEnabled=a,canvasContext.msImageSmoothingEnabled=a)}}function suppressContextMenu(a){a.addEventListener("contextmenu",jt.Util.blockEvent)}function preventDrag(a){a.ondragstart=jt.Util.blockEvent}function setupMain(){switch(mainElement.innerHTML=jt.ScreenGUI.html(),mainElement.tabIndex=-1,delete jt.ScreenGUI.html,fsElement=document.getElementById("jt-screen-fs"),fsElementCenter=document.getElementById("jt-screen-fs-center"),canvasOuter=document.getElementById("jt-screen-canvas-outer"),canvas=document.getElementById("jt-screen-canvas"),canvasLoadingIcon=document.getElementById("jt-canvas-loading-icon"),osd=document.getElementById("jt-osd"),logo=document.getElementById("jt-logo"),logoCenter=document.getElementById("jt-logo-center"),logoImage=document.getElementById("jt-logo-image"),logoLoadingIcon=document.getElementById("jt-logo-loading-icon"),logoMessage=document.getElementById("jt-logo-message"),logoMessageText=document.getElementById("jt-logo-message-text"),logoMessageOK=document.getElementById("jt-logo-message-ok"),logoMessageOKText=document.getElementById("jt-logo-message-ok-text"),scrollMessage=document.getElementById("jt-screen-scroll-message"),unmuteMessage=document.getElementById("jt-unmute-message"),consolePanelElement=document.getElementById("jt-console-panel"),suppressContextMenu(mainElement),preventDrag(logoImage),preventDrag(logoLoadingIcon),preventDrag(canvasLoadingIcon),updateCanvasContentSize(),browserName){case"CHROME":case"EDGE":case"OPERA":canvasImageRenderingValue="pixelated";break;case"FIREFOX":canvasImageRenderingValue="-moz-crisp-edges";break;case"SAFARI":canvasImageRenderingValue="-webkit-optimize-contrast";break;default:canvasImageRenderingValue="pixelated"}setupMainEvents()}function setupMainEvents(){(isMobileDevice?canvasOuter:fsElement).addEventListener("mousemove",function(){showCursorAndBar()}),"onblur"in document?fsElement.addEventListener("blur",releaseControllersOnLostFocus,!0):fsElement.addEventListener("focusout",releaseControllersOnLostFocus,!0),window.addEventListener("orientationchange",function(){closeAllOverlays(),signalIsOn?hideCursorAndBar():showCursorAndBar(),self.requestReadjust()}),mainElement.addEventListener("drop",closeAllOverlays,!0),logoMessageOK.jtNeedsUIG=logoMessageOKText.jtNeedsUIG=!0,jt.Util.onTapOrMouseDownWithBlockUIG(logoMessageOK,self.closeLogoMessage),jt.Util.addEventsListener(fsElementCenter,"touchstart touchend mousedown",function(a){"touchend"!==a.type?(closeAllOverlays(),showCursorAndBar()):a.cancelable&&a.preventDefault()})}function setupBar(){buttonsBar=document.getElementById("jt-bar"),buttonsBarInner=document.getElementById("jt-bar-inner"),BAR_AUTO_HIDE&&(document.documentElement.classList.add("jt-bar-auto-hide"),fsElement.addEventListener("mouseleave",hideBar),hideBar());var a=[{label:"Power",clickModif:0,control:jt.PeripheralControls.CONSOLE_POWER_TOGGLE},{label:"Fry Console",control:jt.PeripheralControls.CONSOLE_POWER_FRY},{label:"",divider:!0},{label:"Net Play!",control:jt.PeripheralControls.SCREEN_OPEN_NETPLAY},{label:"",divider:!0},{label:"Select Cartridge",control:jt.PeripheralControls.CARTRIDGE_LOAD_RECENT},{label:"Set ROM Format",clickModif:KEY_SHIFT_MASK,control:jt.PeripheralControls.CARTRIDGE_CHOOSE_FORMAT},{label:"",divider:!0},{label:"Open File",clickModif:KEY_CTRL_MASK,control:jt.PeripheralControls.AUTO_LOAD_FILE,needsUIG:!0},{label:"Open URL",clickModif:KEY_CTRL_MASK|KEY_ALT_MASK,control:jt.PeripheralControls.AUTO_LOAD_URL,needsUIG:!0},{label:"",divider:!0},{label:"Load State",control:jt.PeripheralControls.CONSOLE_LOAD_STATE_MENU},{label:"Save State",control:jt.PeripheralControls.CONSOLE_SAVE_STATE_MENU}];powerButton=addBarButton("jt-bar-power",-5,-26,"System Power",null,!1,a,"System"),barMenuSystem=a,self.consolePowerAndUserPauseStateUpdate(!1,!1), netplayButton=addBarButton("jt-bar-netplay",-192,-1,"NetPlay!",jt.PeripheralControls.SCREEN_OPEN_NETPLAY),netplayButton.classList.add("jt-hidden"),isMobileDevice?settingsButton=addBarButton("jt-bar-settings",-33,-26,"Quick Options",jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS,!1):(a=[{label:"Help & Settings",clickModif:0,control:jt.PeripheralControls.SCREEN_OPEN_SETTINGS},{label:"Quick Options",control:jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS},{label:"Defaults",control:jt.PeripheralControls.SCREEN_DEFAULTS}],settingsButton=addBarButton("jt-bar-settings",-33,-26,"Settings",null,!1,a,"Settings")),gameSelectButton=addBarButton("jt-bar-select",-78,-51,"Game Select",jt.ConsoleControls.SELECT,!0),gameResetButton=addBarButton("jt-bar-reset",-33,-51,"Game Reset",jt.ConsoleControls.RESET,!0),-2!==FULLSCREEN_MODE&&(fullscreenButton=addBarButton("jt-bar-full-screen",-103,-1,"Full Screen",jt.PeripheralControls.SCREEN_FULLSCREEN,!1),fullscreenButton.jtNeedsUIG=!0,isMobileDevice&&fullscreenButton.classList.add("jt-mobile")),Javatari.SCREEN_RESIZE_DISABLED||isMobileDevice||(scaleUpButton=addBarButton("jt-bar-scale-plus",-80,-1,"Increase Screen",jt.PeripheralControls.SCREEN_SCALE_PLUS,!1),scaleUpButton.classList.add("jt-full-screen-hidden"),scaleDownButton=addBarButton("jt-bar-scale-minus",-58,-1,"Decrease Screen",jt.PeripheralControls.SCREEN_SCALE_MINUS,!1),scaleDownButton.classList.add("jt-full-screen-hidden")),addBarButton("jt-bar-console-panel",-61,-25,"Toggle Console Panel",jt.PeripheralControls.SCREEN_CONSOLE_PANEL_TOGGLE,!1).classList.add("jt-full-screen-only"),logoButton=addBarButton("jt-bar-logo",-99,-26,"About Javatari",jt.PeripheralControls.SCREEN_OPEN_ABOUT,!1),logoButton.classList.add("jt-full-screen-hidden"),jt.Util.onTapOrMouseDownWithBlockUIG(buttonsBar,barElementTapOrMouseDown),jt.Util.addEventsListener(buttonsBar,"touchmove",barElementTouchMove),jt.Util.addEventsListener(buttonsBar,"mouseup touchend",barElementTouchEndOrMouseUp)}function addBarButton(a,b,c,d,e,f,g,h){var i=document.createElement("div");return i.id=a,i.classList.add("jt-bar-button"),i.jtBarElementType=1,i.jtControl=e,i.jtIsConsoleControl=f,i.style.backgroundPosition=b+"px "+c+"px",i.jtBX=b,g&&(i.jtMenu=g,g.jtTitle=h,g.jtRefElement=i,g.jtMenuIndex=barMenus.length,barMenus.push(g)),d&&(i.title=d),i.addEventListener("mouseenter",function(a){barButtonHoverOver(a.target,a)}),f&&i.addEventListener("mouseleave",barButtonMouseLeft),buttonsBarInner.appendChild(i),i}function barButtonTapOrMousedown(a,b,c,d){if(d||consoleControls.hapticFeedbackOnTouch(b),!logoMessageActive&&!c){var e=barMenuActive;if(closeAllOverlays(),a.jtControl)return void(b.button||(a.jtIsConsoleControl?(barConsoleControlPressed=a.jtControl,consoleControls.processControlState(barConsoleControlPressed,!0)):peripheralControls.controlActivated(a.jtControl)));var f=a.jtMenu;if(f){var g=0|(b.altKey&&KEY_ALT_MASK)|(b.ctrlKey&&KEY_CTRL_MASK)|(b.shiftKey&&KEY_SHIFT_MASK);if(0===g&&!b.button)return void(e!==f&&(showBarMenu(f),"touchstart"===b.type&&barButtonLongTouchStart(b)));for(var h=0;h1||barMenuItemFireActive(a.shiftKey,1===a.button||a.ctrlKey))}function barMenuItemTapOrMouseDown(a,b,c){c||barMenuItemSetActive(a,"touchstart"===b.type)}function barMenuItemHoverOver(a,b){barMenuItemSetActive(a,"touchmove"===b.type)}function barMenuItemHoverOut(){barMenuItemSetActive(null)}function barMenuItemTouchEndOrMouseUp(a){logoMessageActive||!barMenuItemActive||a.button>1||barMenuItemFireActive(a.shiftKey,1===a.button||a.ctrlKey)}function barMenuItemFireActive(a,b){var c=barMenuItemActive.jtMenuOption;barMenuItemSetActive(null),c&&!c.disabled&&(c.extension?extensionsSocket.toggleExtension(c.extension,b,a):c.control&&(a|=c.secSlot,closeAllOverlays(),peripheralControls.controlActivated(c.control,b,a)))}function barMenuItemSetActive(a,b){a!==barMenuItemActive&&(barMenuItemActive&&barMenuItemActive.classList.remove("jt-hover"),a&&a.jtMenuOption?(barMenuItemActive=a,b&&consoleControls.hapticFeedback(),barMenuItemActive.classList.add("jt-hover")):barMenuItemActive=null)}function barElementTapOrMouseDown(a,b,c){cursorHideFrameCountdown=CURSOR_HIDE_FRAMES;var d=a.target;1===d.jtBarElementType?barButtonTapOrMousedown(d,a,b,c):2===d.jtBarElementType?barMenuItemTapOrMouseDown(d,a,c):hideBarMenu()}function barElementTouchMove(a){jt.Util.blockEvent(a);var b=a.changedTouches[0],c=b&&document.elementFromPoint(b.clientX,b.clientY);barButtonLongTouchTarget&&c!==barButtonLongTouchTarget&&barButtonLongTouchCancel(),2!==c.jtBarElementType&&c!==barButtonLongTouchTarget&&barMenuItemSetActive(null),1===c.jtBarElementType?barButtonHoverOver(c,a):2===c.jtBarElementType&&barMenuItemHoverOver(c,a)}function barElementTouchEndOrMouseUp(a){cursorHideFrameCountdown=CURSOR_HIDE_FRAMES,jt.Util.blockEvent(a),barButtonLongTouchCancel();var b=a.target;1===b.jtBarElementType?barButtonTouchEndOrMouseUp(a):2===b.jtBarElementType&&barMenuItemTouchEndOrMouseUp(a)}function setupFullscreen(){fullscreenAPIEnterMethod=fsElement.requestFullscreen||fsElement.webkitRequestFullscreen||fsElement.webkitRequestFullScreen||fsElement.mozRequestFullScreen,fullScreenAPIExitMethod=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen,"fullscreenElement"in document?fullScreenAPIQueryProp="fullscreenElement":"webkitFullscreenElement"in document?fullScreenAPIQueryProp="webkitFullscreenElement":"mozFullScreenElement"in document&&(fullScreenAPIQueryProp="mozFullScreenElement"),fullscreenAPIEnterMethod||!isMobileDevice||isBrowserStandalone||(fullScreenScrollHack=!0),"onfullscreenchange"in document?document.addEventListener("fullscreenchange",fullscreenByAPIChanged):"onwebkitfullscreenchange"in document?document.addEventListener("webkitfullscreenchange",fullscreenByAPIChanged):"onmozfullscreenchange"in document&&document.addEventListener("mozfullscreenchange",fullscreenByAPIChanged),fullscreenAPIEnterMethod||(scrollMessage.jtScroll=canvas.jtScroll=logo.jtScroll=logoCenter.jtScroll=logoImage.jtScroll=logoMessage.jtScroll=logoMessageText.jtScroll=logoMessageOK.jtScroll=logoMessageOKText.jtScroll=!0,fsElement.addEventListener("touchmove",function(a){if(isFullscreen){if(!fullScreenScrollHack||!a.target.jtScroll)return jt.Util.blockEvent(a);scrollMessageActive&&setScrollMessage(!1)}}))}function setEnterFullscreenByAPIOnFirstTouch(){if(fullscreenAPIEnterMethod){var a=!1,b=function(){a||(a=!0,jt.Util.removeEventsListener(fsElement,"touchend mousedown",b,!0),enterFullScreenByAPI())};jt.Util.addEventsListener(fsElement,"touchend mousedown",b,!0)} }function setFullscreenState(a){isFullscreen=a,a?(setViewport(),document.documentElement.classList.add("jt-full-screen"),fullScreenScrollHack&&document.documentElement.classList.add("jt-full-screen-scroll-hack"),consoleControls.setupTouchControlsIfNeeded(fsElementCenter),fullScreenScrollHack&&setScrollMessage(!0),fullscreenAPIEnterMethod||tryToFixSafariBugOnFullScreenChange()):(restoreViewport(),document.documentElement.classList.remove("jt-full-screen"),fullScreenScrollHack&&document.documentElement.classList.remove("jt-full-screen-scroll-hack"),fullscreenAPIEnterMethod||tryToFixSafariBugOnFullScreenChange()),closeAllOverlays(),self.requestReadjust()}function tryToFixSafariBugOnFullScreenChange(){var a=document.getElementById("jt-dummy-element");a?mainElement.removeChild(a):(a=document.createElement("div"),a.id="jt-dummy-element",mainElement.appendChild(a))}function showBar(){buttonsBar.classList.remove("jt-hidden")}function hideBar(){!BAR_AUTO_HIDE&&!isFullscreen||barMenuActive||consolePanelActive||barConsoleControlPressed||(hideBarMenu(),buttonsBar.classList.add("jt-hidden"))}function showBarMenu(a,b){if(a&&barMenuActive!==a){if(!barMenu)return setupBarMenu(),void setTimeout(function(){showBarMenu(a,b)},1);refreshBarMenu(a),barMenuItemSetActive(b?barMenu.jtDefaultItem:null);var c=a.jtRefElement,d=c&&c.offsetLeft-15||0;d+jt.ScreenGUI.BAR_MENU_WIDTH>c.parentElement.clientWidth?(barMenu.style.right=0,barMenu.style.left="auto",barMenu.style.transformOrigin="bottom right"):(d<0&&(d=0),barMenu.style.left=d+"px",barMenu.style.right="auto",barMenu.style.transformOrigin="bottom left"),showCursorAndBar(!0),barMenuActive=a,barMenu.style.display="inline-block",barMenu.jtTitle.focus()}}function refreshBarMenu(a){barMenu.jtTitle.innerHTML=a.jtTitle,barMenu.jtDefaultItem=null;for(var b,c=0,d=Math.min(a.length,BAR_MENU_MAX_ITEMS),e=jt.ScreenGUI.BAR_MENU_ITEM_HEIGHT+3,f=0;f=0&&!c[d].jtMenuOption);e>=0&&barMenuItemSetActive(c[d])}return jt.Util.blockEvent(a)}),buttonsBar.appendChild(barMenu)}function closeAllOverlays(){hideBarMenu(),saveStateDialog&&saveStateDialog.hide(),quickOtionsDialog&&quickOtionsDialog.hide(),netPlayDialog&&netPlayDialog.hide(),cartFormatDialog&&cartFormatDialog.hide(),settingsDialog&&settingsDialog.hide(),recentROMsDialog&&recentROMsDialog.hide()}function showLogoMessage(a,b,c,d){consolePanel.setLogoMessageActive(!0),logoMessageActive||(closeAllOverlays(),d&&(afterMessageAction=d),logoMessageText.innerHTML=a,logoMessageOK.classList.toggle("jt-higher",!!c),logoMessageOKText.innerHTML=b||"OK",fsElement.classList.add("jt-logo-message-active"),logoMessageActive=!0,signalIsOn=!1,updateLogo())}function updateLogoScale(){var a=canvasOuter.clientWidth,b=Math.min(a/jt.ScreenGUI.LOGO_SCREEN_WIDTH,1);logoCenter.style.transform=b<1?"translate(-50%, -50%) scale("+b.toFixed(4)+")":"translate(-50%, -50%)"}function setScrollMessage(a){console.error("Scroll Message: "+a),fsElement.classList.toggle("jt-scroll-message",a),scrollMessageActive=a,a&&setTimeout(function(){setScrollMessage(!1)},5e3)}function readjustAll(a){if(isReadjustScreeSizeChanged(a)){if(isFullscreen){buttonsBarDesiredWidth=isLandscape?0:-1;var b=readjustScreenSize.h;isLandscape||(b-=jt.ScreenGUI.BAR_HEIGHT+2),monitor.displayScale(aspectX,displayOptimalScaleY(readjustScreenSize.w,b))}else buttonsBarDesiredWidth=-1,monitor.displayScale(Javatari.SCREEN_DEFAULT_ASPECT,self.displayDefaultScale());self.focus(),consolePanelUpdateForOrientation(),consoleControlsSocket.releaseControllers()}readjustInterval&&jt.Util.performanceNow()-readjustRequestTime>=1e3&&(clearInterval(readjustInterval),readjustInterval=null)}function isReadjustScreeSizeChanged(a){var b=mainElement.parentElement.clientWidth,c=fsElementCenter.clientWidth,d=fsElementCenter.clientHeight;return!(!a&&readjustScreenSize.pw===b&&readjustScreenSize.w===c&&readjustScreenSize.h===d)&&(readjustScreenSize.pw=b,readjustScreenSize.w=c,readjustScreenSize.h=d,isLandscape=c>d,!0)}function displayOptimalScaleY(a,b){var c=2*aspectX,d=b/targetHeight;return targetWidth*c*d>a&&(d=a/(targetWidth*c)),d}function setViewport(){if(isMobileDevice){if(void 0===viewPortOriginalContent&&(viewPortOriginalTag=document.querySelector("meta[name=viewport]"),viewPortOriginalContent=viewPortOriginalTag&&viewPortOriginalTag.content||null),viewportTag||(viewportTag=document.createElement("meta"),viewportTag.name="viewport",viewportTag.content="width = device-width, height = device-height, initial-scale = 1.0, minimum-scale = 1.0, maximum-scale = 1.0, user-scalable = yes",document.head.appendChild(viewportTag)),viewPortOriginalTag)try{document.head.removeChild(viewPortOriginalTag)}catch(a){}viewPortOriginalTag=null}}function restoreViewport(){if(isMobileDevice){if(!viewPortOriginalTag&&viewPortOriginalContent&&(viewPortOriginalTag=document.createElement("meta"),viewPortOriginalTag.name="viewport",viewPortOriginalTag.content=viewPortOriginalContent,document.head.appendChild(viewPortOriginalTag)),viewportTag)try{document.head.removeChild(viewportTag)}catch(a){}viewportTag=null}}function setPageVisibilityHandling(){function a(){logoMessageActive||(document.hidden?b=!atariConsole.systemPause(!0):b&&atariConsole.systemPause(!1))}var b;document.addEventListener("visibilitychange",a)}var self=this;this.connect=function(a){atariConsole=a,monitor.connect(atariConsole.getVideoOutput()), consoleControlsSocket=atariConsole.getConsoleControlsSocket(),cartridgeSocket=atariConsole.getCartridgeSocket(),consolePanel.connect(consoleControlsSocket)},this.connectPeripherals=function(a,b,c,d,e,f){recentROMs=a,fileLoader=b,b.registerForDnD(fsElement),b.registerForFileInputElement(fsElement),fileDownloader=c,fileDownloader.registerForDownloadElement(fsElement),peripheralControls=e,consoleControls=d,consoleControls.addKeyInputElement(fsElement),stateMedia=f,consolePanel.connectPeripherals(b,consoleControls,peripheralControls)},this.powerOn=function(){monitor.setDefaults(),updateLogo(),document.documentElement.classList.add("jt-started"),setPageVisibilityHandling(),this.focus(),JavatariFullScreenSetup.shouldStartInFullScreen()&&(setFullscreenState(!0),setEnterFullscreenByAPIOnFirstTouch())},this.powerOff=function(){document.documentElement.classList.remove("jt-started")},this.start=function(a){function b(){self.setFullscreen(!0),a()}!isMobileDevice||isBrowserStandalone||isFullscreen?a():jt.Util.isOfficialHomepage()?showLogoMessage("For "+(fullscreenAPIEnterMethod?"the best":"a full-screen")+' experience, use
the "Add to Home Screen" function
then launch from the Installed App',"NICE!",!1,b):showLogoMessage("For the best experience,
Javatari will go full-screen","GO!",!0,b)},this.refresh=function(a,b,c){cursorHideFrameCountdown>0&&--cursorHideFrameCountdown<=0&&hideCursorAndBar(),signalIsOn||(signalIsOn=!0,updateLogo()),canvasContext||createCanvasContext(),canvasContext.drawImage(a,0,0,canvas.width,canvas.height)},this.videoSignalOff=function(){signalIsOn=!1,showCursorAndBar(),updateLogo()},this.mousePointerLocked=function(a){mousePointerLocked=a,mousePointerLocked?hideCursorAndBar():showCursorAndBar()},this.openHelp=function(){return self.openSettings("GENERAL"),!1},this.openAbout=function(){return self.openSettings("ABOUT"),!1},this.openSettings=function(a){closeAllOverlays(),settingsDialog||(settingsDialog=new jt.SettingsDialog(fsElementCenter,consoleControls)),settingsDialog.show(a)},this.openSaveStateDialog=function(a){closeAllOverlays(),saveStateDialog||(saveStateDialog=new jt.SaveStateDialog(fsElementCenter,consoleControls,peripheralControls,stateMedia)),saveStateDialog.show(a)},this.openQuickOptionsDialog=function(){closeAllOverlays(),quickOtionsDialog||(quickOtionsDialog=new jt.QuickOptionsDialog(fsElementCenter,consoleControls,consoleControlsSocket,peripheralControls)),quickOtionsDialog.show()},this.openNetPlayDialog=function(){closeAllOverlays(),netPlayDialog||(netPlayDialog=new jt.NetPlayDialog(room,fsElementCenter)),netPlayDialog.show()},this.openCartridgeFormatDialog=function(a){closeAllOverlays(),cartFormatDialog||(cartFormatDialog=new jt.CartridgeFormatDialog(this,fsElementCenter,atariConsole,cartridgeSocket)),cartFormatDialog.show(a)},this.openLoadFileDialog=function(a,b){fileLoader.openFileChooserDialog(jt.FileLoader.OPEN_TYPE.AUTO,a,b,!1)},this.openRecentROMsDialog=function(){closeAllOverlays(),recentROMsDialog||(recentROMsDialog=new jt.RecentROMsDialog(fsElementCenter,this,recentROMs,fileLoader)),recentROMsDialog.show()},this.openCartridgeChooserDialog=function(a,b,c){logoMessageActive&&self.closeLogoMessage(),a||0!==recentROMs.getCatalog().length?this.openRecentROMsDialog():this.openLoadFileDialog(b,c)},this.toggleConsolePanel=function(){isFullscreen&&isLandscape?consolePanelActiveLandscape=!consolePanelActiveLandscape:consolePanelActivePortrait=!consolePanelActivePortrait,consolePanelUpdateForOrientation()},this.getControlReport=function(a){return{label:-2===crtFilter?"Browser":-1===crtFilter?"Auto":0===crtFilter?"OFF":"Level "+crtFilter,active:crtFilter>=0}},this.toggleMenuByKey=function(){barMenuActive?hideBarMenu():(closeAllOverlays(),showBarMenu(barMenuSystem,!0))},this.getScreenCapture=function(){if(signalIsOn)return canvas.toDataURL("image/png")},this.saveScreenCapture=function(){var a=this.getScreenCapture();a&&fileDownloader.startDownloadURL("Javatari Screen",a,"Screen Capture")},this.displayMetrics=function(a,b){targetWidth===a&&targetHeight===b||(targetWidth=a,targetHeight=b,updateCanvasContentSize(),isFullscreen?this.requestReadjust(!0):updateScale())},this.displayScale=function(a,b){aspectX=a,scaleY=b,updateScale()},this.getMonitor=function(){return monitor},this.showOSD=function(a,b,c){if(osdTimeout&&clearTimeout(osdTimeout),!a)return osd.style.transition="all 0.15s linear",osd.style.top="-29px",osd.style.opacity=0,void(osdShowing=!1);!b&&osdShowing||(osd.innerHTML=a,osd.style.color=c?"rgb(255, 60, 40)":"rgb(0, 255, 0)"),osd.style.transition="none",osd.style.top="15px",osd.style.opacity=1,osdShowing=!0;var d=canvasOuter.clientWidth-30,e=osd.clientWidth,f=e0)return Javatari.SCREEN_DEFAULT_SCALE;var a=Number.parseFloat(window.getComputedStyle(mainElement.parentElement).width);return a>=640?2:a>=540?1.65:a>=420?1.25:a>=355?1.05:a>=340?1:a>=300?.9:.8},this.setDebugMode=function(a){debugMode=!!a,canvasContext=null},this.crtFilterToggle=function(){var a=crtFilter+1;a>3&&(a=-2),setCRTFilter(a);var b=null===crtFilterEffective?"browser default":crtFilterEffective<1?"OFF":"level "+crtFilterEffective;this.showOSD("CRT filter: "+(-1===crtFilter?"AUTO ("+b+")":b),!0),Javatari.userPreferences.current.crtFilter!==crtFilter&&(Javatari.userPreferences.current.crtFilter=crtFilter,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save())},this.crtFilterSetDefault=function(){var a=Javatari.userPreferences.current.crtFilter;setCRTFilter(-3!==Javatari.SCREEN_FILTER_MODE?Javatari.SCREEN_FILTER_MODE:null!==a&&a>-3?a:-1)},this.crtModeToggle=function(){var a=crtMode+1;a>1&&(a=-1),setCRTMode(a);var b=1===crtModeEffective?"Phosphor":"OFF";this.showOSD("CRT mode: "+(-1===crtMode?"AUTO ("+b+")":b),!0)},this.crtModeSetDefault=function(){setCRTMode(Javatari.SCREEN_CRT_MODE)},this.displayToggleFullscreen=function(){if(-2!==FULLSCREEN_MODE)return fullscreenAPIEnterMethod&&!isFullScreenByAPI()?void enterFullScreenByAPI():void this.setFullscreen(!isFullscreen)},this.setFullscreen=function(a){fullscreenAPIEnterMethod?a?enterFullScreenByAPI():exitFullScreenByAPI():setFullscreenState(a)},this.focus=function(){canvas.focus()},this.consolePowerAndUserPauseStateUpdate=function(a,b){isLoading&&(a=!1),powerButton.style.backgroundPosition=powerButton.jtBX+"px "+mediaButtonBackYOffsets[a?2:1]+"px",powerButton.jtMenu[0].label="Power "+(a?"OFF":"ON");var c=2===room.netPlayMode;powerButton.jtMenu[1].disabled=powerButton.jtMenu[12].disabled=c||!a,powerButton.jtMenu[6].disabled=c||!(cartridgeSocket&&cartridgeSocket.inserted()),powerButton.jtMenu[5].disabled=powerButton.jtMenu[8].disabled=powerButton.jtMenu[9].disabled=powerButton.jtMenu[11].disabled=c},this.cartridgeInserted=function(a){consolePanel.cartridgeInserted(a),powerButton.jtMenu[6].disabled=!a||2===room.netPlayMode},this.controlsModeStateUpdate=function(){settingsDialog&&settingsDialog.controlsModeStateUpdate(),quickOtionsDialog&&quickOtionsDialog.controlsModeStateUpdate()},this.touchControlsActiveUpdate=function(a,b){touchControlsActive===a&&touchControlsDirBig===b||(touchControlsActive=a,touchControlsDirBig=b,isFullscreen&&(touchControlsActive&&consoleControls.setupTouchControlsIfNeeded(fsElementCenter),this.requestReadjust(!0)))},this.roomNetPlayStatusChangeUpdate=function(a){netPlayDialog&&netPlayDialog.isVisible()||closeAllOverlays(),netPlayDialog&&netPlayDialog.roomNetPlayStatusChangeUpdate(a),netplayButton.classList.toggle("jt-hidden",room.netPlayMode<1)},this.controlStateChanged=function(a,b){consolePanel.controlStateChanged(a,b),quickOtionsDialog&&quickOtionsDialog.controlStateChanged(a,b)},this.controlsStatesRedefined=function(){consolePanel.controlsStatesRedefined()},this.speakerUnlockStateUpdate=function(a){ if(unmuteMessage.classList.toggle("jt-show",!a),!a){var b=canvasOuter.clientWidth-30,c=unmuteMessage.clientWidth,d=c=0&&(c&&jt.DOMConsoleControls.hapticFeedbackOnTouch(a),m=a.target.jtItem,f(),c||setTimeout(b,120))}),j.addEventListener("keydown",function(c){return c.keyCode===q?a():r.indexOf(c.keyCode)>=0?b():s[c.keyCode]&&(m+=s[c.keyCode],m<0?m=0:m>l.length&&(m=l.length),f()),jt.Util.blockEvent(c)})}var i=this;this.show=function(b){if(!j)return g(),setTimeout(function(){i.show(b)},0);l=c.getCatalog().slice(0),l.sort(function(a,b){return a.n>b.n});var d=c.lastROMLoadedIndex;d=l.indexOf(l.find(function(a){return a.i===d})),m=d<0||d>=l.length?l.length:d,o=!0,e(),j.classList.add("jt-show"),j.focus(),jt.Util.scaleToFitParentHeight(j,a,jt.ScreenGUI.BAR_HEIGHT)},this.hide=function(a){if(o&&(j.classList.remove("jt-show"),o=!1,Javatari.room.screen.focus(),a))if(m===l.length)b.openLoadFileDialog();else{var e=c.getROM(l[m].i);d.loadROM(e)}};var j,k,l=[],m=0,n=[],o=!1,p=jt.DOMKeys,q=p.VK_ESCAPE.c,r=[p.VK_ENTER.c,p.VK_SPACE.c],s={};s[p.VK_UP.c]=-1,s[p.VK_DOWN.c]=1},jt.SaveStateDialog=function(a,b,c,d){"use strict";function e(){l.textContent="Select Slot to "+(m?"Save":"Load");for(var a=m?"Save to ":"Load from ",b=0;b=0&&(c&&jt.DOMConsoleControls.hapticFeedbackOnTouch(a),n=a.target.jtSlot,f(),c||setTimeout(b,120))}),j.addEventListener("keydown",function(c){return c.keyCode===u?a():v.indexOf(c.keyCode)>=0?b():w[c.keyCode]&&(n+=w[c.keyCode],n<0?n=0:n>10&&(n=10),f()),jt.Util.blockEvent(c)})}var i=this;this.show=function(b){if(!j)return g(),setTimeout(function(){i.show(b)},0);m=b,p=!0,e(),j.classList.add("jt-show"),j.focus(),jt.Util.scaleToFitParentHeight(j,a,jt.ScreenGUI.BAR_HEIGHT)},this.hide=function(a){if(p&&(j.classList.remove("jt-show"),p=!1,Javatari.room.screen.focus(),a)){var d=s[n],e=m?d.save:d.load;d.peripheral?c.controlActivated(e):b.processControlState(e,!0)}};var j,k,l,m=!1,n=0,o=[],p=!1,q=jt.ConsoleControls,r=jt.PeripheralControls,s=[{d:"Slot 1",load:q.LOAD_STATE_1,save:q.SAVE_STATE_1},{d:"Slot 2",load:q.LOAD_STATE_2,save:q.SAVE_STATE_2},{d:"Slot 3",load:q.LOAD_STATE_3,save:q.SAVE_STATE_3},{d:"Slot 4",load:q.LOAD_STATE_4,save:q.SAVE_STATE_4},{d:"Slot 5",load:q.LOAD_STATE_5,save:q.SAVE_STATE_5},{d:"Slot 6",load:q.LOAD_STATE_6,save:q.SAVE_STATE_6},{d:"Slot 7",load:q.LOAD_STATE_7,save:q.SAVE_STATE_7},{d:"Slot 8",load:q.LOAD_STATE_8,save:q.SAVE_STATE_8},{d:"Slot 9",load:q.LOAD_STATE_9,save:q.SAVE_STATE_9},{d:"Slot 10",load:q.LOAD_STATE_10,save:q.SAVE_STATE_10},{d:"File...",load:r.CONSOLE_LOAD_STATE_FILE,save:r.CONSOLE_SAVE_STATE_FILE,peripheral:!0 }],t=jt.DOMKeys,u=t.VK_ESCAPE.c,v=[t.VK_ENTER.c,t.VK_SPACE.c],w={};w[t.VK_UP.c]=-1,w[t.VK_DOWN.c]=1},jt.QuickOptionsDialog=function(a,b,c,d){"use strict";function e(){for(var a=0;a=0&&h.hide(),jt.Util.blockEvent(a)})}var h=this;this.show=function(){if(!i)return f(),setTimeout(h.show,0);e(),k=!0,i.classList.add("jt-show"),i.focus(),jt.Util.scaleToFitParentHeight(i,a,jt.ScreenGUI.BAR_HEIGHT)},this.hide=function(){k&&(Javatari.userPreferences.save(),i.classList.remove("jt-show"),k=!1,Javatari.room.screen.focus())},this.controlsModeStateUpdate=function(){k&&e()},this.controlStateChanged=function(a,b){!k||a!==m.NO_COLLISIONS&&a!==m.VSYNCH||e()};var i,j,k=!1,l=[],m=jt.ConsoleControls,n=jt.DOMKeys,o=[n.VK_ESCAPE.c,n.VK_ENTER.c,n.VK_SPACE.c]},jt.NetPlayDialog=function(a,b){"use strict";function c(){switch(a.netPlayMode){case 0:o.textContent="STANDALONE",m.textContent="HOST",n.textContent="JOIN",m.disabled=!1,n.disabled=!1,r.disabled=!1,s.disabled=!1,k.classList.remove("jt-active"),l.classList.remove("jt-disabled"),r.setAttribute("placeholder","Enter a name");break;case 1:var b=a.getNetServer();o.textContent="HOSTING Session: "+b.getSessionID(),m.textContent="STOP",n.textContent="JOIN",m.disabled=!1,n.disabled=!0,r.disabled=!0,s.disabled=!0,k.classList.add("jt-active"),l.classList.add("jt-disabled"),r.setAttribute("placeholder","Automatic"),p.href=e();break;case 2:var c=a.getNetClient();o.textContent="JOINED Session: "+c.getSessionID(),m.textContent="HOST",n.textContent="LEAVE",m.disabled=!0,n.disabled=!1,r.disabled=!0,s.disabled=!0,k.classList.add("jt-active"),l.classList.remove("jt-disabled"),l.classList.add("jt-disabled"),r.setAttribute("placeholder","Enter a name"),p.href=e();break;case-1:case-2:o.textContent="Establishing connection...",r.disabled=!0,s.disabled=!0,k.classList.remove("jt-active"),l.classList.add("jt-disabled"),-1===a.netPlayMode?(m.textContent="CANCEL",n.textContent="JOIN",m.disabled=!1,n.disabled=!0,r.setAttribute("placeholder","Automatic")):(m.textContent="HOST",n.textContent="CANCEL",m.disabled=!0,n.disabled=!1,r.setAttribute("placeholder","Enter a name"))}}function d(){r.value=u.netPlaySessionName,s.value=u.netPlayNick}function e(){return jt.Util.browserCurrentURL()+"?JOIN="+a.netController.getSessionID()}function f(b){var c=b.target;if(!c.disabled){jt.DOMConsoleControls.hapticFeedbackOnTouch(b);var d=!1,e=a.netPlayMode;if(c!==m||0!==e&&1!==e&&-1!==e?c!==n||0!==e&&2!==e&&-2!==e||(0===e?(a.getNetClient().joinSession(r.value,s.value),d=!0):a.getNetClient().leaveSession(!1,-2===e?"NetPlay connection aborted":void 0)):0===e?(a.getNetServer().startSession(r.value),d=!0):a.getNetServer().stopSession(!1,-1===e?"NetPlay connection aborted":void 0),d){var f=r.value.trim(),g=s.value.trim();u.netPlaySessionName===f&&u.netPlayNick===g||(u.netPlaySessionName=f,u.netPlayNick=g,Javatari.userPreferences.setDirty(),Javatari.userPreferences.save())}}}function g(){j=document.createElement("div"),j.id="jt-netplay",j.tabIndex=-1,k=document.createElement("div"),k.id="jt-netplay-status-box",j.appendChild(k),q=document.createElement("input"),q.id="jt-netplay-link-text",k.appendChild(q),o=document.createElement("div"),o.id="jt-netplay-status",o.textContent="STANDALONE",k.appendChild(o),p=document.createElement("a"),p.id="jt-netplay-link",p.textContent="🔗",p.setAttribute("title","Copy Join Session link to clipboard"),k.appendChild(p),l=document.createElement("div"),l.id="jt-netplay-session-box",j.appendChild(l);var a=document.createElement("div");a.id="jt-netplay-session-label",l.appendChild(a),m=document.createElement("button"),m.id="jt-netplay-start",m.jtCommand=!0,m.classList.add("jt-netplay-button"),m.textContent="HOST",l.appendChild(m),r=document.createElement("input"),r.id="jt-netplay-session-name",r.setAttribute("placeholder","Enter a name"),r.setAttribute("maxlength",12),r.spellcheck=!1,r.autocorrect=!1,r.autocapitalize=!1,l.appendChild(r),n=document.createElement("button"),n.id="jt-netplay-join",n.jtCommand=!0,n.classList.add("jt-netplay-button"),n.textContent="JOIN",l.appendChild(n);var c=document.createElement("div");c.id="jt-netplay-nick-label",l.appendChild(c),s=document.createElement("input"),s.id="jt-netplay-nick",s.setAttribute("placeholder","Automatic"),s.setAttribute("maxlength",12),s.spellcheck=!1,s.autocorrect=!1,s.autocapitalize=!1,l.appendChild(s),h(),b.appendChild(j)}function h(){function b(a){var b=a.target,c=b.value;return!c||c.match(/^[A-Za-z0-9]+[A-Za-z0-9_\-]*@?$/)?b.jtLastValidValue=c:b.value=b.jtLastValidValue||""}jt.Util.onTapOrMouseDownWithBlock(j,function(a){a.target.jtCommand?f(a):j.focus()}),j.addEventListener("keydown",function(a){return w.indexOf(a.keyCode)>=0&&i.hide(),jt.Util.blockEvent(a)}),r.addEventListener("input",b),s.addEventListener("input",b),jt.Util.addEventsListener(o,"touchstart touchmove touchend mousedown mousemove mouseup keydown keyup",function(a){a.stopPropagation()}),jt.Util.addEventsListener(r,"touchstart touchmove touchend mousedown mousemove mouseup keydown keyup",function(a){a.stopPropagation()}),jt.Util.addEventsListener(s,"touchstart touchmove touchend mousedown mousemove mouseup keydown keyup",function(a){a.stopPropagation()}),j.ondragstart=jt.Util.blockEvent,k.addEventListener("contextmenu",function(a){a.stopPropagation()}),jt.Util.addEventsListener(p,"click",function(b){if(jt.Util.blockEvent(b),!document.queryCommandSupported||!document.queryCommandSupported("copy"))return a.showOSD("Copy to Clipboard not supported by the browser!",!0,!0);q.value=e(),q.focus(),q.select(),document.execCommand("copy"),j.focus()})}var i=this;this.show=function(){if(!j)return g(),setTimeout(i.show,0);c(),d(),t=!0,j.classList.add("jt-show"),j.focus(),jt.Util.scaleToFitParentWidth(j,b,12)},this.hide=function(){t&&(j.classList.remove("jt-show"),t=!1,a.screen.focus())},this.roomNetPlayStatusChangeUpdate=function(b){if(t&&c(),2===a.netPlayMode&&b<0&&t)return setTimeout(function(){i.hide()},2e3);0===a.netPlayMode&&b>0&&!t&&i.show()},this.isVisible=function(){return t};var j,k,l,m,n,o,p,q,r,s,t=!1,u=Javatari.userPreferences.current,v=jt.DOMKeys,w=[v.VK_ESCAPE.c]},jt.CartridgeFormatDialog=function(a,b,c,d){"use strict";function e(){q=0, k.reinsertROMContent(),r=jt.CartridgeCreator.getUserFormatOptionNames(k.rom);var a=jt.CartridgeCreator.getBestFormatOption(k.rom);a||(a=jt.CartridgeFormats["4K"]),r.unshift(a.name);for(var b=0;ba.offsetTop?m.scrollTop=a.offsetTop:m.scrollTop+m.offsetHeight=0&&c(a.target.jtIndex)}),jt.Util.addEventsListener(m,"click",function(a){if(jt.Util.blockEvent(a),a.target.jtIndex>=0){var d=a.target.jtIndex===q;c(a.target.jtIndex),setTimeout(b,d?0:120)}}),jt.Util.onTapOrMouseDownWithBlock(n,function(a){v&&(jt.DOMConsoleControls.hapticFeedbackOnTouch(a),u=!u,g())}),l.addEventListener("keydown",function(c){var d=x.codeForKeyboardEvent(c);return d===y?a():z.indexOf(d)>=0?b():A[d]&&(q+=A[d],q<0?q=0:q>=r.length&&(q=r.length-1),f()),jt.Util.blockEvent(c)})}var j=this;this.show=function(a){if(!l)return h(),setTimeout(function(){j.show(a)},0);o=a,(k=d.inserted())&&(p=k.format.name,u=!!w.getForROM(k.rom),v=!!k.rom.info.h,t=!0,l.classList.add("jt-show"),e(),l.focus(),jt.Util.scaleToFitParentHeight(l,b,jt.ScreenGUI.BAR_HEIGHT))},this.hide=function(b){if(t){if(l.classList.remove("jt-show"),t=!1,Javatari.room.screen.focus(),b){var e=r[q],f=e===r[0],g=jt.CartridgeCreator.changeCartridgeFormat(k,jt.CartridgeFormats[e]);u&&w.setForROM(k.rom,e,f),d.insert(g,!o&&c.powerIsOn,!0),a.showOSD("ROM Format: "+e+(f?" (Auto)":""),!0)}k=void 0}};var k,l,m,n,o=!1,p="",q=0,r=[],s=[],t=!1,u=!1,v=!1,w=Javatari.userROMFormats,x=jt.DOMKeys,y=x.VK_ESCAPE.c,z=[x.VK_ENTER.c,x.VK_SPACE.c],A={};A[x.VK_UP.c]=-1,A[x.VK_DOWN.c]=1},jt.SettingsGUI={WIDTH:600,HEIGHT:450},jt.SettingsGUI.html=function(){ return'
Help & Settings
CONSOLE
CONTROLLERS
EMULATION
ABOUT
F1
POWER
F2
TV TYPE
F4
P1 Difficulty
F5
Load Cartridge File
F6
Load Cartridge URL
F7
Remove Cartridge
F12
RESET
F11
SELECT
F9
P2 Difficulty
Alt
 + 
L
Toggle Paddles
Alt
 + 
K
Toggle Swap Sides
Alt
 + 
J
Toggle Gamepads
Alt
 + 
H
Adjust Turbo Fire speed
PLAYER 1
Fire
Up
Turbo Fire
Left
Right
Down
PLAYER 2
Fire
Up
Turbo Fire
Left
Right
Down
Alt
 + 
C
Collisions
Shift
 + 
F1
Fry Console
Alt
 + 
Q
NTSC/PAL
Alt
 + 
W
V-Synch Modes
Alt
 + 
R
CRT Modes
Alt
 + 
T
CRT Filters
Alt
 + 
D
Debug Modes
Alt
 + 
I
Show Info
Alt
 + 
G
Capture Screen
Right-Click Bar Icons: Default Action
Alt
 + 
0 - 9
Load State
Ctrl
 + 
0 - 9
Save State
F8
Save State File
F12
  /  
Shift
 + 
F12
Fast / Slow Speed
Shift
 
Alt
 + 
Arrows
Adjust Speed
Alt
 + 
P
Toggle Pause
Alt
 + 
O
 / 
F
Next Frame
Alt
 + 
Enter
Full Screen
Ctrl
 
Alt
 + 
Arrows
Screen Size / Width
Shift
 
Ctrl
 + 
Arrows
Viewport Size / Origin
Backspace
Defaults
version '+Javatari.VERSION+'
'+atob("Q3JlYXRlZCBieSBQYXVsbyBBdWd1c3RvIFBlY2Npbg==")+"
"+atob("PGEgdGFyZ2V0PSJfYmxhbmsiIGhyZWY9Imh0dHA6Ly9qYXZhdGFyaS5vcmciPmh0dHA6Ly9qYXZhdGFyaS5vcmc8L2E+")+'
' },jt.SettingsGUI.css=function(){return"#jt-modal * { outline: none; box-sizing: border-box; } #jt-modal { position: absolute; overflow: hidden; width: "+jt.SettingsGUI.WIDTH+"px; height: 0; opacity: 0; visibility: hidden; top: 50%; left: 50%; color: hsl(0, 0%, 10%); font: normal 13px sans-serif; white-space: nowrap; text-align: initial; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform: scale(0.85); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out, height .25s step-end; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; z-index: 50; } #jt-modal.jt-show { transform: scale(1); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out; height: "+jt.SettingsGUI.HEIGHT+'px; visibility: visible; opacity: 1; } #jt-modal .jt-heading { font-weight: 700; color: hsl(0, 0%, 30%); } #jt-modal .jt-link { font-weight: 700; line-height: 21px; color: hsl(228, 90%, 40%); cursor: pointer; } #jt-modal .jt-link:hover { outline: 1px solid; } .jt-command { position: relative; display: inline-block; font-weight: 600; color: hsl(0, 0%, 48%); } .jt-hotkey { height: 27px; padding: 3px 5px; box-sizing: border-box; } .jt-hotkey .jt-desc { display: inline-block; line-height: 21px; } .jt-key { position: relative; display: inline-block; top: -1px; min-width: 25px; height: 21px; padding: 4px 6px 3px; box-sizing: border-box; font-weight: 600; font-size: 12px; line-height: 12px; color: hsl(0, 0%, 42%); background: white; border-radius: 3px; border: 1px solid rgb(210, 210, 210); box-shadow: 0 1px 0 1px hsl(0, 0%, 47%); text-align: center; } .jt-key-fixed { width: 31px; padding-left: 0; padding-right: 2px; } .jt-footer { margin-top: 16px; text-align: center; } #jt-menu { position: relative; background: white; border-bottom: 1px solid hsl(0, 0%, 72%); } #jt-menu #jt-back { position: absolute; width: 40px; height: 34px; margin: 3px 1px; padding: 16px 12px; cursor: pointer; } #jt-menu #jt-back:hover { background: rgba(0, 0, 0, .12); } .jt-back-arrow { display: block; width: 16px; height: 2px; border-radius: 1000px; background: hsl(0, 0%, 98%); } .jt-back-arrow:before { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(-45deg); transform-origin: 1px 1px; } .jt-back-arrow:after { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(45deg); transform-origin: 1px 1px; } #jt-menu .jt-caption { height: 29px; margin: 0 -1px; padding: 10px 0 0 48px; font-size: 18px; color: white; background: hsl(358, 66%, 50%); box-shadow: 0 1px 3px rgba(0, 0, 0, .9); vertical-align: middle; box-sizing: content-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-menu .jt-items { position: relative; width: 84%; height: 39px; margin: 0 auto; font-weight: 600; } #jt-menu .jt-item { float: left; width: 25%; height: 100%; padding-top: 13px; font-size: 14px; color: rgba(0, 0, 0, .43); text-align: center; cursor: pointer; } #jt-menu .jt-selected { color: hsl(358, 67%, 46%); } #jt-menu #jt-menu-selection { position: absolute; left: 0; bottom: 0; width: 25%; height: 3px; background: hsl(358, 67%, 46%); transition: left 0.3s ease-in-out; } #jt-content { position: relative; left: 0; width: 3000px; height: 371px; background: rgb(218, 218, 218); transition: left 0.3s ease-in-out } #jt-console, #jt-ports, #jt-general, #jt-about { position: absolute; width: '+jt.SettingsGUI.WIDTH+"px; height: 100%; box-sizing: border-box; } #jt-console { padding-top: 35px; } #jt-console .jt-hotkey { height: 29px; } #jt-console .jt-command { width: 42px; } #jt-console .jt-left, #jt-console .jt-middle, #jt-console .jt-right { float: left; } #jt-console .jt-left { width: 160px; margin-left: 58px; } #jt-console .jt-middle { width: 204px; } #jt-console .jt-right .jt-command { width: 46px; } #jt-console .jt-console-panel { position: relative; margin: 18px auto 0; box-shadow: rgba(0, 0, 0, 0.6) 2px 2px 4px; } #jt-console .jt-console-panel * { cursor: auto; } #jt-console .jt-footer { margin: 20px auto; } #jt-ports { left: "+jt.SettingsGUI.WIDTH+'px; padding: 18px 0 0 27px; } #jt-ports > .jt-left { float: left; width: 335px; padding-left: 26px; } #jt-ports > .jt-right { float: left; } #jt-ports .jt-command { width: 91px; } #jt-ports .jt-bottom { width: 546px; text-align: center; } #jt-ports .jt-player { position: absolute; top: 146px; width: 217px; color: rgba(0, 0, 0, .8); } #jt-ports .jt-p1 { left: 47px; } #jt-ports .jt-p2 { right: 47px; } #jt-ports .jt-title { margin-bottom: 09px; font-size: 14px; line-height: 14px; font-weight: bold; color: hsl(0, 0%, 35%); text-align: center; } #jt-ports .jt-player .jt-command { display: block; position: relative; float: left; width: 33%; height: 45px; font-size: 13px; text-align: center; } #jt-ports .jt-command.jt-fire1, #jt-ports .jt-command.jt-fire2 { top: 14px; } #jt-ports .jt-command.jt-left, #jt-ports .jt-command.jt-right { top: 27px; } #jt-ports .jt-command.jt-down { float: none; clear: both; margin: 0 auto; } #jt-ports .jt-command.jt-controller { height: 90px; } #jt-ports #jt-control-p1-controller, #jt-ports #jt-control-p2-controller { width: 70px; height: 89px; margin-left: 1px; background: url("'+jt.Images.urls.controllers+'") no-repeat -1px 0; background-size: 73px 179px; } #jt-ports .jt-player .jt-key { min-width: 33px; height: 23px; padding: 5px 6px 4px; margin-top: 2px; cursor: pointer; } #jt-ports .jt-player .jt-key:hover { box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5), 1px 2px 6px 4px rgb(170, 170, 170); } #jt-ports .jt-player .jt-key.jt-redefining { color: white; background-color: rgb(87, 128, 255); border-color: rgb(71, 117, 255); } #jt-ports .jt-player .jt-key.jt-undefined { background-color: rgb(255, 150, 130); border-color: rgb(255, 130, 90); } #jt-ports-defaults, #jt-ports-revert { position: absolute; left: 260px; width: 82px; text-align: center; padding: 3px 0 1px; font-size: 12px; } #jt-ports-defaults { bottom: 47px; } #jt-ports-revert { bottom: 21px; } #jt-general { left: '+2*jt.SettingsGUI.WIDTH+"px; padding-top: 18px; padding-left: 34px; } #jt-general .jt-left { float: left; width: 245px; } #jt-general .jt-left .jt-command { width: 99px; } #jt-general .jt-right { float: left; } #jt-general .jt-right .jt-command { width: 160px; } #jt-about { left: "+3*jt.SettingsGUI.WIDTH+'px; font-size: 18px; } #jt-about #jt-logo-version { width: 300px; height: 238px; margin: 26px auto 19px; color: hsl(0, 0%, 98%); padding-top: 200px; box-sizing: border-box; text-align: center; background: black url("'+jt.Images.urls.logo+'") center 18px no-repeat; background-size: 233px 173px; box-shadow: 3px 3px 14px rgb(75, 75, 75); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-about .jt-info { line-height: 30px; text-align: center; } #jt-about a { color: rgb(0, 40, 200); text-decoration: none; } #jt-about a:hover { text-decoration: underline; } #jt-about #jt-browserinfo { position: absolute; left: 0; right: 0; bottom: 7px; font-size: 10px; text-align: center; color: transparent; } .jt-clear { clear: both; } .jt-divider { clear: both; height: 27px; } .jt-full-divider { clear: both; height: 21px; } #jt-general .jt-full-divider { clear: both; height: 18px; }'},jt.SettingsDialog=function(a,b){"use strict";function c(){jt.Util.insertCSS(jt.SettingsGUI.css()),a.insertAdjacentHTML("beforeend",jt.SettingsGUI.html()),j=document.getElementById("jt-modal"),delete jt.SettingsGUI.html,delete jt.SettingsGUI.css,d(),e()}function d(){function a(b,c){c(b);for(var d=b.childNodes,e=0;e=0;d-=1)b[d]=0;if(0!==j.length)for(var e=j.length-1;e>=0;e-=1){for(var f=n[e],g=j[e].retrieveSamples(c*f+o[e]|0,r),h=g.buffer,i=g.bufferSize,k=g.start+o[e],l=0;l=i&&(k-=i);o[e]=k-(0|k)}}this.connect=function(a){a.connectMonitor(this)},this.connectPeripherals=function(a){g=a},this.connectAudioSignal=function(a){j.indexOf(a)>=0||(jt.Util.arrayAdd(j,a),e())},this.disconnectAudioSignal=function(a){j.indexOf(a)<0||(jt.Util.arrayRemoveAllElement(j,a),e())},this.powerOn=function(){h(),m&&(d(),this.unpause())},this.powerOff=function(){this.pause(),k&&k.close(),k=m=void 0},this.mute=function(){r=!0},this.unMute=function(){r=!1},this.pause=function(){m&&m.disconnect()},this.unpause=function(){m&&m.connect(k.destination)},this.toggleBufferBaseSize=function(){if(!k)return g.showOSD("Audio is DISABLED",!0,!0);q=(q+2)%8-1,this.pause(),i(),this.unpause(),g.showOSD("Audio Buffer size: "+(-1===q?"Auto ("+l+")":0===q?"Browser ("+l+")":l),!0),p.audioBufferBase=q,Javatari.userPreferences.setDirty()},this.getControlReport=function(a){return{label:-2===q?"OFF":-1===q?"Auto":0===q?"Browser":l,active:q>0}};var g,h=function(){if(-2===q||0===Javatari.AUDIO_MONITOR_BUFFER_SIZE)return void jt.Util.warning("Audio disabled in configuration");try{var a=window.AudioContext||window.webkitAudioContext||window.WebkitAudioContext;if(!a)throw new Error("WebAudio API not supported by the browser");k=new a,jt.Util.log("Speaker AudioContext created. Sample rate: "+k.sampleRate+(k.state?", "+k.state:"")),i()}catch(a){jt.Util.error("Could not create AudioContext. Audio DISABLED!\n"+a)}},i=function(){try{ var a=-1===q?b():0===q?c():q,d=Javatari.AUDIO_MONITOR_BUFFER_SIZE>0?Javatari.AUDIO_MONITOR_BUFFER_SIZE:a>0?jt.Util.exp2(0|jt.Util.log2((k.sampleRate+14e3)/22050))*jt.Util.exp2(a-1)*256:0;m=k.createScriptProcessor(d,1,1),m.onaudioprocess=f,l=m.bufferSize,e(),jt.Util.log("Audio Processor buffer size: "+m.bufferSize)}catch(a){jt.Util.error("Could not create ScriptProcessorNode. Audio DISABLED!\n"+a)}},j=[];this.signals=j;var k,l,m,n=[],o=[],p=Javatari.userPreferences.current,q=-3===Javatari.AUDIO_MONITOR_BUFFER_BASE?p.audioBufferBase:Javatari.AUDIO_MONITOR_BUFFER_BASE,r=!1},jt.LocalStorageSaveStateMedia=function(a){"use strict";function b(){return 2===a.netPlayMode}this.connect=function(a){a.connectMedia(this)},this.connectPeripherals=function(a){c=a},this.isSlotUsed=function(a){return void 0!==localStorage["javatarisave"+a]},this.saveState=function(a,b){var c=f(b);return c&&d("save"+a,c)},this.loadState=function(a){var b=e("save"+a);return g(b)},this.saveStateFile=function(a,d){if(!b()){var e=f(d);e&&c.startDownloadBinary((a||"Javatari SaveState")+j,e,"System State file")}},this.loadStateFile=function(a){if(!b())return g(a)},this.saveResource=function(a,b){try{var c=b&&JSON.stringify(b);return d("res"+a,c)}catch(a){}},this.loadResource=function(a){try{var b=e("res"+a);return b&&JSON.parse(b)}catch(a){}},this.externalStateChange=function(){1===a.netPlayMode&&a.netController.processExternalStateChange()};var c,d=function(a,c){if(b())return!0;try{return localStorage["javatari"+a]=c,!0}catch(a){return jt.Util.error(a),!1}},e=function(a){if(!b())try{return localStorage["javatari"+a]}catch(a){jt.Util.warning(a)}},f=function(a){try{return h+JSON.stringify(a)}catch(a){jt.Util.error(a)}},g=function(a){try{var b;if((b="string"==typeof a?a.substr(0,h.length):jt.Util.int8BitArrayToByteString(a,0,h.length))!==h&&b!==i)return;var c;return(c="string"==typeof a?a.slice(h.length):jt.Util.int8BitArrayToByteString(a,h.length))&&JSON.parse(c)}catch(a){jt.Util.error(a)}},h=String.fromCharCode(0,0)+"javataristate!",i="javatarijsstate!",j=".jst"},jt.PeripheralControls={SCREEN_ASPECT_PLUS:1,SCREEN_ASPECT_MINUS:2,SCREEN_SCALE_PLUS:3,SCREEN_SCALE_MINUS:4,VIEWPORT_ORIGIN_PLUS:5,VIEWPORT_ORIGIN_MINUS:6,VIEWPORT_SIZE_PLUS:7,VIEWPORT_SIZE_MINUS:8,SCREEN_FULLSCREEN:10,SCREEN_CRT_FILTER:11,SCREEN_CRT_MODE:12,SCREEN_TOGGLE_MENU:13,SCREEN_OPEN_HELP:14,SCREEN_OPEN_ABOUT:15,SCREEN_OPEN_SETTINGS:16,SCREEN_OPEN_QUICK_OPTIONS:17,SCREEN_DEFAULTS:18,SCREEN_CONSOLE_PANEL_TOGGLE:19,SPEAKER_BUFFER_TOGGLE:20,CONSOLE_POWER_TOGGLE:102,CONSOLE_POWER_FRY:103,CONSOLE_LOAD_STATE_FILE:104,CONSOLE_SAVE_STATE_FILE:105,CONSOLE_LOAD_STATE_MENU:106,CONSOLE_SAVE_STATE_MENU:107,P1_CONTROLS_TOGGLE:201,JOYSTICKS_TOGGLE_MODE:202,PADDLES_TOGGLE_MODE:203,TOUCH_TOGGLE_MODE:204,TOUCH_TOGGLE_DIR_BIG:205,TURBO_FIRE_TOGGLE:206,HAPTIC_FEEDBACK_TOGGLE_MODE:207,CAPTURE_SCREEN:304,CARTRIDGE_LOAD_RECENT:40,CARTRIDGE_LOAD_FILE:41,CARTRIDGE_LOAD_URL:42,CARTRIDGE_REMOVE:43,CARTRIDGE_LOAD_DATA_FILE:44,CARTRIDGE_SAVE_DATA_FILE:45,CARTRIDGE_CHOOSE_FORMAT:46,AUTO_LOAD_FILE:47,AUTO_LOAD_URL:48,SCREEN_OPEN_NETPLAY:500},jt.DOMPeripheralControls=function(a){"use strict";var b=this;this.connect=function(a){i=a},this.connectPeripherals=function(a,b,c,i){d=a,f=b,e=a.getMonitor(),g=c,h=i},this.getControlReport=function(a){switch(a){case k.PADDLES_TOGGLE_MODE:case k.P1_CONTROLS_TOGGLE:case k.TURBO_FIRE_TOGGLE:case k.TOUCH_TOGGLE_DIR_BIG:case k.HAPTIC_FEEDBACK_TOGGLE_MODE:return g.getControlReport(a);case k.SCREEN_CRT_FILTER:return d.getControlReport(a);case k.SPEAKER_BUFFER_TOGGLE:return f.getControlReport(a)}return{label:"Unknown",active:!1}},this.processKey=function(a,c){if(!c)return!1;var d=l[a]||l[a&m];return!!d&&(b.controlActivated(d,!!(a&n),!1),!0)},this.controlActivated=function(b,j,l){if(2===a.netPlayMode&&N.has(b))return a.showOSD("Function not available in NetPlay Client mode",!0,!0);switch(b){case k.CONSOLE_POWER_TOGGLE:g.processControlState(jt.ConsoleControls.POWER,!0);break;case k.CONSOLE_POWER_FRY:g.processControlState(jt.ConsoleControls.POWER_FRY,!0);break;case k.CONSOLE_LOAD_STATE_FILE:h.openFileChooserDialog(o.STATE,!1,!1,!1);break;case k.CONSOLE_SAVE_STATE_FILE:g.processControlState(jt.ConsoleControls.SAVE_STATE_FILE,!0);break;case k.CONSOLE_LOAD_STATE_MENU:d.openSaveStateDialog(!1);break;case k.CONSOLE_SAVE_STATE_MENU:d.openSaveStateDialog(!0);break;case k.CARTRIDGE_LOAD_RECENT:c()||d.openCartridgeChooserDialog(!1,j,l);break;case k.CARTRIDGE_LOAD_FILE:c()||h.openFileChooserDialog(o.ROM,j,l,!1);break;case k.CARTRIDGE_LOAD_URL:c()||h.openURLChooserDialog(o.ROM,j,l);break;case k.CARTRIDGE_REMOVE:c()||i.insert(null,!1);break;case k.CARTRIDGE_LOAD_DATA_FILE:case k.CARTRIDGE_SAVE_DATA_FILE:break;case k.CARTRIDGE_CHOOSE_FORMAT:c()||d.openCartridgeFormatDialog(j);break;case k.AUTO_LOAD_FILE:c()||h.openFileChooserDialog(o.AUTO,j,l,!1);break;case k.AUTO_LOAD_URL:c()||h.openURLChooserDialog(o.AUTO,j,l,!1);break;case k.SCREEN_CRT_MODE:e.crtModeToggle();break;case k.SCREEN_CRT_FILTER:e.crtFilterToggle();break;case k.SCREEN_FULLSCREEN:e.fullscreenToggle();break;case k.SCREEN_DEFAULTS:g.processControlState(jt.ConsoleControls.DEFAULTS,!0),e.setDefaults();break;case k.SCREEN_TOGGLE_MENU:d.toggleMenuByKey();break;case k.SCREEN_OPEN_HELP:d.openHelp();break;case k.SCREEN_OPEN_ABOUT:d.openAbout();break;case k.SCREEN_OPEN_SETTINGS:if(j)return this.controlActivated(k.SCREEN_DEFAULTS);d.openSettings();break;case k.SCREEN_OPEN_QUICK_OPTIONS:d.openQuickOptionsDialog();break;case k.SCREEN_CONSOLE_PANEL_TOGGLE:d.toggleConsolePanel();break;case k.SCREEN_OPEN_NETPLAY:d.openNetPlayDialog();break;case k.P1_CONTROLS_TOGGLE:g.toggleP1ControlsMode();break;case k.JOYSTICKS_TOGGLE_MODE:g.toggleGamepadMode();break;case k.PADDLES_TOGGLE_MODE:g.togglePaddleMode();break;case k.TOUCH_TOGGLE_MODE:g.toggleTouchControlsMode();break;case k.TOUCH_TOGGLE_DIR_BIG:g.toggleTouchDirBig();break;case k.TURBO_FIRE_TOGGLE:g.toggleTurboFireSpeed();break;case k.HAPTIC_FEEDBACK_TOGGLE_MODE:g.toggleHapticFeedback();break;case k.CAPTURE_SCREEN:d.saveScreenCapture();break;case k.SPEAKER_BUFFER_TOGGLE:f.toggleBufferBaseSize();break;case k.VIEWPORT_ORIGIN_MINUS:e.viewportOriginDecrease();break;case k.VIEWPORT_ORIGIN_PLUS:e.viewportOriginIncrease()}if(!M)switch(b){case k.SCREEN_ASPECT_MINUS:e.displayAspectDecrease();break;case k.SCREEN_ASPECT_PLUS:e.displayAspectIncrease();break;case k.SCREEN_SCALE_MINUS:e.displayScaleDecrease();break;case k.SCREEN_SCALE_PLUS:e.displayScaleIncrease();break;case k.VIEWPORT_SIZE_MINUS:e.viewportSizeDecrease();break;case k.VIEWPORT_SIZE_PLUS:e.viewportSizeIncrease()}};var c=function(){return Javatari.CARTRIDGE_CHANGE_DISABLED?(e.showOSD("Cartridge change is disabled!",!0,!0),!0):2===a.netPlayMode&&(e.showOSD("Cartridge change is disabled in NetPlay Client mode!",!0,!0),!0)};this.mediaChangeDisabledWarning=c;var d,e,f,g,h,i,j=function(){var a=jt.DOMKeys;l[x]=k.CARTRIDGE_LOAD_RECENT,l[x|a.ALT]=k.CARTRIDGE_LOAD_RECENT,l[y]=k.AUTO_LOAD_URL,l[y|a.ALT]=k.AUTO_LOAD_URL,l[z]=k.CARTRIDGE_REMOVE,l[z|a.ALT]=k.CARTRIDGE_REMOVE,l[L]=k.CONSOLE_SAVE_STATE_FILE,l[L|a.ALT]=k.CONSOLE_SAVE_STATE_FILE,l[A|a.ALT]=k.P1_CONTROLS_TOGGLE,l[C|a.ALT]=k.PADDLES_TOGGLE_MODE,l[B|a.ALT]=k.JOYSTICKS_TOGGLE_MODE,l[D|a.ALT]=k.TOUCH_TOGGLE_MODE,l[E|a.ALT]=k.TURBO_FIRE_TOGGLE,l[G|a.ALT]=k.SCREEN_CRT_FILTER,l[F|a.ALT]=k.SCREEN_CRT_MODE,l[H|a.ALT]=k.SCREEN_OPEN_SETTINGS,l[I|a.ALT]=k.SCREEN_OPEN_QUICK_OPTIONS,l[J|a.ALT]=k.SCREEN_CONSOLE_PANEL_TOGGLE,l[K|a.ALT]=k.SCREEN_FULLSCREEN,l[q|a.CONTROL|a.ALT]=k.SCREEN_SCALE_MINUS,l[s|a.CONTROL|a.ALT]=k.SCREEN_SCALE_PLUS,l[p|a.CONTROL|a.ALT]=k.SCREEN_ASPECT_MINUS,l[r|a.CONTROL|a.ALT]=k.SCREEN_ASPECT_PLUS,l[q|a.SHIFT|a.CONTROL]=k.VIEWPORT_ORIGIN_MINUS,l[s|a.SHIFT|a.CONTROL]=k.VIEWPORT_ORIGIN_PLUS,l[p|a.SHIFT|a.CONTROL]=k.VIEWPORT_SIZE_MINUS,l[r|a.SHIFT|a.CONTROL]=k.VIEWPORT_SIZE_PLUS,l[t]=k.SCREEN_TOGGLE_MENU,l[u]=k.SCREEN_DEFAULTS, l[u|a.ALT]=k.SCREEN_DEFAULTS,l[v|a.ALT]=k.CAPTURE_SCREEN,l[w|a.ALT]=k.SPEAKER_BUFFER_TOGGLE},k=jt.PeripheralControls,l={},m=~jt.DOMKeys.SHIFT,n=jt.DOMKeys.SHIFT,o=jt.FileLoader.OPEN_TYPE,p=jt.DOMKeys.VK_LEFT.c,q=jt.DOMKeys.VK_UP.c,r=jt.DOMKeys.VK_RIGHT.c,s=jt.DOMKeys.VK_DOWN.c,t=jt.DOMKeys.VK_CONTEXT.c,u=jt.DOMKeys.VK_BACKSPACE.c,v=jt.DOMKeys.VK_G.c,w=jt.DOMKeys.VK_A.c,x=jt.DOMKeys.VK_F5.c,y=jt.DOMKeys.VK_F6.c,z=jt.DOMKeys.VK_F7.c,A=jt.DOMKeys.VK_K.c,B=jt.DOMKeys.VK_J.c,C=jt.DOMKeys.VK_L.c,D=jt.DOMKeys.VK_N.c,E=jt.DOMKeys.VK_H.c,F=jt.DOMKeys.VK_R.c,G=jt.DOMKeys.VK_T.c,H=jt.DOMKeys.VK_Y.c,I=jt.DOMKeys.VK_U.c,J=jt.DOMKeys.VK_S.c,K=jt.DOMKeys.VK_ENTER.c,L=(jt.DOMKeys.VK_F1.c,jt.DOMKeys.VK_F8.c),M=Javatari.SCREEN_RESIZE_DISABLED,N=new Set([k.CONSOLE_POWER_FRY,k.CONSOLE_LOAD_STATE_FILE,k.CONSOLE_SAVE_STATE_FILE,k.CONSOLE_LOAD_STATE_MENU,k.CONSOLE_SAVE_STATE_MENU,k.CARTRIDGE_LOAD_RECENT,k.CARTRIDGE_LOAD_FILE,k.CARTRIDGE_LOAD_URL,k.CARTRIDGE_REMOVE,k.CARTRIDGE_LOAD_DATA_FILE,k.CARTRIDGE_SAVE_DATA_FILE,k.AUTO_LOAD_FILE,k.AUTO_LOAD_URL]);!function(){j()}()},jt.NetServer=function(a){"use strict";function b(){void 0===v&&(v=setInterval(p,3e4));var a={sessionControl:"createSession",sessionType:"javatari",wsOnly:D,queryVariables:["RTC_CONFIG","RTC_DATA_CHANNEL_CONFIG"]};u&&(a.sessionID=u),s.send(JSON.stringify(a))}function c(){r.stopSession(!0,v?"NetPlay Session stopped: Connection lost":"NetPlay: Connection error")}function d(a){var b=JSON.parse(a.data);if(b.javatariUpdate)return o(b.javatariUpdate);if(b.sessionControl)switch(b.sessionControl){case"sessionCreated":return void e(b);case"clientJoined":return void f(b);case"clientLeft":return void g(b);case"createError":return void r.stopSession(!0,"NetPlay: "+b.errorMessage)}else b.clientSDP&&h(b)}function e(b){try{w=JSON.parse(b.queriedVariables.RTC_CONFIG||"{}")}catch(a){}try{x=JSON.parse(b.queriedVariables.RTC_DATA_CHANNEL_CONFIG||"{}")}catch(a){}t=b.sessionID,z.netClearControlsToSend(),a.enterNetServerMode(r),a.showOSD('NetPlay session "'+b.sessionID+'" started',!0),jt.Util.log('NetPlay session "'+b.sessionID+'" started')}function f(b){var c={nick:b.clientNick,justJoined:!0,wsOnly:D||!!b.wsOnly};if(C[c.nick]=c,a.showOSD('NetPlay client "'+c.nick+'" joined',!0),jt.Util.log('NetPlay client "'+c.nick+'" joined'),!c.wsOnly){var d=new RTCPeerConnection(w);c.rtcConnection=d,d.onicecandidate=function(a){a.candidate||(jt.Util.log("Server SDP for client "+c.nick+":",d.localDescription),s.send(JSON.stringify({toClientNick:c.nick,serverSDP:d.localDescription})))};var e=d.createDataChannel("dataChannel",x);c.dataChannel=e,e.onopen=function(a){i(c,a)},e.onclose=function(a){j(c,a)},e.onmessage=function(a){k(c,a)},d.createOffer().then(function(a){return d.setLocalDescription(a)}).catch(function(a){l(c,a)})}}function g(a){var b=C[a.clientNick];b&&n(b,!0,!1,'NetPlay client "'+b.nick+'" left')}function h(a){var b=C[a.fromClientNick];b&&(jt.Util.log("Client SDP from client "+b.nick+":",a.clientSDP),b.rtcConnection.setRemoteDescription(new RTCSessionDescription(a.clientSDP)).catch(l))}function i(a,b){jt.Util.log("Client "+a.nick+" dataChannel open"),a.dataChannelActive=!0}function j(a,b){jt.Util.error("NetPlay Client "+a.nick+" dataChannel closed"),n(a,!0,!0,'NetPlay client "'+a.nick+'" dropped: P2P connection lost')}function k(a,b){o(JSON.parse(b.data))}function l(a,b){jt.Util.error("NetPlay Client "+a.nick+" RTC error:",b),n(a,!0,!0,'NetPlay client "'+a.nick+'" dropped: P2P connection error')}function m(){for(var a in C)n(C[a],!1)}function n(b,c,d,e){c&&(a.showOSD(e||'NetPlay client "'+b.nick+'" left',!0,d),(d?jt.Util.error:jt.Util.log)(e||'NetPlay client "'+b.nick+'" left')),b.dataChannel&&(b.dataChannel.onopen=b.dataChannel.onclose=b.dataChannel.onmessage=void 0,b.dataChannel.close()),b.rtcConnection&&(b.rtcConnection.onicecandidate=void 0,b.rtcConnection.close()),delete C[b.nick]}function o(a){a.c&&z.netServerProcessControlsChanges(a.c)}function p(){try{s.send('{ "sessionControl": "keep-alive" }')}catch(a){jt.Util.error("NetPlay error sending keep-alive"),r.stopSession(!0,"NetPlay Session stopped: connection error")}}function q(a,b){var c=b.length;if(c0&&setTimeout(jt.NetClient.sendKeepAlive,Javatari.SERVER_KEEPALIVE)})},jt.Room=function(a,b){"use strict";function c(a){var b=Javatari.AUTO_POWER_ON_DELAY;b>=0&&JavatariFullScreenSetup.shouldStartInFullScreen()&&(b+=1400),b-=Date.now()-i,b<1&&(b=1),setTimeout(a,b)}function d(){b&&(h.console.getCartridgeSocket().inserted()?h.console.userPowerOn():Javatari.CARTRIDGE_SHOW_RECENT&&!Javatari.CARTRIDGE_CHANGE_DISABLED&&h.screen.openCartridgeChooserDialog(!0))}function e(){h.mainVideoClock=new jt.Clock(h.mainVideoClockPulse)}function f(){h.peripheralControls=new jt.DOMPeripheralControls(h),h.consoleControls=new jt.DOMConsoleControls(h,h.peripheralControls),h.fileDownloader=new jt.FileDownloader,h.stateMedia=new jt.LocalStorageSaveStateMedia(h),h.recentROMs=new jt.RecentStoredROMs,h.fileLoader=new jt.FileLoader(h,h.recentROMs,h.peripheralControls),h.speaker=new jt.WebAudioSpeaker(a),h.screen=new jt.CanvasDisplay(h,a),h.fileDownloader.connectPeripherals(h.screen),h.screen.connectPeripherals(h.recentROMs,h.fileLoader,h.fileDownloader,h.consoleControls,h.peripheralControls,h.stateMedia),h.speaker.connectPeripherals(h.screen),h.consoleControls.connectPeripherals(h.screen),h.stateMedia.connectPeripherals(h.fileDownloader),h.peripheralControls.connectPeripherals(h.screen,h.speaker,h.consoleControls,h.fileLoader)}function g(){h.console=new jt.AtariConsole,h.mainVideoClock.connect(h.console.getVideoClockSocket()),h.stateMedia.connect(h.console.getSavestateSocket()),h.fileLoader.connect(h.console),h.screen.connect(h.console),h.speaker.connect(h.console.getAudioSocket()),h.consoleControls.connect(h.console.getConsoleControlsSocket()),h.peripheralControls.connect(h.console.getCartridgeSocket()),h.console.socketsConnected()}var h=this;this.powerOn=function(){h.screen.powerOn(),h.speaker.powerOn(),h.consoleControls.powerOn(),h.setLoading(!0),h.enterStandaloneMode(),i=Date.now()},this.powerOff=function(){h.console.powerOff(),h.consoleControls.powerOff(),h.speaker.powerOff(),h.screen.powerOff()},this.getNetServer=function(){return this.netServer||(this.netServer=new jt.NetServer(this)),this.netServer},this.getNetClient=function(){return this.netClient||(this.netClient=new jt.NetClient(this)),this.netClient},this.setLoading=function(a){this.isLoading!==a&&(this.isLoading=a,this.console.setLoading(this.isLoading),this.screen.setLoading(this.isLoading))},this.start=function(a){this.mainVideoClock.detectHostNativeFPSAndCallback(function(b){h.console.vSynchSetSupported(b>0),c(function(){h.setLoading(!1),h.screen.start(a||d)})})},this.showOSD=function(a,b,c){this.console.showOSD(a,b,c)},this.mainVideoClockPulse=function(){h.console.isSystemPaused()||(h.netController?h.netController.netVideoClockPulse():(h.console.getConsoleControlsSocket().controlsClockPulse(),h.console.videoClockPulse()))},this.enterStandaloneMode=function(){var a=this.netPlayMode;this.netPlayMode=0,this.netController=void 0,h.mainVideoClock.go(),this.netPlayStateBeforeClientMode&&(this.console.loadState(this.netPlayStateBeforeClientMode),this.consoleControls.setP1ControlsAndPaddleMode(this.netPlayControlsModeBeforeClientMode.p1,this.netPlayControlsModeBeforeClientMode.pd),this.netPlayStateBeforeClientMode=void 0),a!==this.netPlayMode&&this.screen.roomNetPlayStatusChangeUpdate(a)},this.enterNetServerMode=function(a){var b=this.netPlayMode;this.netPlayMode=1,this.netController=a,h.mainVideoClock.go(),b!==this.netPlayMode&&this.screen.roomNetPlayStatusChangeUpdate(b)},this.enterNetClientMode=function(a){var b=this.netPlayMode;this.netPlayMode=2,this.netController=a,h.mainVideoClock.pause(),this.netPlayStateBeforeClientMode=this.console.saveState(!0),this.netPlayControlsModeBeforeClientMode={p1:this.consoleControls.isP1ControlsMode(),pd:this.consoleControls.isPaddleMode()},b!==this.netPlayMode&&this.screen.roomNetPlayStatusChangeUpdate(b)},this.enterNetPendingMode=function(a){var b=this.netPlayMode;this.netPlayMode=a===this.netServer?-1:-2,this.netController=void 0,h.mainVideoClock.go(),b!==this.netPlayMode&&this.screen.roomNetPlayStatusChangeUpdate(b)},this.mainVideoClock=null,this.console=null,this.screen=null,this.speaker=null,this.consoleControls=null,this.fileDownloader=null,this.stateMedia=null,this.recentROMs=null,this.fileLoader=null,this.peripheralControls=null,this.netPlayMode=0,this.netController=void 0,this.netServer=void 0,this.netClient=void 0,this.netPlayStateBeforeClientMode=void 0,this.netPlayControlsModeBeforeClientMode=void 0,this.isLoading=!1;var i;this.runFramesAtTopSpeed=function(a){this.mainVideoClock.pause();for(var b=jt.Util.performanceNow(),c=0;c=0),Javatari.room=new jt.Room(Javatari.screenElement,a),Javatari.room.powerOn(),jt.Util.log("version "+Javatari.VERSION+" started"),jt.CartridgeDatabase.uncompress(),jt.NetClient.initKeepAlive();var b=Javatari.NETPLAY_JOIN;if(!b&&Javatari.STATE_URL)new jt.MultiDownloader([{url:Javatari.STATE_URL}],function(a){Javatari.room.start(function(){Javatari.room.fileLoader.loadFromContent(a[0].url,a[0].content,jt.FileLoader.OPEN_TYPE.STATE,0,!1)})}).start();else{var c=b?[]:jt.Configurator.mediaURLSpecs();new jt.MultiDownloader(c,function(){Javatari.room.start(b?function(){Javatari.room.getNetClient().joinSession(b,Javatari.NETPLAY_NICK)}:void 0)}).start()}Javatari.shutdown=function(){Javatari.room&&Javatari.room.powerOff(),jt.Util.log("shutdown")}},Javatari.preLoadImagesAndStart=function(){function a(a){Javatari.start&&Javatari.AUTO_START&&(a||b&&0===c)&&Javatari.start()}var b=!1,c=jt.Images.embedded?0:jt.Images.count;if(document.addEventListener("DOMContentLoaded",function(){b=!0,a(!1)}),c>0)for(var d in jt.Images.urls){var e=new Image;e.src=jt.Images.urls[d],e.onload=function(){c--,a(!1)}}window.addEventListener("load",function(){a(!0)})},window.applicationCache&&(window.applicationCache.status===window.applicationCache.UPDATEREADY?onUpdateReady():window.applicationCache.addEventListener("updateready",onUpdateReady)),Javatari.VERSION="5.0.4",Javatari.preLoadImagesAndStart(); ================================================ FILE: release/stable/5.0/standalone/cache.manifest ================================================ CACHE MANIFEST # Version 5.0.4 # Stable CACHE: manifest.webapp images/logo-icon192.png images/logo-icon512.png NETWORK: * ================================================ FILE: release/stable/5.0/standalone/index.html ================================================ Javatari
The online Atari 2600 emulator
Select Cartridge slot to load ROMs
Drag & Drop or Select Cartridge slot to load ROMs
================================================ FILE: release/stable/5.0/standalone/manifest.webapp ================================================ { "name": "Javatari", "description": "Javatari - The online Atari 2600 emulator", "display": "standalone", "background_color": "#000", "theme_color": "#363636", "icons": [{ "src": "images/logo-icon192.png", "sizes": "192x192", "type": "image/png" }, { "src": "images/logo-icon512.png", "sizes": "512x512", "type": "image/png" }] } ================================================ FILE: release/stable/old/index.html ================================================ Javatari.js
================================================ FILE: release/stable/old/javatari/javatari.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Main Emulator parameters. // You may change any of these after loading the project and before starting the Emulator Javatari = { VERSION: "version 0.92", // Don't change this one! ROM_AUTO_LOAD_URL: "", // Full or relative URL of ROM AUTO_START: true, // Set false to start emulator manually with Javatari.start() SCREEN_ELEMENT_ID: "javatari-screen", CONSOLE_PANEL_ELEMENT_ID: "javatari-console-panel", CARTRIDGE_CHANGE_DISABLED: false, SCREEN_RESIZE_DISABLED: false, SCREEN_FULLSCREEN_DISABLED: false, CARTRIDGE_LABEL_COLORS: "", // Space-separated colors for Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults PADDLES_MODE: -1, // -1 = auto, 0 = off, 1 = 0n SCREEN_OPENING_SIZE: 2, // 1 .. 4 SCREEN_CONTROL_BAR: 0, // 0 = Always, 1 = Hover, 2 = Original Javatari SCREEN_NATURAL_FPS: 60, // 60, 50 fps AUDIO_BUFFER_SIZE: 1024, // 256, 512, 1024, 2048, 4096, 8192. More buffer = more delay IMAGES_PATH: window.Javatari_IMAGES_PATH || "javatari/" }; jt = window.jt || {}; jt.Util=new function(){this.log=function(a){console.log(">> Javatari: "+a)},this.message=function(a){alert(a)},this.arraysEqual=function(a,b){var c=a.length;if(c!==b.length)return!1;for(;c--;)if(a[c]!==b[c])return!1;return!0},this.arrayFill=function(a,b){for(var c=a.length;c--;)a[c]=b;return a},this.arrayFillWithArrayClone=function(a,b){for(var c=a.length;c--;)a[c]=b.slice(0);return a},this.arrayFillSegment=function(a,b,c,d){for(var e=c;e-- >b;)a[e]=d;return a},this.arrayCopy=function(a,b,c,d,e){for(var f=b+e;b>8&255,c[d++]=g>>16&255,c[d++]=g>>>24}},this.arrayCopyCircularSourceWithStep=function(a,b,c,d,e,f,g){for(var h=b,i=f,j=f+g;i=c&&(h-=c)},this.arrayRemove=function(a,b){var c=a.indexOf(b);c<0||a.splice(c,1)},this.booleanArrayToByteString=function(a){for(var b="",c=0,d=a.length;c>>24),b+=String.fromCharCode((16711680&e)>>>16),b+=String.fromCharCode((65280&e)>>>8),b+=String.fromCharCode(255&e)}return b},this.byteStringToUInt32Array=function(a){for(var b=[],c=0,d=a.length;c127),Ba=Ba<<1&255,zb(Ba),Ab(Ba)})}function b(){return Jb(function(){Ja=0})}function c(){return Jb(function(){Ga=0})}function d(){return Jb(function(){Ha=0})}function e(){return Jb(function(){Fa=0})}function f(){return Jb(function(){Ca=Ca-1&255,zb(Ca),Ab(Ca)})}function g(){return Jb(function(){Da=Da-1&255,zb(Da),Ab(Da)})}function h(){return Jb(function(){Ca=Ca+1&255,zb(Ca),Ab(Ca)})}function i(){return Jb(function(){Da=Da+1&255,zb(Da),Ab(Da)})}function j(){return Jb(function(){Ja=1&Ba,Ba>>>=1,zb(Ba),Ea=0})}function k(){return Jb(function(){})}function l(){return Jb(function(){var a=Ba>127;Ba=255&(Ba<<1|Ja),Cb(a),zb(Ba),Ab(Ba)})}function m(){return Jb(function(){var a=1&Ba;Ba=Ba>>>1|Ja<<7,Cb(a),zb(Ba),Ab(Ba)})}function n(){return Jb(function(){Ja=1})}function o(){return Jb(function(){Ga=1})}function p(){return Jb(function(){Ha=1})}function q(){return Jb(function(){Ca=Ba,zb(Ca),Ab(Ca)})}function r(){return Jb(function(){Da=Ba,zb(Da),Ab(Da)})}function s(){return Jb(function(){Ca=Aa,zb(Ca),Ab(Ca)})}function t(){return Jb(function(){Ba=Ca,zb(Ba),Ab(Ba)})}function u(){return Jb(function(){Aa=Ca})}function v(){return Jb(function(){Ba=Da,zb(Ba),Ab(Ba)})}function w(){return[_a,function(){Ib("KIL/HLT/JAM")},function(){Ka--}]}function x(a){return a(function(){Ib("NOP/DOP")})}function y(a){return a(function(){if(Ga){var a=Ma,b=(15&Ba)+(15&a)+Ja;b>9&&(b+=6);var c=(Ba>>4)+(a>>4)+(b>15)<<4;zb(Ba+a+Ja&255),Ab(c),Bb((Ba^c)&~(Ba^a)&128),c>159&&(c+=96),Cb(c>255),Ba=255&(c|15&b)}else{var d=Ba+Ma+Ja;Cb(d>255),Bb((Ba^d)&(Ma^d)&128),Ba=255&d,zb(Ba),Ab(Ba)}})}function z(a){return a(function(){Ba&=Ma,zb(Ba),Ab(Ba)})}function A(a){return a(function(){var a=Ma;zb(Ba&a),Bb(64&a),Ab(a)})}function B(a){return a(function(){var a=Ba-Ma&255;Cb(Ba>=Ma),zb(a),Ab(a)})}function C(a){return a(function(){var a=Ca-Ma&255;Cb(Ca>=Ma),zb(a),Ab(a)})}function D(a){return a(function(){var a=Da-Ma&255;Cb(Da>=Ma),zb(a),Ab(a)})}function E(a){return a(function(){Ba^=Ma,zb(Ba),Ab(Ba)})}function F(a){return a(function(){Ba=Ma,zb(Ba),Ab(Ba)})}function G(a){return a(function(){Ca=Ma,zb(Ca),Ab(Ca)})}function H(a){return a(function(){Da=Ma,zb(Da),Ab(Da)})}function I(a){return a(function(){Ba|=Ma,zb(Ba),Ab(Ba)})}function J(a){return a(function(){if(Ga){var a=Ma,b=(15&Ba)-(15&a)-(1-Ja),c=(Ba>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=Ba-a-(1-Ja);Cb(256&~d),Bb((Ba^a)&(Ba^d)&128),zb(255&d),Ab(d),Ba=255&(c<<4|15&b)}else a=255&~Ma,d=Ba+a+Ja,Cb(d>255),Bb((Ba^d)&(a^d)&128),Ba=255&d,zb(Ba),Ab(Ba)})}function K(a){return a(function(){Ib("ANC"),Ba&=Ma,zb(Ba),Ea=Ja=128&Ba?1:0})}function L(a){return a(function(){Ib("ANE")})}function M(a){return a(function(){Ib("ARR");var a=Ba&Ma,b=Ja?128:0;a=a>>>1|b,Ba=a,zb(a),Ab(a);var c=96&Ba;96==c?(Ja=1,Fa=0):0==c?(Ja=0,Fa=0):32==c?(Ja=0,Fa=1):64==c&&(Ja=1,Fa=1)})}function N(a){return a(function(){Ib("ASR");var a=Ba&Ma;Ja=1&a,a>>>=1,Ba=a,zb(a),Ea=0})}function O(a){return a(function(){Ib("LAS");var a=Aa&Ma;Ba=a,Ca=a,Aa=a,zb(a),Ab(a)})}function P(a){return a(function(){Ib("LAX");var a=Ma;Ba=a,Ca=a,zb(a),Ab(a)})}function Q(a){return a(function(){Ib("LXA");var a=Ba&Ma;Ba=a,Ca=a,zb(a),Ab(a)})}function R(a){return a(function(){Ib("SBX");var a=Ba&Ca,b=Ma,c=a-b&255;Ca=c,Cb(a>=b),zb(c),Ab(c)})}function S(a){return a(function(){Ma=Ba})}function T(a){return a(function(){Ma=Ca})}function U(a){return a(function(){Ma=Da})}function V(a){return a(function(){Ib("SAX"),Ma=Ba&Ca})}function W(a){return a(function(){Ib("SHA"),Ma=Ba&Ca&(Oa>>>8)+1&255})}function X(a){return a(function(){Ib("SHS");var a=Ba&Ca;Aa=a,Ma=a&(Oa>>>8)+1&255})}function Y(a){return a(function(){Ib("SHX"),Ma=Ca&(Oa>>>8)+1&255})}function Z(a){return a(function(){Ib("SHY"),Ma=Da&(Oa>>>8)+1&255})}function $(a){return a(function(){Cb(Ma>127);var a=Ma<<1&255;Ma=a,zb(a),Ab(a)})}function _(a){return a(function(){var a=Ma-1&255;Ma=a,zb(a),Ab(a)})}function aa(a){return a(function(){var a=Ma+1&255;Ma=a,zb(a),Ab(a)})}function ba(a){return a(function(){Ja=1&Ma,Ma>>>=1,zb(Ma),Ea=0})}function ca(a){return a(function(){var a=Ma>127,b=255&(Ma<<1|Ja);Ma=b,Cb(a),zb(b),Ab(b)})}function da(a){return a(function(){var a=1&Ma,b=Ma>>>1|Ja<<7;Ma=b,Cb(a),zb(b),Ab(b)})}function ea(a){return a(function(){Ib("DCP");var a=Ma-1&255;Ma=a,a=Ba-a,Cb(a>=0),zb(a),Ab(a)})}function fa(a){return a(function(){if(Ib("ISB"),Ma=Ma+1&255,Ga){var a=Ma,b=(15&Ba)-(15&a)-(1-Ja),c=(Ba>>4)-(a>>4)-(b<0);b<0&&(b-=6),c<0&&(c-=6);var d=Ba-a-(1-Ja);Cb(256&~d),Bb((Ba^a)&(Ba^d)&128),zb(255&d),Ab(d),Ba=255&(c<<4|15&b)}else a=255&~Ma,d=Ba+a+Ja,Cb(d>255),Bb((Ba^d)&(a^d)&128),Ba=255&d,zb(Ba),Ab(Ba)})}function ga(a){return a(function(){Ib("RLA");var a=Ma,b=Ja;Cb(128&a),a=255&(a<<1|b),Ma=a,Ba&=a,zb(a),Ab(a)})}function ha(a){return a(function(){Ib("RRA");var a=Ma,b=Ja?128:0;if(Cb(1&a),a=a>>>1|b,Ma=a,Ga){var c=Ma,d=(15&Ba)+(15&c)+Ja;d>9&&(d+=6);var e=(Ba>>4)+(c>>4)+(d>15)<<4;zb(Ba+c+Ja&255),Ab(e),Bb((Ba^e)&~(Ba^c)&128),e>159&&(e+=96),Cb(e>255),Ba=255&(e|15&d)}else{var f=Ba+Ma+Ja;Cb(f>255),Bb((Ba^f)&(Ma^f)&128),Ba=255&f,zb(Ba),Ab(Ba)}})}function ia(a){return a(function(){Ib("SLO");var a=Ma;Cb(128&a),a=a<<1&255,Ma=a,a|=Ba,Ba=a,zb(a),Ab(a)})}function ja(a){return a(function(){Ib("SRE");var a=Ma;Cb(1&a),a>>>=1,Ma=a,a=255&(Ba^a),Ba=a,zb(a),Ab(a)})}function ka(){return[_a,bb,function(){Fb(Ba)},ab]}function la(){return[_a,bb,function(){Fb(Gb())},ab]}function ma(){return[_a,bb,Eb,function(){Ba=Db(),zb(Ba),Ab(Ba)},ab]}function na(){return[_a,bb,Eb,function(){Hb(Db())},ab]}function oa(){return[_a,db,Eb,function(){Fb(za>>>8&255)},function(){Fb(255&za)},eb,function(){za=Na,ab()}]}function pa(){return[_a,sb,function(){va.debug&&va.breakpoint("BRK "+Ma),Fb(za>>>8&255)},function(){Fb(255&za)},function(){Fb(Gb())},function(){Na=wa.read(Ua)},function(){Na|=wa.read(Ua+1)<<8},function(){za=Na,ab()}]}function qa(){ return[_a,bb,Eb,function(){Hb(Db())},function(){Na=Db()},function(){Na|=Db()<<8},function(){za=Na,ab()}]}function ra(){return[_a,bb,Eb,function(){Na=Db()},function(){Na|=Db()<<8},function(){za=Na,sb()},ab]}function sa(){return[_a,db,eb,function(){za=Na,ab()}]}function ta(){return[_a,pb,qb,jb,function(){rb(),kb()},function(){za=Oa,ab()}]}function ua(a,b){var c;return c=a===Za?function(){return Ia===b}:a===Xa?function(){return Ea===b}:a===$a?function(){return Ja===b}:function(){return Fa===b},[_a,cb,function(){c()?(bb(),xb()):ab()},function(){Sa?(bb(),yb()):ab()},ab]}var va=this;this.powerOn=function(){this.reset()},this.powerOff=function(){},this.clockPulse=function(){ya&&(Ka++,xa[Ka]())},this.connectBus=function(a){wa=a},this.setRDY=function(a){ya=a},this.reset=function(){Ha=1,Ka=-1,xa=[_a],za=wa.read(Ta)|wa.read(Ta+1)<<8,this.setRDY(!0)};var wa,xa,ya=!1,za=0,Aa=0,Ba=0,Ca=0,Da=0,Ea=0,Fa=0,Ga=0,Ha=0,Ia=0,Ja=0,Ka=-1,La=-1,Ma=0,Na=0,Oa=0,Pa=!1,Qa=0,Ra=0,Sa=0,Ta=65532,Ua=65534,Va=0,Wa=1,Xa=7,Ya=6,Za=1,$a=0;this.debug=!1,this.trace=!1;var _a=function(){La=wa.read(za),xa=cc[La],Ka=0,za++},ab=_a,bb=function(){wa.read(za)},cb=function(){Ra=wa.read(za),za++},db=function(){Na=wa.read(za),za++},eb=function(){Na|=wa.read(za)<<8,za++},fb=function(){Na=wa.read(Oa)},gb=function(){Na|=wa.read(Oa)<<8},hb=function(){Oa=wa.read(za),za++},ib=function(){Oa|=wa.read(za)<<8,za++},jb=function(){Oa=wa.read(Qa)},kb=function(){Oa|=wa.read(Qa)<<8},lb=function(){var a=(255&Oa)+Ca;Pa=a>255,Oa=65280&Oa|255&a},mb=function(){var a=(255&Oa)+Da;Pa=a>255,Oa=65280&Oa|255&a},nb=function(){var a=(255&Oa)+1;Pa=a>255,Oa=65280&Oa|255&a},ob=function(){Pa&&(Oa=Oa+256&65535)},pb=function(){Qa=wa.read(za),za++},qb=function(){Qa|=wa.read(za)<<8,za++},rb=function(){var a=(255&Qa)+1;Qa=65280&Qa|255&a},sb=function(){Ma=wa.read(za),za++},tb=function(){Ma=wa.read(Na)},ub=function(){Ma=wa.read(Oa)},vb=function(){wa.write(Na,Ma)},wb=function(){wa.write(Oa,Ma)},xb=function(){var a=255&za,b=a+Ra&255;Sa=Ra>127?b>a?-256:0:b>>7,Fa=a>>>6&1,Ga=a>>>3&1,Ha=a>>>2&1,Ia=a>>>1&1,Ja=1&a},Ib=function(a){va.debug&&va.breakpoint("Illegal Opcode: "+a)},Jb=function(a){return[_a,bb,function(){a(),ab()}]},Kb=function(a){return[_a,sb,function(){a(),ab()}]},Lb=function(a){return[_a,db,tb,function(){a(),ab()}]},Mb=function(a){return[_a,db,eb,tb,function(){a(),ab()}]},Nb=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},tb,function(){a(),ab()}]},Ob=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},function(){Pa?ub():(a(),ab())},function(){a(),ab()}]}},Pb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),ub()},function(){a(),ab()}]}},Qb=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},function(){Pa?ub():(a(),ab())},function(){a(),ab()}]},Rb=function(a){return[_a,db,function(){a(),vb()},ab]},Sb=function(a){return[_a,db,eb,function(){a(),vb()},ab]},Tb=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},function(){a(),vb()},ab]},Ub=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},function(){a(),wb()},ab]}},Vb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),a(),wb()},ab]}},Wb=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},function(){a(),wb()},ab]},Xb=function(a){return[_a,db,tb,vb,function(){a(),vb()},ab]},Yb=function(a){return[_a,db,eb,tb,vb,function(){a(),vb()},ab]},Zb=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ub,function(){b(),ub()},wb,function(){a(),wb()},ab]}},$b=function(a){var b=a===Va?lb:mb;return function(a){return[_a,hb,ib,function(){b(),ub(),ob()},ub,wb,function(){a(),wb()},ab]}},_b=function(a){return[_a,hb,ub,function(){lb(),fb()},function(){nb(),gb()},tb,vb,function(){a(),vb()},ab]},ac=function(a){return[_a,pb,jb,function(){rb(),kb()},function(){mb(),ub(),ob()},ub,wb,function(){a(),wb()},ab]},bc=new Array(256),cc=new Array(256);bc[0]="BRK",cc[0]=pa(),bc[1]="ORA",cc[1]=I(Nb),bc[2]="uKIL",cc[2]=w(),bc[3]="uSLO",cc[3]=ia(_b),bc[4]="uNOP",cc[4]=x(Lb),bc[5]="ORA",cc[5]=I(Lb),bc[6]="ASL",cc[6]=$(Xb),bc[7]="uSLO",cc[7]=ia(Xb),bc[8]="PHP",cc[8]=la(),bc[9]="ORA",cc[9]=I(Kb),bc[10]="ASL",cc[10]=a(),bc[11]="uANC",cc[11]=K(Kb),bc[12]="uNOP",cc[12]=x(Mb),bc[13]="ORA",cc[13]=I(Mb),bc[14]="ASL",cc[14]=$(Yb),bc[15]="uSLO",cc[15]=ia(Yb),bc[16]="BPL",cc[16]=ua(Xa,0),bc[17]="ORA",cc[17]=I(Qb),bc[18]="uKIL",cc[18]=w(),bc[19]="uSLO",cc[19]=ia(ac),bc[20]="uNOP",cc[20]=x(Pb(Va)),bc[21]="ORA",cc[21]=I(Pb(Va)),bc[22]="ASL",cc[22]=$(Zb(Va)),bc[23]="uSLO",cc[23]=ia(Zb(Va)),bc[24]="CLC",cc[24]=b(),bc[25]="ORA",cc[25]=I(Ob(Wa)),bc[26]="uNOP",cc[26]=x(Jb),bc[27]="uSLO",cc[27]=ia($b(Wa)),bc[28]="uNOP",cc[28]=x(Ob(Va)),bc[29]="ORA",cc[29]=I(Ob(Va)),bc[30]="ASL",cc[30]=$($b(Va)),bc[31]="uSLO",cc[31]=ia($b(Va)),bc[32]="JSR",cc[32]=oa(),bc[33]="AND",cc[33]=z(Nb),bc[34]="uKIL",cc[34]=w(),bc[35]="uRLA",cc[35]=ga(_b),bc[36]="BIT",cc[36]=A(Lb),bc[37]="AND",cc[37]=z(Lb),bc[38]="ROL",cc[38]=ca(Xb),bc[39]="uRLA",cc[39]=ga(Xb),bc[40]="PLP",cc[40]=na(),bc[41]="AND",cc[41]=z(Kb),bc[42]="ROL",cc[42]=l(),bc[43]="uANC",cc[43]=K(Kb),bc[44]="BIT",cc[44]=A(Mb),bc[45]="AND",cc[45]=z(Mb),bc[46]="ROL",cc[46]=ca(Yb),bc[47]="uRLA",cc[47]=ga(Yb),bc[48]="BMI",cc[48]=ua(Xa,1),bc[49]="AND",cc[49]=z(Qb),bc[50]="uKIL",cc[50]=w(),bc[51]="uRLA",cc[51]=ga(ac),bc[52]="uNOP",cc[52]=x(Pb(Va)),bc[53]="AND",cc[53]=z(Pb(Va)),bc[54]="ROL",cc[54]=ca(Zb(Va)),bc[55]="uRLA",cc[55]=ga(Zb(Va)),bc[56]="SEC",cc[56]=n(),bc[57]="AND",cc[57]=z(Ob(Wa)),bc[58]="uNOP",cc[58]=x(Jb),bc[59]="uRLA",cc[59]=ga($b(Wa)),bc[60]="uNOP",cc[60]=x(Ob(Va)),bc[61]="AND",cc[61]=z(Ob(Va)),bc[62]="ROL",cc[62]=ca($b(Va)),bc[63]="uRLA",cc[63]=ga($b(Va)),bc[64]="RTI",cc[64]=qa(),bc[65]="EOR",cc[65]=E(Nb),bc[66]="uKIL",cc[66]=w(),bc[67]="uSRE",cc[67]=ja(_b),bc[68]="uNOP",cc[68]=x(Lb),bc[69]="EOR",cc[69]=E(Lb),bc[70]="LSR",cc[70]=ba(Xb),bc[71]="uSRE",cc[71]=ja(Xb),bc[72]="PHA",cc[72]=ka(),bc[73]="EOR",cc[73]=E(Kb),bc[74]="LSR",cc[74]=j(),bc[75]="uASR",cc[75]=N(Kb),bc[76]="JMP",cc[76]=sa(),bc[77]="EOR",cc[77]=E(Mb),bc[78]="LSR",cc[78]=ba(Yb),bc[79]="uSRE",cc[79]=ja(Yb),bc[80]="BVC",cc[80]=ua(Ya,0),bc[81]="EOR",cc[81]=E(Qb),bc[82]="uKIL",cc[82]=w(),bc[83]="uSRE",cc[83]=ja(ac),bc[84]="uNOP",cc[84]=x(Pb(Va)),bc[85]="EOR",cc[85]=E(Pb(Va)),bc[86]="LSR",cc[86]=ba(Zb(Va)),bc[87]="uSRE",cc[87]=ja(Zb(Va)),bc[88]="CLI",cc[88]=d(),bc[89]="EOR",cc[89]=E(Ob(Wa)),bc[90]="uNOP",cc[90]=x(Jb),bc[91]="uSRE",cc[91]=ja($b(Wa)),bc[92]="uNOP",cc[92]=x(Ob(Va)),bc[93]="EOR",cc[93]=E(Ob(Va)),bc[94]="LSR",cc[94]=ba($b(Va)),bc[95]="uSRE",cc[95]=ja($b(Va)),bc[96]="RTS",cc[96]=ra(),bc[97]="ADC",cc[97]=y(Nb),bc[98]="uKIL",cc[98]=w(),bc[99]="uRRA",cc[99]=ha(_b);bc[100]="uNOP";cc[100]=x(Lb),bc[101]="ADC",cc[101]=y(Lb),bc[102]="ROR",cc[102]=da(Xb),bc[103]="uRRA",cc[103]=ha(Xb),bc[104]="PLA",cc[104]=ma(),bc[105]="ADC",cc[105]=y(Kb),bc[106]="ROR",cc[106]=m(),bc[107]="uARR",cc[107]=M(Kb),bc[108]="JMP",cc[108]=ta(),bc[109]="ADC",cc[109]=y(Mb),bc[110]="ROR",cc[110]=da(Yb),bc[111]="uRRA",cc[111]=ha(Yb),bc[112]="BVS",cc[112]=ua(Ya,1),bc[113]="ADC",cc[113]=y(Qb),bc[114]="uKIL",cc[114]=w(),bc[115]="uRRA",cc[115]=ha(ac),bc[116]="uNOP",cc[116]=x(Pb(Va)),bc[117]="ADC",cc[117]=y(Pb(Va)),bc[118]="ROR",cc[118]=da(Zb(Va)),bc[119]="uRRA",cc[119]=ha(Zb(Va)),bc[120]="SEI",cc[120]=p(),bc[121]="ADC",cc[121]=y(Ob(Wa)),bc[122]="uNOP",cc[122]=x(Jb),bc[123]="uRRA",cc[123]=ha($b(Wa)),bc[124]="uNOP",cc[124]=x(Ob(Va)),bc[125]="ADC",cc[125]=y(Ob(Va)),bc[126]="ROR", cc[126]=da($b(Va)),bc[127]="uRRA",cc[127]=ha($b(Va)),bc[128]="uNOP",cc[128]=x(Kb),bc[129]="STA",cc[129]=S(Tb),bc[130]="uNOP",cc[130]=x(Kb),bc[131]="uSAX",cc[131]=V(Tb),bc[132]="STY",cc[132]=U(Rb),bc[133]="STA",cc[133]=S(Rb),bc[134]="STX",cc[134]=T(Rb),bc[135]="uSAX",cc[135]=V(Rb),bc[136]="DEY",cc[136]=g(),bc[137]="uNOP",cc[137]=x(Kb),bc[138]="TXA",cc[138]=t(),bc[139]="uANE",cc[139]=L(Kb),bc[140]="STY",cc[140]=U(Sb),bc[141]="STA",cc[141]=S(Sb),bc[142]="STX",cc[142]=T(Sb),bc[143]="uSAX",cc[143]=V(Sb),bc[144]="BCC",cc[144]=ua($a,0),bc[145]="STA",cc[145]=S(Wb),bc[146]="uKIL",cc[146]=w(),bc[147]="uSHA",cc[147]=W(Wb),bc[148]="STY",cc[148]=U(Vb(Va)),bc[149]="STA",cc[149]=S(Vb(Va)),bc[150]="STX",cc[150]=T(Vb(Wa)),bc[151]="uSAX",cc[151]=V(Vb(Wa)),bc[152]="TYA",cc[152]=v(),bc[153]="STA",cc[153]=S(Ub(Wa)),bc[154]="TXS",cc[154]=u(),bc[155]="uSHS",cc[155]=X(Ub(Wa)),bc[156]="uSHY",cc[156]=Z(Ub(Va)),bc[157]="STA",cc[157]=S(Ub(Va)),bc[158]="uSHX",cc[158]=Y(Ub(Wa)),bc[159]="uSHA",cc[159]=W(Ub(Wa)),bc[160]="LDY",cc[160]=H(Kb),bc[161]="LDA",cc[161]=F(Nb),bc[162]="LDX",cc[162]=G(Kb),bc[163]="uLAX",cc[163]=P(Nb),bc[164]="LDY",cc[164]=H(Lb),bc[165]="LDA",cc[165]=F(Lb),bc[166]="LDX",cc[166]=G(Lb),bc[167]="uLAX",cc[167]=P(Lb),bc[168]="TAY",cc[168]=r(),bc[169]="LDA",cc[169]=F(Kb),bc[170]="TAX",cc[170]=q(),bc[171]="uLXA",cc[171]=Q(Kb),bc[172]="LDY",cc[172]=H(Mb),bc[173]="LDA",cc[173]=F(Mb),bc[174]="LDX",cc[174]=G(Mb),bc[175]="uLAX",cc[175]=P(Mb),bc[176]="BCS",cc[176]=ua($a,1),bc[177]="LDA",cc[177]=F(Qb),bc[178]="uKIL",cc[178]=w(),bc[179]="uLAX",cc[179]=P(Qb),bc[180]="LDY",cc[180]=H(Pb(Va)),bc[181]="LDA",cc[181]=F(Pb(Va)),bc[182]="LDX",cc[182]=G(Pb(Wa)),bc[183]="uLAX",cc[183]=P(Pb(Wa)),bc[184]="CLV",cc[184]=e(),bc[185]="LDA",cc[185]=F(Ob(Wa)),bc[186]="TSX",cc[186]=s(),bc[187]="uLAS",cc[187]=O(Ob(Wa)),bc[188]="LDY",cc[188]=H(Ob(Va)),bc[189]="LDA",cc[189]=F(Ob(Va)),bc[190]="LDX",cc[190]=G(Ob(Wa)),bc[191]="uLAX",cc[191]=P(Ob(Wa)),bc[192]="CPY",cc[192]=D(Kb),bc[193]="CMP",cc[193]=B(Nb),bc[194]="uNOP",cc[194]=x(Kb),bc[195]="uDCP",cc[195]=ea(_b),bc[196]="CPY",cc[196]=D(Lb),bc[197]="CMP",cc[197]=B(Lb),bc[198]="DEC",cc[198]=_(Xb),bc[199]="uDCP",cc[199]=ea(Xb),bc[200]="INY";cc[200]=i();bc[201]="CMP",cc[201]=B(Kb),bc[202]="DEX",cc[202]=f(),bc[203]="uSBX",cc[203]=R(Kb),bc[204]="CPY",cc[204]=D(Mb),bc[205]="CMP",cc[205]=B(Mb),bc[206]="DEC",cc[206]=_(Yb),bc[207]="uDCP",cc[207]=ea(Yb),bc[208]="BNE",cc[208]=ua(Za,0),bc[209]="CMP",cc[209]=B(Qb),bc[210]="uKIL",cc[210]=w(),bc[211]="uDCP",cc[211]=ea(ac),bc[212]="uNOP",cc[212]=x(Pb(Va)),bc[213]="CMP",cc[213]=B(Pb(Va)),bc[214]="DEC",cc[214]=_(Zb(Va)),bc[215]="uDCP",cc[215]=ea(Zb(Va)),bc[216]="CLD",cc[216]=c(),bc[217]="CMP",cc[217]=B(Ob(Wa)),bc[218]="uNOP",cc[218]=x(Jb),bc[219]="uDCP",cc[219]=ea($b(Wa)),bc[220]="uNOP",cc[220]=x(Ob(Va)),bc[221]="CMP",cc[221]=B(Ob(Va)),bc[222]="DEC",cc[222]=_($b(Va)),bc[223]="uDCP",cc[223]=ea($b(Va)),bc[224]="CPX",cc[224]=C(Kb),bc[225]="SBC",cc[225]=J(Nb),bc[226]="uNOP",cc[226]=x(Kb),bc[227]="uISB",cc[227]=fa(_b),bc[228]="CPX",cc[228]=C(Lb),bc[229]="SBC",cc[229]=J(Lb),bc[230]="INC",cc[230]=aa(Xb),bc[231]="uISB",cc[231]=fa(Xb),bc[232]="INX",cc[232]=h(),bc[233]="SBC",cc[233]=J(Kb),bc[234]="NOP",cc[234]=k(),bc[235]="SBC",cc[235]=J(Kb),bc[236]="CPX",cc[236]=C(Mb),bc[237]="SBC",cc[237]=J(Mb),bc[238]="INC",cc[238]=aa(Yb),bc[239]="uISB",cc[239]=fa(Yb),bc[240]="BEQ",cc[240]=ua(Za,1),bc[241]="SBC",cc[241]=J(Qb),bc[242]="uKIL",cc[242]=w(),bc[243]="uISB",cc[243]=fa(ac),bc[244]="uNOP",cc[244]=x(Pb(Va)),bc[245]="SBC",cc[245]=J(Pb(Va)),bc[246]="INC",cc[246]=aa(Zb(Va)),bc[247]="uISB",cc[247]=fa(Zb(Va)),bc[248]="SED",cc[248]=o(),bc[249]="SBC",cc[249]=J(Ob(Wa)),bc[250]="uNOP",cc[250]=x(Jb),bc[251]="uISB",cc[251]=fa($b(Wa)),bc[252]="uNOP",cc[252]=x(Ob(Va)),bc[253]="SBC",cc[253]=J(Ob(Va)),bc[254]="INC",cc[254]=aa($b(Va)),bc[255]="uISB",cc[255]=fa($b(Va)),this.saveState=function(){return{PC:za,A:Ba,X:Ca,Y:Da,SP:Aa,N:Ea,V:Fa,D:Ga,I:Ha,Z:Ia,C:Ja,T:Ka,o:La,R:0|ya,d:Ma,AD:Na,BA:Oa,BC:0|Pa,IA:Qa,bo:Ra,boa:Sa}},this.loadState=function(a){za=a.PC,Ba=a.A,Ca=a.X,Da=a.Y,Aa=a.SP,Ea=a.N,Fa=a.V,Ga=a.D,Ha=a.I,Ia=a.Z,Ja=a.C,Ka=a.T,La=a.o,ya=!!a.R,Ma=a.d,Na=a.AD,Oa=a.BA,Pa=!!a.BC,Qa=a.IA,Ra=a.bo,Sa=a.boa,xa=cc[La]},this.toString=function(){return"CPU PC: "+za.toString(16)+" op: "+La.toString()+" T: "+Ka+" data: "+Ma+"\n A: "+Ba.toString(16)+" X: "+Ca.toString(16)+" Y: "+Da.toString(16)+" SP: "+Aa.toString(16)+" N"+Ea+" V"+Fa+" D"+Ga+" I"+Ha+" Z"+Ia+" C"+Ja+" "},this.breakpoint=function(a){if(jt.Util.log(a),this.trace){var b="CPU Breakpoint! "+(a?"("+a+")":"")+"\n\n"+this.toString();jt.Util.message(b)}},this.runCycles=function(a){for(var b=performance.now(),c=0;c=0;a--)b[a]=256*Math.random()|0}this.powerOn=function(){},this.powerOff=function(){},this.read=function(a){return b[a&c]},this.write=function(a,d){b[a&c]=d},this.powerFry=function(){for(var a=1-f+2*Math.random()*f,c=a*d,g=0;g>>> Ineffective Write to PIA SWBCNT: "+c)):0===f?void e(">>>> Unsupported Write to PIA SWCHA: "+c):1===f?void e(">>>> Unsupported Write to PIA SWACNT "+c):0};var a=function(){--o<0?(p|=192,o=255,h=i=1):h=i},b=function(b,c){o=b,p&=63,h=i=j=c,a()},c=function(){p&=191,1===i&&(h=i=j)},d=function(a){m=203&m|34&a},e=function(a){self.debug&&jt.Util.log(a)},f=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case f.JOY0_UP:return void(b?k&=239:k|=16);case f.JOY0_DOWN:return void(b?k&=223:k|=32);case f.PADDLE1_BUTTON:case f.JOY0_LEFT:return void(b?k&=191:k|=64);case f.PADDLE0_BUTTON:case f.JOY0_RIGHT:return void(b?k&=127:k|=128);case f.JOY1_UP:return void(b?k&=254:k|=1);case f.JOY1_DOWN:return void(b?k&=253:k|=2);case f.JOY1_LEFT:return void(b?k&=251:k|=4);case f.JOY1_RIGHT:return void(b?k&=247:k|=8);case f.RESET:return void(b?m&=254:m|=1);case f.SELECT:return void(b?m&=253:m|=2)}if(b)switch(a){case f.BLACK_WHITE:return 0==(8&m)?m|=8:m&=247,void g.getTia().getVideoOutput().showOSD(0!=(8&m)?"COLOR":"B/W",!0);case f.DIFFICULTY0:return 0==(64&m)?m|=64:m&=191,void g.getTia().getVideoOutput().showOSD(0!=(64&m)?"P1 Expert":"P1 Novice",!0);case f.DIFFICULTY1:return 0==(128&m)?m|=128:m&=127,void g.getTia().getVideoOutput().showOSD(0!=(128&m)?"P2 Expert":"P2 Novice",!0)}},this.controlValueChanged=function(a,b){},this.controlsStateReport=function(a){a[f.BLACK_WHITE]=0===(8&m),a[f.DIFFICULTY0]=0!==(64&m),a[f.DIFFICULTY1]=0!==(128&m),a[f.SELECT]=0===(2&m),a[f.RESET]=0===(1&m)},this.saveState=function(){return{t:h,c:i,l:j,SA:k,SAC:l,SB:m,SBC:n,IT:o,IS:p,T1:q,T8:r,T6:s,T2:t}},this.loadState=function(a){h=a.t,i=a.c,j=a.l,l=a.SAC,m=a.SB,n=a.SBC,o=a.IT,p=a.IS,q=a.T1,r=a.T8,s=a.T6,t=a.T2},this.debug=!1;var g,h=1024,i=1024,j=1024,k=255,l=0,m=11,n=0,o=256*Math.random()|0,p=0,q=0,r=0,s=0,t=0,u=7},function(){for(var a=[0,4210752,7105644,9474192,11579568,13158600,14474460,16053492,17476,1074276,2393220,3448992,4241592,5296336,6088936,6880508,10352,1328260,2645144,3963052,5016764,6070476,6862044,7915756,6276,1586328,3166380,4745408,6062288,7378144,8431852,9747708,136,2105500,3947696,5789888,7368912,8947936,10526956,11842812,6029432,7610508,8928416,10246320,11563200,12616912,13671644,14725356,7864392,9445472,10763384,12081292,13398176,14451892,15506628,16560340,8650772,9969712,11287628,12605544,13660284,14715028,15507624,16561340,8912896,10231836,11550776,12606544,13661288,14716028,15508624,16562340,8132608,9451548,11031608,12349520,13404264,14457980,15512720,16566436,6040576,7883804,9463864,11306064,12622952,13939836,15256720,16572580,2898944,4742172,6585400,8428624,9745512,11325564,12641424,13958308,15360,2120736,4226112,6069340,7648372,9228428,10806436,12123320,14356,1858612,3701840,5281900,6861956,8178844,9495732,10812616,12332,1855564,3436648,5016708,6596764,7913652,8967372,10284256,10308,1591396,3172484,4490400,5807288,7124176,8178920,9232636],b=[0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,22656,2125972,3966120,5807292,7384268,8700124,10277100,11591932,23620,2127964,3969140,5811340,7389344,8705200,10283204,11599060,13424,2117768,3958944,5801140,7379144,8695004,10273004,11588860,1336320,3440672,5281852,7123032,8701040,10279044,11856028,13171888,1310832,3416200,5258400,7100596,8679624,10257628,11836652,13152508,6052864,7631904,9210940,10789976,12105840,13158532,14474396,15527088,6029424,7610500,8928404,10246312,11563188,12616900,13671632,14725344,7355392,8935452,10515512,11832400,13149288,14465148,15518864,16572580,7340120,8921196,10501248,11819156,13136036,14451892,15506628,16560340,7348224,8928284,10508344,11826256,13142120,14459004,15512720,16566436,8388668,9707604,11025516,12343424,13398164,14451880,15506616,16560328,8912896,10231840,11549756,12605528,13660272,14713988,15506588,16560304,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113,0,2631720,5263440,7631988,9737364,11842740,13684944,15856113],c=new Array(256),d=new Array(256),e=0,f=a.length;el&&(i=l)},this.finishFrame=function(){var a=i-j;a>0&&c(a),j=0},this.retrieveSamples=function(a){var b=g>=h?a-(g-h):a-(l-h+g);b>0&&c(b,!0);var d=h+a;d>=l&&(d-=l);var e=o;return e.start=h,h=d,e};var a,b,c=function(a,c){for(var h,i=a;i>0;i--)b&&b.audioClockPulse(),d?(h=e.nextSample()-f.nextSample(),h!==k&&(h=(9*h+k)/10,k=h)):h=0,n[g]=h*m,g++,g>=l&&(g=0);c||(j+=a)},d=!1,e=new jt.TiaAudioChannel,f=new jt.TiaAudioChannel,g=0,h=0,i=jt.TiaAudioSignal.SAMPLE_RATE/jt.VideoStandard.NTSC.fps,j=0,k=0,l=10*Javatari.AUDIO_BUFFER_SIZE,m=.4,n=jt.Util.arrayFill(new Array(l),0),o={buffer:n,bufferSize:l,start:0}},jt.TiaAudioSignal.SAMPLE_RATE=31440,jt.TiaAudioChannel=function(){this.nextSample=function(){return--s<=0&&(s+=r,t=o()),1===t?p:0},this.setVolume=function(a){p=a/E},this.setDivider=function(a){r!==a&&(s=s/r*a,r=a)},this.setControl=function(b){q!==b&&(q=b,o=0===b||11===b?a:1===b?c:2===b?k:3===b?l:4===b||5===b?f:6===b||10===b?j:7===b||9===b?d:8===b?e:12===b||13===b?h:14===b?m:15===b?n:a)};var a=function(){return 1},b=function(){return z[y]},c=function(){return 15===++y&&(y=0),z[y]},d=function(){return 31===++A&&(A=0),B[A]},e=function(){var a=1&x,b=1&(x>>4^a);return x>>>=1,0===b?x&=255:x|=256,a},f=function(){return 1===r?1:u=u?0:1},g=function(){return v},h=function(){return 0===--w&&(w=3,v=v?0:1),v},i=function(){return D[C]},j=function(){return 31===++C&&(C=0),D[C]},k=function(){return i()!==j()?c():b()},l=function(){return d()?c():b()},m=function(){return i()!=j()?h():g()},n=function(){return d()?h():g()},o=a,p=0,q=0,r=1,s=1,t=0,u=1,v=1,w=3,x=511,y=14,z=[1,1,1,1,0,0,0,1,0,0,1,1,0,1,0],A=30,B=[1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,1,0,1,1,0,0],C=30,D=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0],E=15},jt.Tia=function(a,b){var c=this;this.powerOn=function(){jt.Util.arrayFill(Ga,ia),jt.Util.arrayFill(Vb,0),lc.getChannel0().setVolume(0),lc.getChannel1().setVolume(0),H(),F(),bc=!0,lc.signalOn(),Fa=!0},this.powerOff=function(){Fa=!1,kc.signalOff(),lc.signalOff()},this.frame=function(){if(!(Wb&&Xb--<=0)){do{for(P=0,O.clockPulse(),Da.setRDY(!0),P=3;P=76)&&Ob||d();lc.audioClockPulse(),e()}while(!kc.nextLine(Ga,Ha));lc.finishFrame(),kc.finishFrame()}},this.connectBus=function(a){O=a},this.getVideoOutput=function(){return kc},this.getAudioOutput=function(){return lc},this.setVideoStandard=function(a){kc.standard=a,R=a===jt.VideoStandard.NTSC?jt.VideoStandard.NTSC.palette:jt.VideoStandard.PAL.palette},this.debug=function(a){Tb=a>4?0:a,Sb=0!==Tb,kc.showOSD(Sb?"Debug Level "+Tb:"Debug OFF",!0),Da.debug=Sb,Ea.debug=Sb,Sb?K():L()},this.read=function(a){var b=a&Ba;return 0===b?mc:1===b?nc:2===b?oc:3===b?pc:4===b?qc:5===b?rc:6===b?sc:7===b?tc:8===b?uc:9===b?vc:10===b?wc:11===b?xc:12===b?yc:13===b?zc:0},this.write=function(a,b){var c=a&Ca;return 27===c?void z(0,b):28===c?void z(1,b):2===c?(Da.setRDY(!1),void(Sb&&I(za))):42===c?void r():13===c?void(S==b&&0!==Ta||g(0,b)):14===c?void(T==b&&1!==Ta||g(1,b)):15===c?void(U==b&&2!==Ta||g(2,b)):6===c?(F(),void(Sb||(Xa=sb=R[b]))):7===c?(F(),void(Sb||(hb=zb=R[b]))):8===c?(F(),void(Sb||(Na=Hb=R[b]))):9===c?(F(),void(Sb||(Oa=R[b]))):29===c?(F(),void(rb=0!==(2&b))):30===c?(F(),void(yb=0!==(2&b))):20===c?void q():16===c?void m():17===c?void n():18===c?void o():19===c?void p():32===c?void(_=b>127?-16+(b>>>4):b>>>4):33===c?void(aa=b>127?-16+(b>>>4):b>>>4):34===c?void(ba=b>127?-16+(b>>>4):b>>>4):35===c?void(ca=b>127?-16+(b>>>4):b>>>4):36===c?void(da=b>127?-16+(b>>>4):b>>>4):43===c?void(_=aa=ba=ca=da=0):31===c?void i(b):4===c?void j(b):5===c?void k(b):10===c?void l(b):11===c?(F(),void(eb=0!==(8&b))):12===c?(F(),void(qb=0!==(8&b))):37===c?(F(),void(ab=0!==(1&b))):38===c?(F(),void(mb=0!==(1&b))):39===c?(F(),void(Lb=0!==(1&b))):21===c?(V=b,void lc.getChannel0().setControl(15&b)):22===c?(W=b,void lc.getChannel1().setControl(15&b)):23===c?(X=b,void lc.getChannel0().setDivider((31&b)+1)):24===c?(Y=b,void lc.getChannel1().setDivider((31&b)+1)):25===c?(Z=b,void lc.getChannel0().setVolume(15&b)):26===c?($=b,void lc.getChannel1().setVolume(15&b)):40===c?void B(b):41===c?void C(b):1===c?void D(b):0===c?(F(),Ha=0!==(2&b),void(Sb&&I(ja))):44===c?(F(),void(mc=nc=oc=pc=qc=rc=sc=tc=0)):0};var d=function(){if(Ha)return void(Ga[P]=Yb);if(Ia)return void(Ga[P]=Zb);var a=!1,b=!1,c=!1,d=!1,e=!1,g=!1;0!==(3&P)&&P!==ac||f();var h;if(Ra&&(Jb>=0&&Jb<=7&&(A(),Fb&&(g=!0,h=Hb)),Ma&&(e=!0,h||(h=Na))),$a>=0&&$a<=31){A();var i=ab?Va:Wa;0!=i&&0!==(i>>(eb?7-($a>>>2):$a>>>2)&1)&&(a=!0,h||(h=Xa))}vb>=0&&rb&&vb<=7&&!xb&&(c=!0,!h>0&&(h=sb)),kb>=0&&kb<=31&&(A(),i=mb?fb:gb,0!==i&&0!==(i>>(qb?7-(kb>>>2):kb>>>2)&1)&&(b=!0,h||(h=hb))),Cb>=0&&yb&&Cb<=7&&!Eb&&(d=!0,h||(h=zb)),Ra||(Jb>=0&&Jb<=7&&(A(),Fb&&(g=!0,h||(h=Hb))),Ma&&(e=!0,h||(h=Qa?P<148?Xa:hb:Na))),h||(h=Oa),Ga[P]=h,Ub||(a&&e&&(oc|=128),b&&(e&&(pc|=128),a&&(tc|=128)),g&&(e&&(sc|=128),a&&(oc|=64),b&&(pc|=64)),c&&(b&&(mc|=128),a&&(mc|=64),e&&(qc|=128),g&&(qc|=64)),d&&(a&&(nc|=128),b&&(nc|=64),e&&(rc|=128),g&&(rc|=64),c&&(tc|=64)))},e=function(){gc>=0&&!fc&&(uc<128&&++hc>=gc&&(uc|=128),vc<128&&++jc>=ic&&(vc|=128)),Ob&&(Ga[ea]=Ga[ea+1]=Ga[ea+2]=Ga[ea+3]=Ga[ea+4]=Ga[ea+5]=Ga[ea+6]=Ga[ea+7]=$b,Ob=!1),Qb&&(Qb=!1,Ob=Rb,s()),bc&&(ac=227,bc=!1),Tb>=2&&J()},f=function(){if(h(!1),La){if(La=!1,0===S&&0===T&&0===U)return jt.Util.arrayFill(Ka,!1),void(Ma=!1);var a,b;Pa?(a=40,b=-1):(a=19,b=1),Ka[0]=Ka[a+=b]=0!==(16&S),Ka[1]=Ka[a+=b]=0!==(32&S),Ka[2]=Ka[a+=b]=0!==(64&S),Ka[3]=Ka[a+=b]=0!==(128&S),Ka[4]=Ka[a+=b]=0!==(128&T),Ka[5]=Ka[a+=b]=0!==(64&T),Ka[6]=Ka[a+=b]=0!==(32&T),Ka[7]=Ka[a+=b]=0!==(16&T),Ka[8]=Ka[a+=b]=0!==(8&T),Ka[9]=Ka[a+=b]=0!==(4&T),Ka[10]=Ka[a+=b]=0!==(2&T),Ka[11]=Ka[a+=b]=0!==(1&T),Ka[12]=Ka[a+=b]=0!==(1&U),Ka[13]=Ka[a+=b]=0!==(2&U),Ka[14]=Ka[a+=b]=0!==(4&U),Ka[15]=Ka[a+=b]=0!==(8&U),Ka[16]=Ka[a+=b]=0!==(16&U),Ka[17]=Ka[a+=b]=0!==(32&U),Ka[18]=Ka[a+=b]=0!==(64&U),Ka[19]=Ka[a+=b]=0!==(128&U)}Ma=Ka[P-ea>>>2]},g=function(a,b){F(),Sb&&I(ta),h(!0),Sa=P,Ta=a,Ua=b},h=function(a){if(Ta!==-1){if(!a){var b=P-Sa;if(0===b||1===b)return}F(),0===Ta?S=Ua:1===Ta?T=Ua:2===Ta&&(U=Ua),La=!0,Ta=-1}},i=function(a){F(),Gb=0!=(2&a),Lb||(Fb=Gb)},j=function(a){F();var b=48&a;0===b?b=8:16===b?b=4:32===b?b=2:48===b&&(b=1),wb!==b&&(vb>7?vb=7+(vb-7)/wb*b:vb>=0&&(vb=-1),wb=b),5===(7&a)?(b=2,bb=cb=db=!1):7===(7&a)?(b=1,bb=cb=db=!1):(b=4,bb=0!==(1&a),cb=0!==(2&a),db=0!==(4&a)),_a!==b&&($a>31?$a=31+($a-31)/_a*b:$a>=0&&($a=-1),_a=b)},k=function(a){F();var b=48&a;0===b?b=8:16===b?b=4:32===b?b=2:48===b&&(b=1),Db!==b&&(Cb>7?Cb=7+(Cb-7)/Db*b:Cb>=0&&(Cb=-1),Db=b),5===(7&a)?(b=2,nb=ob=pb=!1):7===(7&a)?(b=1,nb=ob=pb=!1):(b=4,nb=0!==(1&a),ob=0!==(2&a),pb=0!==(4&a)),lb!==b&&(kb>31?kb=31+(kb-31)/lb*b:kb>=0&&(kb=-1),lb=b)},l=function(a){F();var b=0!==(1&a);Pa!=b&&(Pa=b,La=!0),Qa=0!==(2&a),Ra=0!==(4&a);var c=48&a;0===c?c=8:16===c?c=4:32===c?c=2:48===c&&(c=1), Kb!==c&&(Jb>7?Jb=7+(Jb-7)/Kb*c:Jb>=0&&(Jb=-1),Kb=c)},m=function(){if(F(),bc=!0,Sb&&I(la),P>=ea+(Ob?7:0))return 155!==Za&&(Ya=!0),void(Za=155);var a=0;Ob&&(P>=ea?a=ea-P+8:(a=P-Pb-4>>2,a>8&&(a=8))),Za=157-a,Ya=Za<=155},n=function(){if(F(),bc=!0,Sb&&I(oa),P>=ea+(Ob?7:0))return 155!==jb&&(ib=!0),void(jb=155);var a=0;Ob&&(P>=ea?a=ea-P+8:(a=P-Pb-4>>2,a>8&&(a=8))),jb=157-a,ib=jb<=155},o=function(){if(F(),bc=!0,Sb&&I(qa),P>=ea+(Ob?7:0))return 155!==ub&&(tb=!0),void(ub=155);var a=0;Ob&&(P>=ea?a=ea-P+8:(a=P-Pb-4>>2,a>8&&(a=8))),ub=157-a,tb=ub<=155},p=function(){if(F(),bc=!0,Sb&&I(ra),P>=ea+(Ob?7:0))return 155!==Bb&&(Ab=!0),void(Bb=155);var a=0;Ob&&(P>=ea?a=ea-P+8:(a=P-Pb-4>>2,a>8&&(a=8))),Bb=157-a,Ab=Bb<=155},q=function(){if(F(),Sb&&I(va),P>=ea+(Ob?7:0))return void(Ib=155);var a=0;Ob&&(P>=ea?a=ea-P+8:(a=P-Pb-4>>2,a>8&&(a=8))),Ib=157-a},r=function(){return Sb&&I(Aa),P=225))},s=function(){var a,b=!1;if(a=Ob?_:_+8,0!==a)if(b=!0,a>0)for(var c=a;c>0;c--)u();else Za+=a,Za<0&&(Za+=160),$a>=0&&($a-=_a*a);if(a=Ob?aa:aa+8,0!==a)if(b=!0,a>0)for(c=a;c>0;c--)v();else jb+=a,jb<0&&(jb+=160),kb>=0&&(kb-=lb*a);if(a=Ob?ba:ba+8,0!==a)if(b=!0,a>0)for(c=a;c>0;c--)w();else ub+=a,ub<0&&(ub+=160),vb>=0&&(vb-=wb*a);if(a=Ob?ca:ca+8,0!=a)if(b=!0,a>0)for(c=a;c>0;c--)x();else Bb+=a,Bb<0&&(Bb+=160),Cb>=0&&(Cb-=Db*a);if(a=Ob?da:da+8,0!=a)if(b=!0,a>0)for(c=a;c>0;c--)y();else Ib+=a,Ib<0&&(Ib+=160),Jb>=0&&(Jb-=Kb*a);b&&F()},t=function(){u(),v(),w(),x(),y()},u=function(){160===++Za&&(Za=0),$a>=0&&(xb&&Za<12&&$a>=28&&$a<=31&&(ub=156),$a-=_a),156===Za?Ya?Ya=!1:$a=31+_a*(4===_a?5:6):12===Za?bb&&($a=31+5*_a):28===Za?cb&&($a=31+5*_a):60===Za&&db&&($a=31+5*_a)},v=function(){160===++jb&&(jb=0),kb>=0&&(Eb&&jb<12&&kb>=28&&kb<=31&&(Bb=156),kb-=lb),156===jb?ib?ib=!1:kb=31+lb*(4===lb?5:6):12===jb?nb&&(kb=31+5*lb):28===jb?ob&&(kb=31+5*lb):60===jb&&pb&&(kb=31+5*lb)},w=function(){160===++ub&&(ub=0),vb>=0&&(vb-=wb),156===ub?tb?tb=!1:vb=7+4*wb:12===ub?bb&&(vb=7+4*wb):28===ub?cb&&(vb=7+4*wb):60===ub&&db&&(vb=7+4*wb)},x=function(){160===++Bb&&(Bb=0),Cb>=0&&(Cb-=Db),156===Bb?Ab?Ab=!1:Cb=7+4*Db:12===Bb?nb&&(Cb=7+4*Db):28===Bb?ob&&(Cb=7+4*Db):60===Bb&&pb&&(Cb=7+4*Db)},y=function(){160===++Ib&&(Ib=0),Jb>=0&&(Jb-=Kb),156===Ib&&(Jb=7+4*Kb)},z=function(a,b){return F(),Sb&&I(0===a?ma:pa),Nb>=ga?void M(">>> Max player delayed changes reached: "+ga):(Mb[Nb][0]=P,Mb[Nb][1]=a,Mb[Nb][2]=b,void Nb++)},A=function(){if(0!==Nb&&Mb[0][0]!==P){for(var a=0;a=4&&kc.monitor.currentLine()%10==0)for(var a=0;a=3)for(a=0;a=1?xa:ia,Zb=Tb>=2?ya:ha},L=function(){$b=ia,Zb=ha,Oa=R[0],jt.Util.arrayFill(Ga,$b),F()},M=function(a){Sb&&jt.Util.log("Line: "+kc.monitor.currentLine()+", Pixel: "+P+". "+a)},N=jt.ConsoleControls;this.controlStateChanged=function(a,b){switch(a){case N.JOY0_BUTTON:return void(b?(dc=!0,yc&=127):(dc=!1,cc||(yc|=128)));case N.JOY1_BUTTON:return void(b?(ec=!0,zc&=127):(ec=!1,cc||(zc|=128)))}if(b)switch(a){case N.DEBUG:return void c.debug(Tb+1);case N.NO_COLLISIONS:return Ub=!Ub,void kc.showOSD(Ub?"Collisions OFF":"Collisions ON",!0);case N.PAUSE:return Wb=!Wb,Xb=1,void kc.showOSD(Wb?"PAUSE":"RESUME",!0);case N.FRAME:return void(Wb&&(Xb=1));case N.TRACE:return void(Da.trace=!Da.trace)}},this.controlValueChanged=function(a,b){switch(a){case N.PADDLE0_POSITION:return void(gc=b);case N.PADDLE1_POSITION:return void(ic=b)}},this.controlsStateReport=function(a){},this.saveState=function(){return{lp:btoa(jt.Util.uInt32ArrayToByteString(Ga)),lo:ac,oc:0|bc,rl:0|_b,vs:0|Ha,vb:0|Ia,vbd:0|Ja,vbn:0|Q,f:jt.Util.booleanArrayToByteString(Ka),fi:0|La,fp:0|Ma,fc:Na,fb:Oa,fr:0|Pa,fs:0|Qa,ft:0|Ra,p0:Va,p0d:Wa,p0c:Xa,p0rr:0|Ya,p0co:Za,p0sc:$a,p0ss:_a,p0v:0|ab,p0cc:0|bb,p0mc:0|cb,p0wc:0|db,p0r:0|eb,p1:fb,p1d:gb,p1c:hb,p1rr:0|ib,p1co:jb,p1sc:kb,p1ss:lb,p1v:0|mb,p1cc:0|nb,p1mc:0|ob,p1wc:0|pb,p1r:0|qb,m0:0|rb,m0c:sb,m0rr:0|tb,m0co:ub,m0sc:vb,m0ss:wb,m0r:0|xb,m1:0|yb,m1c:zb,m1rr:0|Ab,m1co:Bb,m1sc:Cb,m1ss:Db,m1r:0|Eb,b:0|Fb,bd:0|Gb,bc:Hb,bco:Ib,bsc:Jb,bss:Kb,bv:0|Lb,fd:Sa,fdc:Ta,fdp:Ua,pds:btoa(jt.Util.uInt8BiArrayToByteString(Mb)),pdc:Nb,hb:0|Ob,hc:Pb,PF0:S,PF1:T,PF2:U,AC0:V,AC1:W,AF0:X,AF1:Y,AV0:Z,AV1:$,HP0:_,HP1:aa,HM0:ba,HM1:ca,HB:da,XM0P:mc,XM1P:nc,XP0F:oc,XP1F:pc,XM0F:qc,XM1F:rc,XBP:sc,XPM:tc}},this.loadState=function(a){Ga=jt.Util.byteStringToUInt32Array(atob(a.lp)),ac=a.lo,bc=!!a.oc,_b=!!a.rl,Ha=!!a.vs,Ia=!!a.vb,Ja=!!a.vbd,Q=!!a.vbn,Ka=jt.Util.byteStringToBooleanArray(a.f),La=!!a.fi,Ma=!!a.fp,Na=a.fc,Oa=a.fb,Pa=!!a.fr,Qa=!!a.fs,Ra=!!a.ft,Va=a.p0,Wa=a.p0d,Xa=a.p0c,Ya=!!a.p0rr,Za=a.p0co,$a=a.p0sc,_a=a.p0ss,ab=!!a.p0v,bb=!!a.p0cc,cb=!!a.p0mc,db=!!a.p0wc,eb=!!a.p0r,fb=a.p1,gb=a.p1d,hb=a.p1c,ib=!!a.p1rr,jb=a.p1co,kb=a.p1sc,lb=a.p1ss,mb=!!a.p1v,nb=!!a.p1cc,ob=!!a.p1mc,pb=!!a.p1wc,qb=!!a.p1r,rb=!!a.m0,sb=a.m0c,tb=!!a.m0rr,ub=a.m0co,vb=a.m0sc,wb=a.m0ss,xb=!!a.m0r,yb=!!a.m1,zb=a.m1c,Ab=!!a.m1rr,Bb=a.m1co,Cb=a.m1sc,Db=a.m1ss,Eb=!!a.m1r,Fb=!!a.b,Gb=!!a.bd,Hb=a.bc,Ib=a.bco,Jb=a.bsc,Kb=a.bss,Lb=!!a.bv,Sa=a.fd,Ta=a.fdc,Ua=a.fdp,Mb=jt.Util.byteStringToUInt8BiArray(atob(a.pds),3),Nb=a.pdc,Ob=!!a.hb,Pb=a.hc,S=a.PF0,T=a.PF1,U=a.PF2,V=a.AC0,lc.getChannel0().setControl(15&V),W=a.AC1,lc.getChannel1().setControl(15&W),X=a.AF0,lc.getChannel0().setDivider((31&X)+1),Y=a.AF1,lc.getChannel1().setDivider((31&Y)+1),Z=a.AV0,lc.getChannel0().setVolume(15&Z),$=a.AV1,lc.getChannel1().setVolume(15&$),_=a.HP0,aa=a.HP1,ba=a.HM0,ca=a.HM1,da=a.HB,mc=a.XM0P,nc=a.XM1P,oc=a.XP0F,pc=a.XP1F,qc=a.XM0F,rc=a.XM1F,sc=a.XBP,tc=a.XPM,Sb&&K()};var O,P,Q,R,S,T,U,V,W,X,Y,Z,$,_,aa,ba,ca,da,ea=68,fa=228,ga=50,ha=4278190080,ia=4278190080,ja=4292730333,ka=4278190335,la=4280427195,ma=4279308663,na=4294901760,oa=4290454050,pa=4285993233,qa=4284901119,ra=4294927974,sa=4282681412,ta=4281589043,ua=4281549875,va=4278255615,wa=4280295456,xa=4282664004,ya=4280953386,za=4287103112,Aa=4294967295,Ba=15,Ca=63,Da=a,Ea=b,Fa=!1,Ga=jt.Util.arrayFill(new Array(fa),0),Ha=!1,Ia=!1,Ja=!1,Ka=jt.Util.arrayFill(new Array(40),!1),La=!0,Ma=!1,Na=4278190080,Oa=4278190080,Pa=!1,Qa=!1,Ra=!1,Sa=-1,Ta=-1,Ua=-1,Va=0,Wa=0,Xa=4278190080,Ya=!1,Za=0,$a=-1,_a=4,ab=!1,bb=!1,cb=!1,db=!1,eb=!1,fb=0,gb=0,hb=4278190080,ib=!1,jb=0,kb=-1,lb=4,mb=!1,nb=!1,ob=!1,pb=!1,qb=!1,rb=!1,sb=4278190080,tb=!1,ub=0,vb=-1,wb=8,xb=!1,yb=!1,zb=4278190080,Ab=!1,Bb=0,Cb=-1,Db=8,Eb=!1,Fb=!1,Gb=!1,Hb=4278190080,Ib=0,Jb=-1,Kb=8,Lb=!1,Mb=jt.Util.arrayFillWithArrayClone(new Array(ga),[0,0,0]),Nb=0,Ob=!1,Pb=-1,Qb=!1,Rb=!1,Sb=!1,Tb=0,Ub=!1,Vb=jt.Util.arrayFill(new Array(fa),0),Wb=!1,Xb=0,Yb=ja,Zb=ha,$b=ha,_b=!1,ac=-1,bc=!1,cc=!1,dc=!1,ec=!1,fc=!1,gc=-1,hc=0,ic=-1,jc=0,kc=new jt.TiaVideoSignal,lc=new jt.TiaAudioSignal,mc=0,nc=0,oc=0,pc=0,qc=0,rc=0,sc=0,tc=0,uc=0,vc=0,wc=0,xc=0,yc=0,zc=0},jt.Bus=function(a,b,c,d){function e(e){f=a,g=b,h=c,i=d,f.connectBus(e),g.connectBus(e),h.connectBus(e)}this.powerOn=function(){l=0,j||(g.getVideoOutput().showOSD("NO CARTRIDGE INSERTED!",!0),l=256*Math.random()|0),null!=j&&j.powerOn(),i.powerOn(),h.powerOn(),f.powerOn(),g.powerOn()},this.powerOff=function(){g.powerOff(),f.powerOff(),h.powerOff(),i.powerOff()},this.setCartridge=function(a){j=a,j&&(l=0,j.connectBus(this)),k=j&&j.needsBusMonitoring(); },this.getCartridge=function(){return j},this.getTia=function(){return g},this.clockPulse=function(){h.clockPulse(),f.clockPulse()},this.read=function(a){return k&&j.monitorBusBeforeRead(a,l),(a&m)===n?j&&(l=j.read(a)):l=(a&o)===p?i.read(a):(a&s)===t?h.read(a):63&l|g.read(a),l},this.write=function(a,b){k&&j.monitorBusBeforeWrite(a,b),l=b,(a&q)===r?g.write(a,b):(a&o)===p?i.write(a,b):(a&s)===t?h.write(a,b):j&&j.write(a,b)};var f,g,h,i,j,k=!1,l=0,m=4096,n=4096,o=4736,p=128,q=4224,r=0,s=4736,t=640;e(this)},jt.Clock=function(a,b){function c(){e(b||p)}var d=this;this.go=function(){h=!0,n?n=!1:f()},this.pauseOnNextPulse=function(a){o=a||null,n=!0},this.setFrequency=function(a){h?this.pauseOnNextPulse(function(){e(a),d.go()}):e(a)};var e=function(a){i=a,j=1e3/a,k=window.requestAnimationFrame&&a===p},f=function(){return n?(g(),o&&o(),void(o=null)):(a.clockPulse(),void(k?l=window.requestAnimationFrame(f):m||(m=window.setInterval(f,j))))},g=function(){l&&(window.cancelAnimationFrame(l),l=null),m&&(window.clearTimeout(m),m=null),n=!1,h=!1},h=!1,i=null,j=null,k=null,l=null,m=null,n=!1,o=null,p=Javatari.SCREEN_NATURAL_FPS;c()},jt.ConsoleControls={JOY0_UP:11,JOY0_DOWN:12,JOY0_LEFT:13,JOY0_RIGHT:14,JOY0_BUTTON:15,JOY1_UP:21,JOY1_DOWN:22,JOY1_LEFT:23,JOY1_RIGHT:24,JOY1_BUTTON:25,PADDLE0_POSITION:31,PADDLE1_POSITION:41,PADDLE0_BUTTON:35,PADDLE1_BUTTON:45,POWER:51,BLACK_WHITE:52,SELECT:53,RESET:54,DIFFICULTY0:55,DIFFICULTY1:56,POWER_OFF:61,DEBUG:101,NO_COLLISIONS:102,TRACE:103,PAUSE:104,FRAME:105,FAST_SPEED:106,CARTRIDGE_FORMAT:107,CARTRIDGE_CLOCK_DEC:108,CARTRIDGE_CLOCK_INC:109,CARTRIDGE_REMOVE:110,VIDEO_STANDARD:111,POWER_FRY:112,SAVE_STATE_0:{to:0},SAVE_STATE_1:{to:1},SAVE_STATE_2:{to:2},SAVE_STATE_3:{to:3},SAVE_STATE_4:{to:4},SAVE_STATE_5:{to:5},SAVE_STATE_6:{to:6},SAVE_STATE_7:{to:7},SAVE_STATE_8:{to:8},SAVE_STATE_9:{to:9},SAVE_STATE_10:{to:10},SAVE_STATE_11:{to:11},SAVE_STATE_12:{to:12},LOAD_STATE_0:{from:0},LOAD_STATE_1:{from:1},LOAD_STATE_2:{from:2},LOAD_STATE_3:{from:3},LOAD_STATE_4:{from:4},LOAD_STATE_5:{from:5},LOAD_STATE_6:{from:6},LOAD_STATE_7:{from:7},LOAD_STATE_8:{from:8},LOAD_STATE_9:{from:9},LOAD_STATE_10:{from:10},LOAD_STATE_11:{from:11},LOAD_STATE_12:{from:12},SAVE_STATE_FILE:201,playerDigitalControls:[11,12,13,14,15,21,22,23,24,25,35,45]},jt.AtariConsole=function(){function a(){u(),v(),k()}function b(){this.insert=function(a,b){b&&e.powerIsOn&&e.powerOff(),h(a),b&&!e.powerIsOn&&e.powerOn()},this.inserted=function(){return i()},this.cartridgeInserted=function(b,c){for(var d=0;d=1024&&c<=2047&&(f[c-1024]=b)};var d=function(a){return a&g};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),ra:btoa(jt.Util.uInt8ArrayToByteString(f))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),f=jt.Util.byteStringToUInt8Array(atob(a.ra))};var e,f=jt.Util.arrayFill(new Array(1024),0),g=4095;a&&c(this)},jt.Cartridge2K_CV.prototype=jt.Cartridge.base,jt.Cartridge2K_CV.createFromSaveState=function(a){var b=new jt.Cartridge2K_CV;return b.loadState(a),b},jt.CartridgeBankedByMaskedRange=function(a,b,c,d,e){function f(f){f.rom=a,f.format=b,h=a.content;var g=h.length/q;i=c,j=i+g-1,l=e,null==d||void 0==d?(o=!1,k=!0):(o=!!d,k=!1),m=d!==!1?jt.Util.arrayFill(new Array(l),0):null}this.read=function(a){var b=g(a);return o&&b>=l&&b<2*l?m[b-l]:h[n+b]},this.write=function(a,b){var c=g(a);c=i&&b<=j&&(n=q*(b-i)),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(h)),bo:n,bb:i,es:l,tb:j,s:0|o,sa:0|k,e:m&&btoa(jt.Util.uInt8ArrayToByteString(m))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),h=jt.Util.byteStringToUInt8Array(atob(a.b)),n=a.bo,i=a.bb,l=a.es,j=a.tb,o=!!a.s,k=!!a.sa,m=a.e&&jt.Util.byteStringToUInt8Array(atob(a.e))};var h,i,j,k,l,m,n=0,o=!1,p=4095,q=4096;a&&f(this)},jt.CartridgeBankedByMaskedRange.prototype=jt.Cartridge.base,jt.CartridgeBankedByMaskedRange.createFromSaveState=function(a){var b=new jt.CartridgeBankedByMaskedRange;return b.loadState(a),b},jt.Cartridge8K_E0=function(a,b){function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return b<1024?e[f+b]:b<2048?e[g+b-1024]:b<3072?e[h+b-2048]:e[4096+b]},this.write=function(a,b){d(a)};var d=function(a){var b=a&i;return b>=4064&&b<=4087&&(b<=4071?f=1024*(b-4064):b<=4079?g=1024*(b-4072):b<=4087&&(h=1024*(b-4080))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),s0:f,s1:g,s2:h}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),f=a.s0,g=a.s1,h=a.s2};var e,f=0,g=0,h=0,i=4095;a&&c(this)},jt.Cartridge8K_E0.prototype=jt.Cartridge.base,jt.Cartridge8K_E0.createFromSaveState=function(a){var b=new jt.Cartridge8K_E0;return b.loadState(a),b},jt.Cartridge64K_F0=function(a,b){function c(c){c.rom=a, c.format=b,e=a.content}this.read=function(a){var b=d(a);return e[f+b]},this.write=function(a,b){d(a)};var d=function(a){var b=a&g;return b==j&&(f+=i,f>=h&&(f=0)),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),bo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),f=a.bo};var e,f=0,g=4095,h=65536,i=4096,j=4080;a&&c(this)},jt.Cartridge64K_F0.prototype=jt.Cartridge.base,jt.Cartridge64K_F0.createFromSaveState=function(a){var b=new jt.Cartridge64K_F0;return b.loadState(a),b},jt.Cartridge8K_FE=function(a,b){function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return e[f+b]},this.write=function(a,b){d(a)};var d=function(a){return 0!==(8192&a)?0!==f&&(f=0):f!=h&&(f=h),a&g};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),bo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),f=a.bo};var e,f=0,g=4095,h=4096;a&&c(this)},jt.Cartridge8K_FE.prototype=jt.Cartridge.base,jt.Cartridge8K_FE.createFromSaveState=function(a){var b=new jt.Cartridge8K_FE;return b.loadState(a),b},jt.Cartridge16K_E7=function(a,b){function c(c){c.rom=a,c.format=b,e=a.content}this.read=function(a){var b=d(a);return b>=2304&&b<=2559?h[j+b-2304]:i&&b>=1024&&b<=2047?h[b-1024]:b=2048&&c<=2303?h[j+c-2048]=b:i&&c<=1023&&(h[c]=b)};var d=function(a){var b=a&k;return b>=4064&&b<=4075&&(b<=4070?f=m*(b-4064):4071==b?i=!0:b<=4075&&(j=g+p*(b-4072))),b};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),bo:f,rs:i,ro:j,ra:btoa(jt.Util.uInt8ArrayToByteString(h))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),f=a.bo,i=a.rs,j=a.ro,h=jt.Util.byteStringToUInt8Array(atob(a.ra))};var e,f=0,g=1024,h=jt.Util.arrayFill(new Array(2048),0),i=!1,j=g,k=4095,l=16384,m=2048,n=2048,o=l-m-n,p=256;a&&c(this)},jt.Cartridge16K_E7.prototype=jt.Cartridge.base,jt.Cartridge16K_E7.createFromSaveState=function(a){var b=new jt.Cartridge16K_E7;return b.loadState(a),b},jt.Cartridge10K_DPCa=function(a,b){function c(c){c.rom=a,c.format=b,m=a.content}this.powerOn=function(){y=p,z=0},this.connectBus=function(a){l=a.getTia().getAudioOutput().getChannel0()},this.needsAudioClock=function(){return!0},this.read=function(a){var b=d(a);return b<=63||b>=2048&&b<=2111?f(255&b):m[r+b]},this.write=function(a,b){var c=d(a);(c>=64&&c<=127||c>=2112&&c<=2175)&&g(255&c,b)},this.audioClockPulse=function(){if((z+y|0)>(0|z))for(var a=5;a<=7;a++)x[a]&&(t[a]--,255==(255&t[a])&&h(a,65280&t[a]|u[a]),j(a),A||(A=!0));z+=y,A&&(e(),l.setVolume(B))};var d=function(a){var b=a&o;return 4088===b?r=0:4089===b&&(r=4096),b},e=function(){B=n[(x[5]?4&w[5]:0)|(x[6]?2&w[6]:0)|(x[7]?1&w[7]:0)],A=!1},f=function(a){var b;return a>=0&&a<=3?(k(),s):a>=4&&a<=7?(A&&e(),B):a>=8&&a<=15?(b=m[q-t[a-8]],i(a-8),b):a>=16&&a<=23?(b=m[q-t[a-16]]&w[a-16],i(a-16),b):a>=24&&a<=31?(b=m[q-t[a-24]]&w[a-24],i(a-24),b=240&b|15&b):a>=32&&a<=39?(b=m[q-t[a-32]]&w[a-32],i(a-32),b=128&b|64&b|32&b|16&b|8&b|4&b|2&b|1&b):a>=40&&a<=47?(b=m[q-t[a-40]]&w[a-40],i(a-40),b=255&(b>>>1|b<<7)):a>=48&&a<=55?(b=m[q-t[a-48]]&w[a-48],i(a-48),b=255&(b<<1|b>>7&1)):a>=56&&a<=63?w[a-56]:0},g=function(a,b){if(a>=64&&a<=71){var c=a-64;return u[c]=b,void((255&t[c])===u[c]&&(w[c]=255))}return a>=72&&a<=79?(v[a-72]=b,void(w[a-72]=0)):a>=80&&a<=87?void h(a-80,65280&t[a-80]|255&b):a>=88&&a<=91?void h(a-88,255&t[a-88]|(7&b)<<8):92==a?void h(4,255&t[4]|(7&b)<<8):a>=93&&a<=95?(h(a-88,(255&t[a-88])+((7&b)<<8)),void(x[a-88]=(16&b)>>>4)):void(a>=96&&a<=103||a>=112&&a<=119&&(s=0))},h=function(a,b){t[a]=b},i=function(a){var b=t[a]-1;b<0&&(b=2047),h(a,b),j(a)},j=function(a){var b=255&t[a];b==u[a]?w[a]=255:b==v[a]&&(w[a]=0)},k=function(){s=255&(s<<1|1&~(s>>7^s>>5^s>>4^s>>3)),255===s&&(s=0)};this.controlStateChanged=function(a,b){if(b)switch(a){case jt.ConsoleControls.CARTRIDGE_CLOCK_DEC:y<1&&(y+=.01),jt.Util.log("DPC audio clock factor: "+y);break;case jt.ConsoleControls.CARTRIDGE_CLOCK_INC:y>.3&&(y-=.01),jt.Util.log("DPC audio clock factor: "+y)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(m)),bo:r,rn:s,fp:btoa(jt.Util.uInt8ArrayToByteString(t)),fs:btoa(jt.Util.uInt8ArrayToByteString(u)),fe:btoa(jt.Util.uInt8ArrayToByteString(v)),fm:btoa(jt.Util.uInt8ArrayToByteString(w)),a:btoa(jt.Util.uInt8ArrayToByteString(x))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),m=jt.Util.byteStringToUInt8Array(atob(a.b)),r=a.bo,s=a.rn,t=jt.Util.byteStringToUInt8Array(atob(a.fp)),u=jt.Util.byteStringToUInt8Array(atob(a.fs)),v=jt.Util.byteStringToUInt8Array(atob(a.fe)),w=jt.Util.byteStringToUInt8Array(atob(a.fm)),x=jt.Util.byteStringToUInt8Array(atob(a.a))};var l,m,n=[0,5,5,10,5,10,10,15],o=4095,p=.62,q=10239,r=0,s=0,t=jt.Util.arrayFill(new Array(8),0),u=jt.Util.arrayFill(new Array(8),0),v=jt.Util.arrayFill(new Array(8),0),w=jt.Util.arrayFill(new Array(8),0),x=jt.Util.arrayFill(new Array(8),0),y=p,z=0,A=!0,B=0;a&&c(this)},jt.Cartridge10K_DPCa.prototype=jt.Cartridge.base,jt.Cartridge10K_DPCa.createFromSaveState=function(a){var b=new jt.Cartridge10K_DPCa;return b.loadState(a),b},jt.Cartridge24K_28K_32K_FA2=function(a,b,c){function d(d){d.rom=a,d.format=b,n=a.content,p=c||0,q=p;var e=(n.length-p)/x;o=r+e-1}var e=this;this.connectBus=function(a){l=a},this.connectSaveStateSocket=function(a){m=a},this.read=function(a){var b,c=f(a);if(b=c>=256&&c<512?s[c-256]:n[q+c],c!==y)return b;if(0===u){var d=s[z];if(1===d||2===d)return g(d),64|b}return 0===u?191&b:(j(),0!==u?64|b:191&b)},this.write=function(a,b){var c=f(a);c<256&&(s[c]=b)};var f=function(a){var b=a&w;return b>=r&&b<=o&&(q=p+x*(b-r)),b},g=function(a){u=a,t=Date.now(),1===a?h():2===a&&i()},h=function(){if(l.getTia().getVideoOutput().showOSD("Reading from Cartridge Flash Memory...",!0),m){var a=m.getMedia().loadResourceFromFile(k());a&&(v=jt.Util.byteStringToUInt8Array(atob(a)))}s=v.slice(0)},i=function(){l.getTia().getVideoOutput().showOSD("Writing to Cartridge Flash Memory...",!0),v=s.slice(0),m&&m.getMedia().saveResourceToFile(k(),btoa(jt.Util.uInt8ArrayToByteString(v)))},j=function(){Date.now()-t>1100&&(t=Date.now(),u=0,s[z]=0,l.getTia().getVideoOutput().showOSD("Done.",!0),m&&m.externalStateChange())},k=function(){return"hfm"+e.rom.info.h};this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(n)),rs:p,bo:q,tb:o,e:btoa(jt.Util.uInt8ArrayToByteString(s)),ho:u,ht:t}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),n=jt.Util.byteStringToUInt8Array(atob(a.b)),p=a.rs||0,q=a.bo,o=a.tb,s=jt.Util.byteStringToUInt8Array(atob(a.e)),u=a.ho||0,t=Date.now()};var l,m,n,o,p=0,q=0,r=4085,s=jt.Util.arrayFill(new Array(256),0),t=Date.now(),u=0,v=jt.Util.arrayFill(new Array(256),0),w=4095,x=4096,y=4084,z=255;a&&d(this)},jt.Cartridge24K_28K_32K_FA2.prototype=jt.Cartridge.base,jt.Cartridge24K_28K_32K_FA2.createFromSaveState=function(a){var b=new jt.Cartridge24K_28K_32K_FA2;return b.loadState(a),b},jt.CartridgeBankedByBusMonitoring=function(a,b){this.needsBusMonitoring=function(){return!0},this.monitorBusBeforeRead=function(a,b){this.performBankSwitchOnMonitoredAccess(a)},this.monitorBusBeforeWrite=function(a,b){this.performBankSwitchOnMonitoredAccess(a)},this.performBankSwitchOnMonitoredAccess=function(a){}},jt.CartridgeBankedByBusMonitoring.prototype=jt.Cartridge.base,jt.CartridgeBankedByBusMonitoring.base=new jt.CartridgeBankedByBusMonitoring,jt.Cartridge8K_512K_3F=function(a,b){ function c(c){c.rom=a,c.format=b,d=a.content,e=(d.length-i)/i-1,f=d.length-2*i}this.read=function(a){var b=a&h;return b>=j?d[f+b]:d[g+b]},this.monitorBusBeforeWrite=function(a,b){if(a<=63){var c=255&b;c<=e&&(g=c*i)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(d)),bo:g,sm:e,fo:f}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.byteStringToUInt8Array(atob(a.b)),g=a.bo,e=a.sm,f=a.fo};var d,e,f,g=0,h=4095,i=2048,j=2048;a&&c(this)},jt.Cartridge8K_512K_3F.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3F.createFromSaveState=function(a){var b=new jt.Cartridge8K_512K_3F;return b.loadState(a),b},jt.Cartridge8K_512K_3E=function(a,b){function c(c){c.rom=a,c.format=b,e=a.content,f=(e.length-m)/m-1,g=e.length-2*m}this.read=function(a){var b=d(a);return b>=n?e[g+b]:j>=0&&b<1024?k[j+b]||0:e[i+b]},this.write=function(a,b){if(!(j<0)){var c=d(a);c>=1024&&c<=2047&&(k[j+c-1024]=b)}};var d=function(a){return a&l};this.monitorBusBeforeWrite=function(a,b){if(63===a){var c=255&b;return void(c<=f&&(i=c*m,j=-1))}if(62===a){var d=255&b;j=d*h}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e)),bo:i,sm:f,fo:g,ro:j,ra:btoa(jt.Util.uInt8ArrayToByteString(k))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b)),i=a.bo,f=a.sm,g=a.fo,j=a.ro,k=jt.Util.byteStringToUInt8Array(atob(a.ra))};var e,f,g,h=1024,i=0,j=-1,k=jt.Util.arrayFill(new Array(h),0),l=4095,m=2048,n=2048;a&&c(this)},jt.Cartridge8K_512K_3E.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_512K_3E.createFromSaveState=function(a){var b=new jt.Cartridge8K_512K_3E;return b.loadState(a),b},jt.Cartridge8K_256K_SB=function(a,b){function c(c){c.rom=a,c.format=b,d=a.content,e=d.length/h-1}this.read=function(a){return d[f+(a&g)]},this.performBankSwitchOnMonitoredAccess=function(a){if(2048===(6144&a)){var b=127&a;b>e||(f=b*h)}},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(d)),bo:f,m:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.byteStringToUInt8Array(atob(a.b)),f=a.bo,e=a.m};var d,e,f=0,g=4095,h=4096;a&&c(this)},jt.Cartridge8K_256K_SB.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_256K_SB.createFromSaveState=function(a){var b=new jt.Cartridge8K_256K_SB;return b.loadState(a),b},jt.Cartridge8K_64K_AR=function(a,b){function c(c){c.rom=a,c.format=b,e=jt.Util.arrayFill(new Array(4*M)),o()}this.powerOn=function(){h(0),E=0},this.connectBus=function(a){d=a},this.read=function(a){return f=K&&f0?void(a!==v&&(v=a,0===--w&&(a&R)===S&&(f>2&7;switch(b){case 0:q=2*M,r=N;break;case 1:q=0*M,r=N;break;case 2:q=2*M,r=0*M;break;case 3:q=0*M,r=2*M;break;case 4:q=2*M,r=N;break;case 5:q=1*M,r=N;break;case 6:q=2*M,r=1*M;break;case 7:q=1*M,r=2*M;break;default:throw new Error("Invalid bank configuration")}w=0,u=0!==(2&a),x=0===(1&a)},i=function(b){for(var c=!1;;){if(E>a.content.length-1){if(c)return 0===b?d.getTia().getVideoOutput().showOSD("Could not load Tape from Start. Not a Start Tape ROM!",!0):d.getTia().getVideoOutput().showOSD("Could not find next Part to load in Tape!",!0),void n(!1);E=0,c=!0}if(jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,E)===b)return 0===b?d.getTia().getVideoOutput().showOSD("Loaded Tape from Start",!0):d.getTia().getVideoOutput().showOSD("Loaded next Part from Tape",!0),void j();E+=O}},j=function(){k(),l(),m()},k=function(){jt.Util.arrayCopy(a.content,E+4*M,s,0,s.length),y=s[1]<<8|255&s[0],z=s[2],A=s[3],B=s[4],C=s[5],D=s[7]<<8|255&s[6],g=jt.Util.arrayFill(new Array(A),0),jt.Util.arrayCopy(s,16,g,0,A)},l=function(){jt.Util.arrayFillSegment(e,7*L,8*L-1,0);for(var b=E,c=0,d=g.length;c>2)*L;h+i+255>8&255,n(!0)},n=function(a){e[N+J-63488]=a?1:0},o=function(){var a=JSZip.compressions.DEFLATE.uncompress(jt.Util.byteStringToUInt8Array(atob(P)));jt.Util.arrayCopy(a,0,e,N,M)},p=256,q=0,r=0,s=jt.Util.arrayFill(new Array(p),0),t=0,u=!1,v=-1,w=0,x=!1,y=0,z=0,A=0,B=0,C=0,D=0,E=0,F=64256,G=64257,H=64258,I=64260,J=64261,K=3072,L=256,M=8*L,N=3*M,O=4*M+p,P="7dSxCsIwEAbgv6niGkeddPVZ8kCOXc43yCIokkGIUN+gLxAoZHTxHRxjYq2xk7vSIPS75bb7uYNTuOJWu/bod3iU42BzUTiBe9sTzSjToBnNBVxfQz/nQ+2NhA2a05KYmhhjmxhoQZymxGil8gpeesOdyioW5DN25yxsiri3chQOUO1WeCSI/hPx9AJ/m/576KROMUhlfdE4dQ+AfJoPNBikgOZdLw==",Q=4095,R=4096,S=4096;this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(e))}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),e=jt.Util.byteStringToUInt8Array(atob(a.b))},a&&c(this)},jt.Cartridge8K_64K_AR.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_64K_AR.createFromSaveState=function(a){var b=new jt.Cartridge8K_64K_AR;return b.loadState(a),b},jt.Cartridge8K_64K_AR.HEADER_SIZE=256,jt.Cartridge8K_64K_AR.PAGE_SIZE=256,jt.Cartridge8K_64K_AR.BANK_SIZE=8*jt.Cartridge8K_64K_AR.PAGE_SIZE,jt.Cartridge8K_64K_AR.PART_SIZE=4*jt.Cartridge8K_64K_AR.BANK_SIZE+jt.Cartridge8K_64K_AR.HEADER_SIZE,jt.Cartridge8K_64K_AR.peekPartNoOnTape=function(a,b){return a[b+4*jt.Cartridge8K_64K_AR.BANK_SIZE+5]},jt.Cartridge8K_64K_AR.checkTape=function(a){if(0!=jt.Cartridge8K_64K_AR.peekPartNoOnTape(a.content,0)){var b=new Error("Wrong Supercharger Tape Part ROM!\nPlease load a Full Tape ROM file.");throw b.formatDenial=!0,b}},jt.Cartridge64K_X07=function(a,b){function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){2061===(6159&a)?e=((240&a)>>4)*g:e>=h&&0===(6272&a)&&(e=(0===(64&a)?14:15)*g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(d)),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.byteStringToUInt8Array(atob(a.b)),e=a.bo};var d,e=0,f=4095,g=4096,h=14*g;a&&c(this)},jt.Cartridge64K_X07.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge64K_X07.createFromSaveState=function(a){var b=new jt.Cartridge64K_X07;return b.loadState(a),b},jt.Cartridge8K_0840=function(a,b){function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){var b=6208&a;2048===b?0!==e&&(e=0):2112===b&&e!==g&&(e=g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(d)),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r),d=jt.Util.byteStringToUInt8Array(atob(a.b)),e=a.bo};var d,e=0,f=4095,g=4096;a&&c(this)},jt.Cartridge8K_0840.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_0840.createFromSaveState=function(a){var b=new jt.Cartridge8K_0840;return b.loadState(a),b},jt.Cartridge8K_UA=function(a,b){function c(c){c.rom=a,c.format=b,d=a.content}this.read=function(a){return d[e+(a&f)]},this.performBankSwitchOnMonitoredAccess=function(a){544===a?0!==e&&(e=0):576===a&&e!==g&&(e=g)},this.saveState=function(){return{f:this.format.name,r:this.rom.saveState(),b:btoa(jt.Util.uInt8ArrayToByteString(d)),bo:e}},this.loadState=function(a){this.format=jt.CartridgeFormats[a.f],this.rom=jt.ROM.loadState(a.r), d=jt.Util.byteStringToUInt8Array(atob(a.b)),e=a.bo};var d,e=0,f=4095,g=4096;a&&c(this)},jt.Cartridge8K_UA.prototype=jt.CartridgeBankedByBusMonitoring.base,jt.Cartridge8K_UA.createFromSaveState=function(a){var b=new jt.Cartridge8K_UA;return b.loadState(a),b},jt.CartridgeFormats={"4K":{name:"4K",desc:"4K Atari",priority:101,tryFormat:function(a){if(a.content.length>=8&&a.content.length<=4096&&4096%a.content.length===0)return this},createCartridgeFromRom:function(a){return new jt.Cartridge4K(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge4K.createFromSaveState(a)}},CV:{name:"CV",desc:"2K Commavid +RAM",priority:102,tryFormat:function(a){if(2048===a.content.length||4096===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge2K_CV(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge2K_CV.createFromSaveState(a)}},E0:{name:"E0",desc:"8K Parker Bros.",priority:102,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_E0(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_E0.createFromSaveState(a)}},F0:{name:"F0",desc:"64K Dynacom Megaboy",priority:101,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_F0(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge64K_F0.createFromSaveState(a)}},FE:{name:"FE",desc:"8K Robotank/Decathlon",priority:103,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_FE(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_FE.createFromSaveState(a)}},E7:{name:"E7",desc:"16K M-Network",priority:102,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge16K_E7(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge16K_E7.createFromSaveState(a)}},F8:{name:"F8",desc:"8K Atari (+RAM)",priority:101,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,null,128)},createCartridgeFromSaveState:function(a){return jt.CartridgeBankedByMaskedRange.createFromSaveState(a)}},F6:{name:"F6",desc:"16K Atari (+RAM)",priority:101,tryFormat:function(a){if(16384===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4086,null,128)},createCartridgeFromSaveState:function(a){return jt.CartridgeBankedByMaskedRange.createFromSaveState(a)}},F4:{name:"F4",desc:"32K Atari (+RAM)",priority:101,tryFormat:function(a){if(32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4084,null,128)},createCartridgeFromSaveState:function(a){return jt.CartridgeBankedByMaskedRange.createFromSaveState(a)}},FA2cu:{name:"FA2cu",desc:"32K CBS RAM Plus CU Image",priority:103,tryFormat:function(a){if(32768===a.content.length){var b=jt.Util.arraysEqual(a.content.slice(32,36),this.cuMagicWord);return this.priority=103-(b?30:0),this}},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this,1024)},createCartridgeFromSaveState:function(a){return jt.Cartridge24K_28K_32K_FA2.createFromSaveState(a)},cuMagicWord:[30,171,173,16]},FA2:{name:"FA2",desc:"24K/28K/32K CBS RAM Plus",priority:102,tryFormat:function(a){if(24576===a.content.length||28672===a.content.length||32768===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge24K_28K_32K_FA2(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge24K_28K_32K_FA2.createFromSaveState(a)}},FA:{name:"FA",desc:"12K CBS RAM Plus",priority:101,tryFormat:function(a){if(12288===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4088,!0,256)},createCartridgeFromSaveState:function(a){return jt.CartridgeBankedByMaskedRange.createFromSaveState(a)}},EF:{name:"EF",desc:"8K-64K H. Runner (+RAM)",priority:114,tryFormat:function(a){if(a.content.length%4096===0&&a.content.length>=8192&&a.content.length<=65536)return this},createCartridgeFromRom:function(a){return new jt.CartridgeBankedByMaskedRange(a,this,4064,null,128)},createCartridgeFromSaveState:function(a){return jt.CartridgeBankedByMaskedRange.createFromSaveState(a)}},DPCa:{name:"DPCa",desc:"10K DPC Pitfall 2 (Enhanced Audio)",priority:101,tryFormat:function(a){if(a.content.length>=10240&&a.content.length<=10496)return this},createCartridgeFromRom:function(a){return new jt.Cartridge10K_DPCa(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge10K_DPCa.createFromSaveState(a)}},"3F":{name:"3F",desc:"8K-512K Tigervision",priority:112,tryFormat:function(a){if(a.content.length%2048===0&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3F(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_512K_3F.createFromSaveState(a)}},"3E":{name:"3E",desc:"8K-512K Tigervision (+RAM)",priority:111,tryFormat:function(a){if(a.content.length%2048===0&&a.content.length<=524288)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_512K_3E(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_512K_3E.createFromSaveState(a)}},X07:{name:"X07",desc:"64K AtariAge",priority:102,tryFormat:function(a){if(65536===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge64K_X07(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge64K_X07.createFromSaveState(a)}},"0840":{name:"0840",desc:"8K Econobanking",priority:116,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_0840(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_0840.createFromSaveState(a)}},UA:{name:"UA",desc:"8K UA Limited",priority:115,tryFormat:function(a){if(8192===a.content.length)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_UA(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_UA.createFromSaveState(a)}},SB:{name:"SB",desc:"8K-256K Superbanking",priority:113,tryFormat:function(a){if(a.content.length%4096===0&&a.content.length>=8192&&a.content.length<=262144)return this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_256K_SB(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_256K_SB.createFromSaveState(a)}},AR:{name:"AR",desc:"8K-64K Arcadia/Starpath/Supercharger",priority:101,tryFormat:function(a){if(a.content.length%jt.Cartridge8K_64K_AR.PART_SIZE===0&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE>=1&&a.content.length/jt.Cartridge8K_64K_AR.PART_SIZE<=8)return jt.Cartridge8K_64K_AR.checkTape(a),this},createCartridgeFromRom:function(a){return new jt.Cartridge8K_64K_AR(a,this)},createCartridgeFromSaveState:function(a){return jt.Cartridge8K_64K_AR.createFromSaveState(a)}}},jt.CartridgeDatabase=function(){this.createCartridgeFromRom=function(b){var c=a(b);if(0!==c.length){var d=c[0];return jt.Util.log(""+d.name+": "+d.desc+", priority: "+d.priority+(d.priorityBoosted?" ("+d.priorityBoosted+")":"")),d.createCartridgeFromRom(b)}},this.createCartridgeFromSaveState=function(a){var b=jt.CartridgeFormats[a.f];if(!b){var c=new Error("Unsupported ROM Format: "+a.f);throw c.javatari=!0,c}return b.createCartridgeFromSaveState(a)},this.produceInfo=function(a){var d=a.content.length,e=jt.MD5(a.content);a.content.length>d&&a.content.splice(d);var f=jt.CartridgeInfoLibrary[e];return f?jt.Util.log(""+f.n):(f=b(a.source),jt.Util.log("Unknown ROM: "+f.n)),c(f,a.source,e),f};var a=function(a){var b,c,e=[];for(var f in jt.CartridgeFormats)try{if(b=jt.CartridgeFormats[f].tryFormat(a), !b)continue;d(b,a.info),e.push(b)}catch(a){if(!a.formatDenial)throw a;c||(c=a)}if(0===e.length){var g=c||new Error("Unsupported ROM Format. Size: "+a.content.length);throw g.javatari=!0,g}return e.sort(function(a,b){return(a.priorityBoosted||a.priority)-(b.priorityBoosted||b.priority)}),e},b=function(a){var b={n:"Unknown"};if(!a||!a.trim())return b;var c=a,d=c.lastIndexOf("/"),e=c.lastIndexOf("\\"),f=c.lastIndexOf("?"),g=Math.max(d,Math.max(e,f));g>=0&&g=0&&(c=c.substring(0,h)),b.n=c.trim()||"Unknown",b},c=function(a,b,c){a.h=c,a.l||(a.l=e(a.n));var d=a.n.toUpperCase();a:if(!a.p&&(a.p=0,!d.match(k+"JOYSTICK(S)?"+l)))if(d.match(k+"PADDLE(S)?"+l))a.p=1;else for(var m=0;m>>0).toString(16);return"00000000".substr(0,8-b.length)+b}function c(a){for(var b=[],c=0;c>>=8;return b}function e(a,b){return a<>>32-b}function f(a,b,c){return a&b|~a&c}function g(a,b,c){return c&a|~c&b}function h(a,b,c){return a^b^c}function i(a,b,c){return b^(a|~c)}function j(a,b){return a[b+3]<<24|a[b+2]<<16|a[b+1]<<8|a[b]}function k(a){for(var b=[],c=0;c=0;i--)h=arguments[i],g=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=255&h,h>>>=8,g<<=8,g|=h,f+=b(g);return f}function m(a){for(var b=new Array(a.length),c=0;c56){for(var k=0;k<64-c;k++)p.push(0);c=p.length%64}for(k=0;k<56-c;k++)p.push(0);p=p.concat(d(8*b));var m=1732584193,o=4023233417,q=2562383102,r=271733878,s=0,t=0,u=0,v=0;for(k=0;k>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\0\0",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b^=-1;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\0",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h; for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;gc;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b&&b,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\0",w+=p||q?"\0\b":"\0\0",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\0"+w+s(o.length,2)+"\0\0\0\0"+(j===!0?"\0\0\0":"\0\0\0\0")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(k(e.uint8array?a.subarray(c,h):a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(a){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4), this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16), this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d!==m||(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n)},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d!==i.Z_FINISH||(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK)},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(a){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(a){g=!1}for(var h=new e.Buf8(256),i=0;256>i;i++)h[i]=i>=252?6:i>=248?5:i>=240?4:i>=224?3:i>=192?2:1;h[254]=h[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,i=b||a.length,j=new Array(2*i);for(e=0,c=0;i>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=h[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&i>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+h[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a^=-1;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d), 0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-ja?a.strstart-(a.w_size-ja):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ia,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ia-(m-f),f=m-ia,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-ja)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=ha)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sa;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sa;if(a.strstart-a.block_start>=a.w_size-ja&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sa:sa}function o(a,b){for(var c,d;;){if(a.lookahead=ha&&(a.ins_h=(a.ins_h<=ha)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-ha),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=ha){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<=ha&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=ha-1)),a.prev_length>=ha&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-ha,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-ha),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<=ha&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ia;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ia-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=ha?(c=D._tr_tally(a,1,a.match_length-ha),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sa:ta}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sa;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sa}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ua:va):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sa:ta}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=ha-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fa),this.dyn_dtree=new C.Buf16(2*(2*da+1)),this.bl_tree=new C.Buf16(2*(2*ea+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(ga+1),this.heap=new C.Buf16(2*ca+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*ca+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?la:qa,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h, i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===ra&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===la)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=ma):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wa),h.status=qa);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=ka),m+=31-m%31,h.status=qa,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===ma)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=na)}else h.status=na;if(h.status===na)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=oa)}else h.status=oa;if(h.status===oa)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pa)}else h.status=pa;if(h.status===pa&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qa)):h.status=qa),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===ra&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==ra){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ua||o===va)&&(h.status=ra),o===sa||o===ua)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===ta&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==la&&b!==ma&&b!==na&&b!==oa&&b!==pa&&b!==qa&&b!==ra?d(a,O):(a.state=null,b===qa?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,aa=29,ba=256,ca=ba+1+aa,da=30,ea=19,fa=2*ca+1,ga=15,ha=3,ia=258,ja=ia+ha+1,ka=32,la=42,ma=69,na=73,oa=91,pa=103,qa=113,ra=666,sa=1,ta=2,ua=3,va=4,wa=3,xa=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xa(0,0,0,0,n),new xa(4,4,8,4,o),new xa(4,5,16,8,o),new xa(4,6,32,32,o),new xa(4,4,16,16,p),new xa(8,16,32,32,p),new xa(8,16,128,128,p),new xa(8,32,128,256,p),new xa(32,128,258,1024,p),new xa(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<q&&(p+=B[f++]<>>=w,q-=w),15>q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<q&&(p+=B[f++]<q&&(p+=B[f++]<k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0, b.bits=0,b.lencode=b.lendyn=new r.Buf32(oa),b.distcode=b.distdyn=new r.Buf32(pa),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,ra)}function k(a){if(sa){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sa=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=la;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=la;break}if(m>>>=4,n-=4,wa=(15&m)+8,0===c.wbits)c.wbits=wa;else if(wa>c.wbits){a.msg="invalid window size",c.mode=la;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Ba[2]=m>>>16&255,Ba[3]=m>>>24&255,c.check=t(c.check,Ba,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Ba[0]=255&m,Ba[1]=m>>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Ba,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wa=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wa)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.name+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wa=e[g+q++],c.head&&wa&&c.length<65536&&(c.head.comment+=String.fromCharCode(wa));while(wa&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wa)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ia;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=ba,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=la}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=la;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=la;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Ca[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,ya={bits:c.lenbits},xa=v(w,c.lens,0,19,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid code lengths set",c.mode=la;break}c.have=0,c.mode=aa;case aa:for(;c.have>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<sa)m>>>=qa,n-=qa,c.lens[c.have++]=sa;else{if(16===sa){for(za=qa+2;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,0===c.have){a.msg="invalid bit length repeat",c.mode=la;break}wa=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sa){for(za=qa+3;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=3+(7&m),m>>>=3,n-=3}else{for(za=qa+7;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=qa,n-=qa,wa=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=la;break}for(;q--;)c.lens[c.have++]=wa}}if(c.mode===la)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=la;break}if(c.lenbits=9,ya={bits:c.lenbits},xa=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,ya),c.lenbits=ya.bits,xa){a.msg="invalid literal/lengths set",c.mode=la;break}if(c.distbits=6,c.distcode=c.distdyn,ya={bits:c.distbits},xa=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,ya),c.distbits=ya.bits,xa){a.msg="invalid distances set",c.mode=la;break}if(c.mode=ba,b===B)break a;case ba:c.mode=ca;case ca:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Aa=c.lencode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,c.length=sa,0===ra){c.mode=ha;break}if(32&ra){c.back=-1,c.mode=V;break}if(64&ra){a.msg="invalid literal/length code",c.mode=la;break}c.extra=15&ra,c.mode=da;case da:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=ea;case ea:for(;Aa=c.distcode[m&(1<>>24,ra=Aa>>>16&255,sa=65535&Aa, !(n>=qa);){if(0===i)break a;i--,m+=e[g++]<>ta)],qa=Aa>>>24,ra=Aa>>>16&255,sa=65535&Aa,!(n>=ta+qa);){if(0===i)break a;i--,m+=e[g++]<>>=ta,n-=ta,c.back+=ta}if(m>>>=qa,n-=qa,c.back+=qa,64&ra){a.msg="invalid distance code",c.mode=la;break}c.offset=sa,c.extra=15&ra,c.mode=fa;case fa:if(c.extra){for(za=c.extra;za>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=la;break}c.mode=ga;case ga:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=la;break}q>c.wnext?(q-=c.wnext,oa=c.wsize-q):oa=c.wnext-q,q>c.length&&(q=c.length),pa=c.window}else pa=f,oa=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pa[oa++];while(--q);0===c.length&&(c.mode=ca);break;case ha:if(0===j)break a;f[h++]=c.length,j--,c.mode=ca;break;case ia:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?ga[a]:ga[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ia[d]=c,a=0;a<1<<_[d];a++)ha[c++]=d;for(ha[c-1]=d,e=0,d=0;16>d;d++)for(ja[d]=e,a=0;a<1<>=7;R>d;d++)for(ja[d]=e<<7,a=0;a<1<=b;b++)f[b]=0;for(a=0;143>=a;)ea[2*a+1]=8,a++,f[8]++;for(;255>=a;)ea[2*a+1]=9,a++,f[9]++;for(;279>=a;)ea[2*a+1]=7,a++,f[7]++;for(;287>=a;)ea[2*a+1]=8,a++,f[8]++;for(l(ea,Q+1,f),a=0;R>a;a++)fa[2*a+1]=5,fa[2*a]=i(a,5);ka=new na(ea,_,P+1,Q,U),la=new na(fa,aa,0,R,U),ma=new na(new Array(0),ba,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c, a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++jj){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*ca[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*ca[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pa||(m(),pa=!0),a.l_desc=new oa(a.dyn_ltree,ka),a.d_desc=new oa(a.dyn_dtree,la),a.bl_desc=new oa(a.bl_tree,ma),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,ea),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,ea,fa)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(ha[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],aa=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],ba=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],ca=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],da=512,ea=new Array(2*(Q+2));d(ea);var fa=new Array(2*R);d(fa);var ga=new Array(da);d(ga);var ha=new Array(N-M+1);d(ha);var ia=new Array(O);d(ia);var ja=new Array(R);d(ja);var ka,la,ma,na=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},oa=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pa=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}),jt.Keys={VK_ESCAPE:{c:27,n:"Esc"},VK_F1:{c:112,n:"F1"},VK_F2:{c:113,n:"F2"},VK_F3:{c:114,n:"F3"},VK_F4:{c:115,n:"F4"},VK_F5:{c:116,n:"F5"},VK_F6:{c:117,n:"F6"},VK_F7:{c:118,n:"F7"},VK_F8:{c:119,n:"F8"},VK_F9:{c:120,n:"F9"},VK_F10:{c:121,n:"F10"},VK_F11:{c:122,n:"F11"},VK_F12:{c:123,n:"F12"},VK_SCROLL_LOCK:{c:145,n:"ScrLck"},VK_PAUSE:{c:19,n:"Pause"},VK_QUOTE:{c:192,n:"'"},VK_TILDE:{c:222,n:"~"},VK_1:{c:49,n:"1"},VK_2:{c:50,n:"2"},VK_3:{c:51,n:"3"},VK_4:{c:52,n:"4"},VK_5:{c:53,n:"5"},VK_6:{c:54,n:"6"},VK_7:{c:55,n:"7"},VK_8:{c:56,n:"8"},VK_9:{c:57,n:"9"},VK_0:{c:48,n:"0"},VK_MINUS:{c:189,n:"-"},VK_MINUS2:{c:173,n:"-"},VK_EQUALS:{c:187,n:"="},VK_EQUALS2:{c:61,n:"="},VK_BACK_SPACE:{c:8,n:"Bkspc"},VK_TAB:{c:9,n:"Tab"},VK_Q:{c:81,n:"Q"},VK_W:{c:87,n:"W"},VK_E:{c:69,n:"E"},VK_R:{c:82,n:"R"},VK_T:{c:84,n:"T"},VK_Y:{c:89,n:"Y"},VK_U:{c:85,n:"U"},VK_I:{c:73,n:"I"},VK_O:{c:79,n:"O"},VK_P:{c:80,n:"P"},VK_ACUTE:{c:219,n:"´"},VK_OPEN_BRACKET:{c:221,n:"["},VK_CLOSE_BRACKET:{c:220,n:"]"},VK_CAPS_LOCK:{c:20,n:"CpsLck"},VK_A:{c:65,n:"A"},VK_S:{c:83,n:"S"},VK_D:{c:68,n:"D"},VK_F:{c:70,n:"F"},VK_G:{c:71,n:"G"},VK_H:{c:72,n:"H"},VK_J:{c:74,n:"J"},VK_K:{c:75,n:"K"},VK_L:{c:76,n:"L"},VK_CEDILLA:{c:186,n:"Ç"},VK_TILDE:{c:222,n:"~"},VK_ENTER:{c:13,n:"Enter"},VK_SHIFT:{c:16,n:"Shift"},VK_BACK_SLASH:{c:226,n:"\\"},VK_Z:{c:90,n:"Z"},VK_X:{c:88,n:"X"},VK_C:{c:67,n:"C"},VK_V:{c:86,n:"V"},VK_B:{c:66,n:"B"},VK_N:{c:78,n:"N"},VK_M:{c:77,n:"M"},VK_COMMA:{c:188,n:"] ="},VK_PERIOD:{c:190,n:"."},VK_SEMICOLON:{c:191,n:";"},VK_SLASH:{c:193,n:"/"},VK_CONTROL:{c:17,n:"Ctrl"},VK_ALT:{c:18,n:"Alt"},VK_SPACE:{c:32,n:"Space"},VK_INSERT:{c:45,n:"Ins"},VK_DELETE:{c:46,n:"Del"},VK_HOME:{c:36,n:"Home"},VK_END:{c:35,n:"End"},VK_PAGE_UP:{c:33,n:"PgUp"},VK_PAGE_DOWN:{c:34,n:"PgDown"},VK_UP:{c:38,n:"Up"},VK_DOWN:{c:40,n:"Down"},VK_LEFT:{c:37,n:"Left"},VK_RIGHT:{c:39,n:"Right"},VK_NUM_LOCK:{c:144,n:"Num"},VK_DIVIDE:{c:111,n:"Num /"},VK_MULTIPLY:{c:106,n:"Num *"},VK_SUBTRACT:{c:109,n:"Num -"},VK_ADD:{c:107,n:"Num +"},VK_DECIMAL:{c:194,n:"Num ."},VK_NUMPAD0:{c:96,n:"Num 0"},VK_NUMPAD1:{c:97,n:"Num 1"},VK_NUMPAD2:{c:98,n:"Num 2"},VK_NUMPAD3:{c:99,n:"Num 3"},VK_NUMPAD4:{c:100,n:"Num 4"},VK_NUMPAD5:{c:101,n:"Num 5"},VK_NUMPAD6:{c:102,n:"Num 6"},VK_NUMPAD7:{c:103,n:"Num 7"},VK_NUMPAD8:{c:104,n:"Num 8"},VK_NUMPAD9:{c:105,n:"Num 9"},VK_NUMPAD_CENTER:{c:12,n:"Num Cntr"}},jt.KeysByCode={};for(var a in jt.Keys)jt.KeysByCode[jt.Keys[a].c]=jt.Keys[a];Javatari.preferences={},Javatari.preferences.defaults={KP0LEFT:jt.Keys.VK_LEFT.c,KP0UP:jt.Keys.VK_UP.c,KP0RIGHT:jt.Keys.VK_RIGHT.c,KP0DOWN:jt.Keys.VK_DOWN.c,KP0BUT:jt.Keys.VK_SPACE.c,KP0BUT2:jt.Keys.VK_DELETE.c,KP1LEFT:jt.Keys.VK_F.c,KP1UP:jt.Keys.VK_T.c,KP1RIGHT:jt.Keys.VK_H.c,KP1DOWN:jt.Keys.VK_G.c,KP1BUT:jt.Keys.VK_A.c,KP1BUT2:jt.Keys.VK_PERIOD.c,JP0DEVICE:-1,JP0XAXIS:0,JP0XAXISSIG:1,JP0YAXIS:1,JP0YAXISSIG:1,JP0PAXIS:0,JP0PAXISSIG:1,JP0BUT:0,JP0BUT2:1,JP0SELECT:8,JP0RESET:9,JP0PAUSE:7,JP0FAST:6,JP0DEADZONE:.3,JP0PCENTER:.3,JP0PSENS:.75,JP1DEVICE:-1,JP1XAXIS:0,JP1XAXISSIG:1,JP1YAXIS:1,JP1YAXISSIG:1,JP1PAXIS:0,JP1PAXISSIG:1,JP1BUT:0,JP1BUT2:1,JP1SELECT:8,JP1RESET:9,JP1PAUSE:7,JP1FAST:6,JP1DEADZONE:.3,JP1PCENTER:.3,JP1PSENS:.75},Javatari.preferences.loadDefaults=function(){for(var a in Javatari.preferences.defaults)Javatari.preferences[a]=Javatari.preferences.defaults[a]},Javatari.preferences.load=function(){try{Javatari.preferences.loadDefaults();var a=JSON.parse(localStorage.javatariprefs||"{}");for(var b in Javatari.preferences.defaults)a[b]&&(Javatari.preferences[b]=a[b])}catch(a){}},Javatari.preferences.save=function(){try{localStorage.javatariprefs=JSON.stringify(Javatari.preferences)}catch(a){}},jt.GamepadConsoleControls=function(a){function b(a,b){this.index=a,this.update=function(b){return c=b[a],!!c},this.hasMoved=function(){var a=c.timestamp;return!a||a>m&&(m=a,!0)},this.getButtonDigital=function(a){var b=c.buttons[a];return"object"==typeof b?b.pressed||b.value>.5:b>.5},this.getDPadDirection=function(){return this.getButtonDigital(12)?this.getButtonDigital(15)?1:this.getButtonDigital(14)?7:0:this.getButtonDigital(13)?this.getButtonDigital(15)?3:this.getButtonDigital(14)?5:4:this.getButtonDigital(14)?6:this.getButtonDigital(15)?2:-1; },this.getStickDirection=function(){var a=c.axes[d],b=c.axes[e];if((a<0?-a:a)=1&&(i-=1),8*i|0},this.getPaddlePosition=function(){var a=c.axes[i]*j*k+l|0;return a<0?a=0:a>380&&(a=380),a};var c,d=b.xAxis,e=b.yAxis,f=b.xAxisSig,g=b.yAxisSig,h=b.deadzone,i=b.paddleAxis,j=b.paddleAxisSig,k=b.paddleSens,l=b.paddleCenter,m=Number.MIN_VALUE}this.connect=function(a){i=a},this.connectScreen=function(a){j=a},this.powerOn=function(){q=!!navigator.getGamepads,q&&(this.applyPreferences(),e())},this.powerOff=function(){q=!1},this.toggleMode=function(){q&&(e(),u=!u,j.getMonitor().showOSD("Gamepad input "+(u?"Swapped":"Normal"),!0))},this.setPaddleMode=function(a){q&&(t=a,m.xPosition=n.xPosition=-1)},this.setP1ControlsMode=function(a){v=a},this.clockPulse=function(){if(q&&(++r>=60&&(r=0),k||l||0===r)){var a=navigator.getGamepads();k?k.update(a)?k.hasMoved()&&f(k,m,o,!u):(k=null,c(!0,!1)):0===r&&(k=d(o,p,a),k&&c(!0,!0)),l?l.update(a)?l.hasMoved()&&f(l,n,p,u):(l=null,c(!1,!1)):0===r&&(l=d(p,o,a),l&&c(!1,!0))}};var c=function(a,b){j.getMonitor().showOSD((a^v^u?"P1":"P2")+" Gamepad "+(b?"connected":"disconnected"),a)},d=function(a,c,d){if(d&&0!==d.length){if(a.device>=0)return d[a.device]?new b(a.device,a):null;for(var e=0,f=d.length;e=0)){var b=1===a.rom.info.p;q!==b&&e(b,!1)}},this.clockPulse=function(){n.clockPulse(),q&&(u?t||(r-=s,r<0&&(r=0),k.controlValueChanged(o.PADDLE0_POSITION,r)):t&&(r+=s,r>380&&(r=380),k.controlValueChanged(o.PADDLE0_POSITION,r)),y?x||(v-=w,v<0&&(v=0),k.controlValueChanged(o.PADDLE1_POSITION,v)):x&&(v+=w,v>380&&(v=380),k.controlValueChanged(o.PADDLE1_POSITION,v)))},this.processKeyEvent=function(a,b,c){if(f(a,c,b))return!0;var d=g(a,c);if(null==d)return!1;q&&(d=h(d));var e=D[d];return e&&e===b||(D[d]=b,k.controlStateChanged(d,b)),!0};var c=this.processKeyEvent,d=function(){m.showOSD("Controllers: "+(q?"Paddles":"Joysticks")+(p?", Swapped":""),!0)},e=function(a,b){q=a,t=u=x=y=!1,s=w=2,r=v=q?190:-1;for(var c=0;c1&&s--,m.showOSD("P1 Paddle speed: "+s,!0),!0;case o.JOY1_LEFT:return x=!0,!0;case o.JOY1_RIGHT:return y=!0,!0;case o.JOY1_UP:return w<10&&w++,m.showOSD("P2 Paddle speed: "+w,!0),!0;case o.JOY1_DOWN:return w>1&&w--,m.showOSD("P2 Paddle speed: "+w,!0),!0}}}else if(q){if(e=g(a,c),null==e)return!1;switch(e){case o.JOY0_LEFT:return t=!1,!0;case o.JOY0_RIGHT:return u=!1,!0;case o.JOY1_LEFT:return x=!1,!0;case o.JOY1_RIGHT:return y=!1,!0}}return!1},g=function(a,b){switch(b){case 0:var c=z[a];return c?c:A[a];case pa:return B[a];case qa:return C[a]}return null},h=function(a){switch(a){case o.JOY0_BUTTON:return o.PADDLE0_BUTTON; case o.JOY1_BUTTON:return o.PADDLE1_BUTTON}return a},i=function(){window.onhelp=function(){return!1}},j=function(){b.applyPreferences(),A[O]=o.POWER,A[P]=o.BLACK_WHITE,A[Q]=o.DIFFICULTY0,A[oa]=o.CARTRIDGE_REMOVE,A[la]=o.SAVE_STATE_FILE,A[R]=o.DIFFICULTY1,A[J]=o.SELECT,A[K]=o.SELECT,A[L]=o.RESET,C[O]=o.POWER,C[P]=o.BLACK_WHITE,C[Q]=o.DIFFICULTY0,C[oa]=o.CARTRIDGE_REMOVE,C[la]=o.SAVE_STATE_FILE,C[R]=o.DIFFICULTY1,C[J]=o.SELECT,C[K]=o.SELECT,C[L]=o.RESET,A[M]=o.FAST_SPEED,C[N]=o.PAUSE,C[S]=o.FRAME,C[T]=o.TRACE,C[U]=o.DEBUG,C[V]=o.NO_COLLISIONS,C[W]=o.VIDEO_STANDARD,B[N]=o.PAUSE,B[S]=o.FRAME,B[T]=o.TRACE,B[U]=o.DEBUG,B[V]=o.NO_COLLISIONS,B[W]=o.VIDEO_STANDARD,B[O]=o.POWER_FRY,B[X]=o.SAVE_STATE_0,B[Y]=o.SAVE_STATE_0,B[Z]=o.SAVE_STATE_1,B[$]=o.SAVE_STATE_2,B[_]=o.SAVE_STATE_3,B[aa]=o.SAVE_STATE_4,B[ba]=o.SAVE_STATE_5,B[ca]=o.SAVE_STATE_6,B[da]=o.SAVE_STATE_7,B[ea]=o.SAVE_STATE_8,B[fa]=o.SAVE_STATE_9,B[ga]=o.SAVE_STATE_10,B[ha]=o.SAVE_STATE_11,B[ia]=o.SAVE_STATE_11,B[ja]=o.SAVE_STATE_12,B[ka]=o.SAVE_STATE_12,C[X]=o.LOAD_STATE_0,C[Y]=o.LOAD_STATE_0,C[Z]=o.LOAD_STATE_1,C[$]=o.LOAD_STATE_2,C[_]=o.LOAD_STATE_3,C[aa]=o.LOAD_STATE_4,C[ba]=o.LOAD_STATE_5,C[ca]=o.LOAD_STATE_6,C[da]=o.LOAD_STATE_7,C[ea]=o.LOAD_STATE_8,C[fa]=o.LOAD_STATE_9,C[ga]=o.LOAD_STATE_10,C[ha]=o.LOAD_STATE_11,C[ia]=o.LOAD_STATE_11,C[ja]=o.LOAD_STATE_12,C[ka]=o.LOAD_STATE_12,C[I]=o.CARTRIDGE_FORMAT,C[ma]=o.CARTRIDGE_CLOCK_DEC,C[na]=o.CARTRIDGE_CLOCK_INC,B[I]=o.CARTRIDGE_FORMAT,B[ma]=o.CARTRIDGE_CLOCK_DEC,B[na]=o.CARTRIDGE_CLOCK_INC};this.applyPreferences=function(){z={},p?(z[Javatari.preferences.KP0LEFT]=o.JOY1_LEFT,z[Javatari.preferences.KP0UP]=o.JOY1_UP,z[Javatari.preferences.KP0RIGHT]=o.JOY1_RIGHT,z[Javatari.preferences.KP0DOWN]=o.JOY1_DOWN,z[Javatari.preferences.KP0BUT]=o.JOY1_BUTTON,z[Javatari.preferences.KP0BUT2]=o.JOY1_BUTTON,z[Javatari.preferences.KP1LEFT]=o.JOY0_LEFT,z[Javatari.preferences.KP1UP]=o.JOY0_UP,z[Javatari.preferences.KP1RIGHT]=o.JOY0_RIGHT,z[Javatari.preferences.KP1DOWN]=o.JOY0_DOWN,z[Javatari.preferences.KP1BUT]=o.JOY0_BUTTON,z[Javatari.preferences.KP1BUT2]=o.JOY0_BUTTON):(z[Javatari.preferences.KP0LEFT]=o.JOY0_LEFT,z[Javatari.preferences.KP0UP]=o.JOY0_UP,z[Javatari.preferences.KP0RIGHT]=o.JOY0_RIGHT,z[Javatari.preferences.KP0DOWN]=o.JOY0_DOWN,z[Javatari.preferences.KP0BUT]=o.JOY0_BUTTON,z[Javatari.preferences.KP0BUT2]=o.JOY0_BUTTON,z[Javatari.preferences.KP1LEFT]=o.JOY1_LEFT,z[Javatari.preferences.KP1UP]=o.JOY1_UP,z[Javatari.preferences.KP1RIGHT]=o.JOY1_RIGHT,z[Javatari.preferences.KP1DOWN]=o.JOY1_DOWN,z[Javatari.preferences.KP1BUT]=o.JOY1_BUTTON,z[Javatari.preferences.KP1BUT2]=o.JOY1_BUTTON)};var k,l,m,n,o=jt.ConsoleControls,p=!1,q=!1,r=0,s=3,t=!1,u=!1,v=0,w=3,x=!1,y=!1,z={},A={},B={},C={},D={},E=Javatari.PADDLES_MODE,F=jt.DOMConsoleControls.KEY_TOGGLE_JOYSTICK,G=jt.DOMConsoleControls.KEY_TOGGLE_P1_MODE,H=jt.DOMConsoleControls.KEY_TOGGLE_PADDLE,I=jt.DOMConsoleControls.KEY_CARTRIDGE_FORMAT,J=jt.DOMConsoleControls.KEY_SELECT,K=jt.DOMConsoleControls.KEY_SELECT2,L=jt.DOMConsoleControls.KEY_RESET,M=jt.DOMConsoleControls.KEY_FAST_SPEED,N=jt.DOMConsoleControls.KEY_PAUSE,O=jt.Keys.VK_F1.c,P=jt.Keys.VK_F2.c,Q=jt.Keys.VK_F4.c,R=jt.Keys.VK_F9.c,S=jt.Keys.VK_F.c,T=jt.Keys.VK_Q.c,U=jt.Keys.VK_D.c,V=jt.Keys.VK_C.c,W=jt.Keys.VK_V.c,X=jt.Keys.VK_QUOTE.c,Y=jt.Keys.VK_TILDE.c,Z=jt.Keys.VK_1.c,$=jt.Keys.VK_2.c,_=jt.Keys.VK_3.c,aa=jt.Keys.VK_4.c,ba=jt.Keys.VK_5.c,ca=jt.Keys.VK_6.c,da=jt.Keys.VK_7.c,ea=jt.Keys.VK_8.c,fa=jt.Keys.VK_9.c,ga=jt.Keys.VK_0.c,ha=jt.Keys.VK_MINUS.c,ia=jt.Keys.VK_MINUS2.c,ja=jt.Keys.VK_EQUALS.c,ka=jt.Keys.VK_EQUALS2.c,la=jt.Keys.VK_F8.c,ma=jt.Keys.VK_END.c,na=jt.Keys.VK_HOME.c,oa=jt.Keys.VK_F7.c,pa=1,qa=jt.DOMConsoleControls.KEY_ALT_MASK,ra=4;a()},jt.DOMConsoleControls.KEY_SELECT=jt.Keys.VK_F11.c,jt.DOMConsoleControls.KEY_SELECT2=jt.Keys.VK_F10.c,jt.DOMConsoleControls.KEY_RESET=jt.Keys.VK_F12.c,jt.DOMConsoleControls.KEY_FAST_SPEED=jt.Keys.VK_TAB.c,jt.DOMConsoleControls.KEY_PAUSE=jt.Keys.VK_P.c,jt.DOMConsoleControls.KEY_TOGGLE_JOYSTICK=jt.Keys.VK_J.c,jt.DOMConsoleControls.KEY_TOGGLE_P1_MODE=jt.Keys.VK_K.c,jt.DOMConsoleControls.KEY_TOGGLE_PADDLE=jt.Keys.VK_L.c,jt.DOMConsoleControls.KEY_CARTRIDGE_FORMAT=jt.Keys.VK_B.c,jt.DOMConsoleControls.KEY_ALT_MASK=2,jt.DOMMonitorControls=function(a){function b(){e()}this.addInputElements=function(a){for(var b=0;b=P&&V=0||0!==ma&&1!==ma||t(a?a.rom.info.c||0:0)};var b=function(){return!(VK+ia+ja&&b()},d=function(a){return a?(X=!0,h()):(X=!1,i()),a},e=function(a){I=a,J=a.width,K=a.height,l(L,N),k(O,Q)},f=function(){var a=Y;Y=0,(a>=250&&a<=281||a>=300&&a<=325)&&++U>=5&&g(a)},g=function(a){T=a<290?jt.VideoStandard.NTSC:jt.VideoStandard.PAL;var b=Z,c=a-T.height;c=c>2?(c>6?6:c)-2:0,c!=b&&(Z=c,e(T))},h=function(){I!=B.standard&&e(B.standard)},i=function(){V=0,z.adjustToVideoSignalOff()},j=function(){if(l(da,ea),k(ba,ca),null!=z){var a=z.displayDefaultOpeningScaleX(L,M);n(a,a/ga)}else n(fa,ha);p()},k=function(a,b){O=a,O<0?O=0:O>J-L&&(O=J-L),Q=b,Q<0?Q=0:Q/100*K>K-M&&(Q=(K-M)/K*100);var c=Z/2;P=Q/100*K+c|0,P+M>K&&(P=K-M)},l=function(a,b){L=a,L<10?L=10:L>J&&(L=J),N=b,N<10?N=10:N>100&&(N=100),M=N/100*(K+Z)|0,M>K&&(M=K),k(O,Q),m()},m=function(){z&&(z.displaySize(L*R|0,M*S|0),z.displayMinimumSize(L*fa/ha|0,M))},n=function(a,b){R=a,R<1&&(R=1),S=b,S<1&&(S=1),m()},o=function(a){var b=0|a;b<1&&(b=1),n(b*ga,b); },p=function(){z&&z.displayCenter()},q=function(){X&&(E.putImageData(F,0,0),z.refresh(D,L,M),$>0&&w())},r=function(){z.displayToggleFullscreen()},s=function(){return z.showOSD("Not yet supported!",!0)},t=function(a){var b=a>4||a<0?0:a;ma!==b&&(ma=b,z.showOSD("CRT mode: "+la[ma],!0))},u=function(){z.exit()},v=function(){D=document.createElement("canvas"),D.width=jt.VideoStandard.PAL.width,D.height=jt.VideoStandard.PAL.height,E=D.getContext("2d"),F=E.getImageData(0,0,D.width,D.height),F.data.buffer?G=new Uint32Array(F.data.buffer):H=F.data},w=function(){G&&jt.Util.arrayFill(G,4278255360)},x=function(){return!!Javatari.CARTRIDGE_CHANGE_DISABLED&&(z.showOSD("Cartridge change is disabled",!0),!0)},y=jt.Monitor.Controls;this.controlActivated=function(a){switch(a){case y.LOAD_CARTRIDGE_FILE:x()||A.openFileChooserDialog(!0);break;case y.LOAD_CARTRIDGE_FILE_NO_AUTO_POWER:x()||A.openFileChooserDialog(!1);break;case y.LOAD_CARTRIDGE_URL:x()||A.openURLChooserDialog(!0);break;case y.LOAD_CARTRIDGE_URL_NO_AUTO_POWER:x()||A.openURLChooserDialog(!1);break;case y.CRT_MODES:s();break;case y.CRT_FILTER:z.toggleCRTFilter();break;case y.STATS:_=!_,z.showOSD(null,!0);break;case y.DEBUG:$++,$>4&&($=0);break;case y.ORIGIN_X_MINUS:k(O+1,Q);break;case y.ORIGIN_X_PLUS:k(O-1,Q);break;case y.ORIGIN_Y_MINUS:k(O,Q+.5);break;case y.ORIGIN_Y_PLUS:k(O,Q-.5);break;case y.SIZE_DEFAULT:j();break;case y.FULLSCREEN:r();break;case y.EXIT:u()}if(!aa)switch(a){case y.WIDTH_MINUS:l(L-1,N);break;case y.WIDTH_PLUS:l(L+1,N);break;case y.HEIGHT_MINUS:l(L,N-.5);break;case y.HEIGHT_PLUS:l(L,N+.5);break;case y.SCALE_X_MINUS:n(R-.5,S);break;case y.SCALE_X_PLUS:n(R+.5,S);break;case y.SCALE_Y_MINUS:n(R,S-.5);break;case y.SCALE_Y_PLUS:n(R,S+.5);break;case y.SIZE_MINUS:o(S-1);break;case y.SIZE_PLUS:o(S+1)}};var z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V=0,W=0,X=!1,Y=0,Z=0,$=0,_=!1,aa=Javatari.SCREEN_RESIZE_DISABLED,ba=68,ca=12.4,da=160,ea=81.5,fa=4,ga=2,ha=2,ia=16,ja=5,ka=0,la=["OFF","Phosphor","Phosphor Scanlines","RGB","RGB Phosphor"],ma=ka<0?0:ka;a(this)},jt.Monitor.Controls={WIDTH_PLUS:1,HEIGHT_PLUS:2,WIDTH_MINUS:3,HEIGHT_MINUS:4,ORIGIN_X_PLUS:5,ORIGIN_Y_PLUS:6,ORIGIN_X_MINUS:7,ORIGIN_Y_MINUS:8,SCALE_X_PLUS:9,SCALE_Y_PLUS:10,SCALE_X_MINUS:11,SCALE_Y_MINUS:12,SIZE_PLUS:13,SIZE_MINUS:14,SIZE_DEFAULT:15,FULLSCREEN:16,LOAD_CARTRIDGE_FILE:21,LOAD_CARTRIDGE_FILE_NO_AUTO_POWER:22,LOAD_CARTRIDGE_URL:23,LOAD_CARTRIDGE_URL_NO_AUTO_POWER:24,LOAD_CARTRIDGE_PASTE:25,CRT_FILTER:31,CRT_MODES:32,DEBUG:41,STATS:42,EXIT:51},jt.CanvasDisplay=function(a){function b(a){J(),C(),I(),D(),H(),i=h.getContext("2d"),c=new jt.Monitor,c.connectDisplay(a),c.addControlInputElements(a.keyControlsInputElements())}this.connectPeripherals=function(b,d){b.registerForDnD(a),b.registerForFileInputElement(a),d.registerForDownloadElement(a),c.connectPeripherals(b)},this.connect=function(a,b,e){c.connect(a,e),d=b},this.powerOn=function(){a.style.visibility="visible",this.focus(),B()},this.powerOff=function(){a.style.visibility="hidden",a.style.display="none"},this.refresh=function(a,b,c){L=!0,i.drawImage(a,0,0,b,c,0,0,h.width,h.height)},this.adjustToVideoSignalOff=function(){L=!1,B()},this.keyControlsInputElements=function(){return[a]},this.displayDefaultOpeningScaleX=function(a,b){if(N){var c=g.clientWidth,d=g.clientHeight,e=c/a;e-=e%Q;for(var f=e/Q*b;f>d+35;)e-=Q,f=e/Q*b;return 0|e}return R},this.displaySize=function(a,b){z(a,b),A(),L||B()},this.displayMinimumSize=function(a,b){},this.displayCenter=function(){this.focus()},this.getMonitor=function(){return c},this.showOSD=function(a,b){return m&&clearTimeout(m),a?(!b&&K||(l.innerHTML=a),l.style.transition="none",l.style.top="15px",l.style.opacity=1,K=!0,void(m=setTimeout(function(){l.style.transition="all 0.15s linear",l.style.top="-29px",l.style.opacity=0,K=!1},P))):(l.style.transition="all 0.15s linear",l.style.top="-29px",l.style.opacity=0,void(K=!1))},this.toggleCRTFilter=function(){M=!M,this.showOSD(M?"CRT Filter: ON":"CRT Filter: OFF",!0),A()},this.displayToggleFullscreen=function(){Javatari.SCREEN_FULLSCREEN_DISABLED||(document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement?document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen?document.webkitExitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.msExitFullscreen&&document.msExitFullscreen():g.requestFullscreen?g.requestFullscreen():g.webkitRequestFullscreen?g.webkitRequestFullscreen():g.webkitRequestFullScreen?g.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):g.mozRequestFullScreen?g.mozRequestFullScreen():g.msRequestFullscreen?g.msRequestFullscreen():this.showOSD("Fullscreen is not supported by your browser!"))},this.exit=function(){d.controlStateChanged(jt.ConsoleControls.POWER_OFF,!0),c.controlActivated(jt.Monitor.Controls.SIZE_DEFAULT)},this.focus=function(){h.focus()};var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=function(a){e||(e=new jt.Settings),e.show(a)},y=function(){var a=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;N=!!a,c.controlActivated(jt.Monitor.Controls.SIZE_DEFAULT),N&&setTimeout(function(){c.controlActivated(jt.Monitor.Controls.SIZE_DEFAULT)},120)},z=function(b,c){h.width=b,h.height=c,h.style.width=""+b+"px",h.style.height=""+c+"px",N||(f.style.width=""+b+"px",f.style.height=""+c+"px",b+=2*v,c+=u+w,a.style.width=""+b+"px",a.style.height=""+c+"px")},A=function(){void 0!==i.imageSmoothingEnabled?i.imageSmoothingEnabled=M:(i.webkitImageSmoothingEnabled=M,i.mozImageSmoothingEnabled=M,i.msImageSmoothingEnabled=M)},B=function(){if(i.fillStyle="black",i.fillRect(0,0,h.width,h.height),n.isLoaded){var a=n.width,b=n.height;if(b>.7*h.height){var c=.7*h.height/b;b=b*c|0,a=a*c|0}i.drawImage(n,(h.width-a)/2|0,(h.height-b)/2|0,a,b)}},C=function(){a.style.position="relative",a.style.overflow="hidden",a.style.outline="none",a.tabIndex="-1",f=document.createElement("div"),f.style.position="relative",f.style.overflow="hidden",f.style.background="black",f.style.border="0 solid black",f.style.borderWidth=""+u+"px "+v+"px "+w+"px",2===Javatari.SCREEN_CONTROL_BAR&&(f.style.borderImage="url("+O+"screenborder.png) "+u+" "+v+" "+w+" repeat stretch"),g=document.createElement("div"),g.style.position="relative",g.style.width="100%",g.style.height="100%",g.style.overflow="hidden",g.style.background="black",document.addEventListener("fullscreenchange",y),document.addEventListener("webkitfullscreenchange",y),document.addEventListener("mozfullscreenchange",y),document.addEventListener("msfullscreenchange",y),f.appendChild(g),h=document.createElement("canvas"),h.style.position="absolute",h.style.display="block",h.style.left=h.style.right=0,h.style.top=h.style.bottom=0,h.style.margin="auto",h.tabIndex="-1",h.style.outline="none",g.appendChild(h),z(jt.CanvasDisplay.DEFAULT_STARTING_WIDTH,jt.CanvasDisplay.DEFAULT_STARTING_HEIGHT),a.appendChild(f)},D=function(){j=document.createElement("div"),j.style.position="absolute",j.style.left="0",j.style.right="0",j.style.height="29px",2===Javatari.SCREEN_CONTROL_BAR?j.style.bottom="0":1===Javatari.SCREEN_CONTROL_BAR?(j.style.bottom="-30px",j.style.background="rgba(47, 47, 43, .8)",j.style.transition="bottom 0.3s ease-in-out",a.addEventListener("mouseover",function(){k&&clearTimeout(k),j.style.bottom="0px"}),a.addEventListener("mouseleave",function(){k=setTimeout(function(){j.style.bottom="-30px"},1e3)})):(j.style.bottom="0",j.style.background="rgb(44, 44, 40)",j.style.border="1px solid black"),o=E(6,-26,24,23,-436,-208),G(o,jt.ConsoleControls.POWER);var b=23;Javatari.SCREEN_FULLSCREEN_DISABLED||(s=E(-53,-26,24,22,-387,-209),F(s,jt.Monitor.Controls.FULLSCREEN),b=0),Javatari.SCREEN_RESIZE_DISABLED||(q=E(-92+b,-26,18,22,-342,-209),F(q,jt.Monitor.Controls.SIZE_MINUS),r=E(-74+b,-26,21,22,-364,-209),F(r,jt.Monitor.Controls.SIZE_PLUS)), t=E(-29,-26,24,22,-412,-209),t.style.cursor="pointer",t.addEventListener("mousedown",function(a){a.preventDefault&&a.preventDefault(),x()}),p=E("CENTER",-26,24,24,-388,-181),p.style.cursor="pointer",p.addEventListener("mousedown",function(a){a.preventDefault&&a.preventDefault(),x("ABOUT")}),a.appendChild(j)},E=function(a,b,c,d,e,f,g){var h=document.createElement("div");return h.style.position="absolute","CENTER"===a?(h.style.left=h.style.right=0,h.style.margin="0 auto"):a>0?h.style.left=""+a+"px":h.style.right=""+(-c-a)+"px",b>0?h.style.top=""+b+"px":h.style.bottom=""+(-d-b)+"px",h.style.width=""+c+"px",h.style.height=""+d+"px",h.style.outline="none",g||(h.style.backgroundImage="url("+O+"sprites.png)",h.style.backgroundPosition=""+e+"px "+f+"px",h.style.backgroundRepeat="no-repeat"),j.appendChild(h),h},F=function(a,b){a.style.cursor="pointer",a.addEventListener("mousedown",function(a){a.preventDefault&&a.preventDefault(),c.controlActivated(b)})},G=function(a,b){a.style.cursor="pointer",a.addEventListener("mousedown",function(a){a.preventDefault&&a.preventDefault(),d.controlStateChanged(b,!0)})},H=function(){n=new Image,n.isLoaded=!1,n.onload=function(){n.isLoaded=!0,B()},n.src=O+"logo.png"},I=function(){l=document.createElement("div"),l.style.position="absolute",l.style.overflow="hidden",l.style.top="-29px",l.style.right="18px",l.style.height="29px",l.style.padding="0 12px",l.style.margin="0",l.style.font="bold 15px/29px sans-serif",l.style.color="rgb(0, 255, 0)",l.style.background="rgba(0, 0, 0, 0.4)",l.style.opacity=0,l.innerHTML="",g.appendChild(l)},J=function(){2===Javatari.SCREEN_CONTROL_BAR?(u=5,v=5,w=31):1===Javatari.SCREEN_CONTROL_BAR?(u=1,v=1,w=1):(u=1,v=1,w=30)},K=!1,L=!1,M=!1,N=!1,O=Javatari.IMAGES_PATH,P=2500,Q=2,R=2*(Javatari.SCREEN_OPENING_SIZE||2);b(this)},jt.CanvasDisplay.DEFAULT_STARTING_WIDTH=640,jt.CanvasDisplay.DEFAULT_STARTING_HEIGHT=426,jt.ConsolePanel=function(a){function b(){f(),g(),l()}this.connectPeripherals=function(b,c){n=b,n.getMonitor().addControlInputElements(this.keyControlsInputElements()),c.registerForDnD(a)},this.connect=function(a,b){o=a,o.addForwardedInput(this),o.addRedefinitionListener(this),p=b,p.addInsertionListener(this)},this.powerOn=function(){a.style.visibility="visible",c(),d()},this.powerOff=function(){a.style.visibility="hidden",a.style.display="none"},this.keyControlsInputElements=function(){return[a]};var c=function(){k(r,!C[m.POWER]),k(s,C[m.BLACK_WHITE]),k(t,C[m.SELECT]),k(u,C[m.RESET]),k(v,C[m.DIFFICULTY0]),k(w,C[m.DIFFICULTY1]),d()},d=function(){if(k(x,q),k(B,q),B.innerHTML=q&&q.rom.info.l||F,q&&q.rom.info.lc){var a=q.rom.info.lc.trim().split(/\s+/);B.style.color=a[0]||G,B.style.background=a[1]||H,B.style.borderColor=a[2]||I}else B.style.color=G,B.style.background=H,B.style.borderColor=I},e=function(){o.controlsStateReport(C),c()},f=function(){a.style.position="relative",a.style.width=""+jt.ConsolePanel.DEFAULT_WIDTH+"px",a.style.height=""+jt.ConsolePanel.DEFAULT_HEIGHT+"px",a.style.background="black url("+E+"sprites.png) no-repeat",a.style.outline="none",a.tabIndex="-1"},g=function(){r=h(31,-85,25,47,2,-141),i(r,m.POWER,!1),s=h(95,-85,25,47,-22,-141),i(s,m.BLACK_WHITE,!1),t=h(351,-85,25,47,-46,-141),i(t,m.SELECT,!0),u=h(414,-85,25,47,-70,-141),i(u,m.RESET,!0),v=h(162,-133,33,22,-94,-157),i(v,m.DIFFICULTY0,!1),w=h(275,-133,33,22,-94,-137),i(w,m.DIFFICULTY1,!1),x=h(141,-94,189,82,-127,-139),y=h(143,-93,184,55,0,0,!0),j(y,jt.Monitor.Controls.LOAD_CARTRIDGE_FILE),Javatari.CARTRIDGE_CHANGE_DISABLED||(z=h(171,-35,31,30,2,-188),j(z,jt.Monitor.Controls.LOAD_CARTRIDGE_FILE),k(z,!0),A=h(267,-35,31,30,-94,-188),j(A,jt.Monitor.Controls.LOAD_CARTRIDGE_URL),k(A,!0))},h=function(b,c,d,e,f,g,h){var i=document.createElement("div");return i.style.opacity=0,i.style.position="absolute",b>0?i.style.left=""+b+"px":i.style.right=""+(-d-b)+"px",c>0?i.style.top=""+c+"px":i.style.bottom=""+(-e-c)+"px",i.style.width=""+d+"px",i.style.height=""+e+"px",i.style.outline="none",h||(i.style.backgroundImage="url("+E+"sprites.png)",i.style.backgroundPosition=""+f+"px "+g+"px",i.style.backgroundRepeat="no-repeat"),a.appendChild(i),i},i=function(a,b,c){if(b){a.style.cursor="pointer";var d;a.addEventListener("mousedown",function(a){a.preventDefault&&a.preventDefault(),d=!0,o.controlStateChanged(b,!0)}),c&&(a.addEventListener("mouseup",function(a){a.preventDefault&&a.preventDefault(),d=!1,o.controlStateChanged(b,!1)}),a.addEventListener("mouseleave",function(a){a.preventDefault&&a.preventDefault(),d&&(d=!1,o.controlStateChanged(b,!1))}))}},j=function(a,b){a.style.cursor="pointer",a.addEventListener("click",function(a){a.preventDefault&&a.preventDefault(),n.getMonitor().controlActivated(b)})},k=function(a,b){a.style.opacity=b?1:0},l=function(){var b=(Javatari.CARTRIDGE_LABEL_COLORS||"").trim().split(/\s+/);b[0]&&(G=b[0]),b[1]&&(H=b[1]),b[2]&&(I=b[2]),B=document.createElement("div"),B.style.position="absolute",B.style.overflow="hidden",B.style.textOverflow="ellipsis",B.style.whiteSpace="nowrap",B.style.top="52px",B.style.left="158px",B.style.width="148px",B.style.height="25px",B.style.padding="0 2px",B.style.margin="0",B.style.font="bold 14px/25px sans-serif",B.style.textAlign="center",B.style.color=G,B.style.background=H,B.style.border="1px solid "+I,B.style.opacity="0",B.innerHTML="",j(B,jt.Monitor.Controls.LOAD_CARTRIDGE_FILE),a.appendChild(B)},m=jt.ConsoleControls;this.controlStateChanged=function(a,b){D[a]&&e()},this.controlValueChanged=function(a,b){},this.controlsStateReport=function(a){},this.controlsStatesRedefined=function(){e()},this.cartridgeInserted=function(a){q=a,d()};var n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C={},D={};D[m.POWER]=1,D[m.BLACK_WHITE]=1,D[m.SELECT]=1,D[m.RESET]=1,D[m.DIFFICULTY0]=1,D[m.DIFFICULTY1]=1;var E=Javatari.IMAGES_PATH,F="JAVATARI.js",G="#fa2525",H="#101010",I="transparent";b()},jt.ConsolePanel.DEFAULT_WIDTH=465,jt.ConsolePanel.DEFAULT_HEIGHT=137,jt.WebAudioSpeaker=function(){this.connect=function(b){a=b,a.connectMonitor(this)},this.powerOn=function(){e(),c&&(d=c.createScriptProcessor(Javatari.AUDIO_BUFFER_SIZE,0,1),d.onaudioprocess=f,this.play())},this.powerOff=function(){this.mute(),c=void 0},this.play=function(){d&&d.connect(c.destination)},this.mute=function(){d&&d.disconnect()};var a,b,c,d,e=function(){try{var a=window.AudioContext||window.webkitAudioContext||window.WebkitAudioContext;if(!a)throw new Error("WebAudio API not supported by the browser");c=new a,b=jt.TiaAudioSignal.SAMPLE_RATE/c.sampleRate,jt.Util.log("Speaker AudioContext created. Sample rate: "+c.sampleRate)}catch(a){jt.Util.log("Could not create AudioContext. Audio disabled.\n"+a.message)}},f=function(c){if(a){var d=c.outputBuffer.getChannelData(0),e=a.retrieveSamples((d.length*b|0)+1);jt.Util.arrayCopyCircularSourceWithStep(e.buffer,e.start,e.bufferSize,b,d,0,d.length)}}},jt.LocalStorageSaveStateMedia=function(){this.connect=function(a){a.connectMedia(this)},this.registerForDownloadElement=function(a){b=a},this.saveState=function(a,b){var d=e(b);return d&&c("save"+a,d)},this.loadState=function(a){var b=d("save"+a);return f(b)},this.saveStateFile=function(a,b){var c=e(b);return c&&g(a||"JavatariSave",c)},this.loadStateFile=function(a){return f(a)},this.saveResourceToFile=function(a,b){try{var d=b&&JSON.stringify(b);return c(a,d)}catch(a){}},this.loadResourceFromFile=function(a){try{var b=d(a);return b&&JSON.parse(b)}catch(a){}};var a,b,c=function(a,b){try{return localStorage["javatari"+a]=b,!0}catch(a){return!1}},d=function(a){try{return localStorage["javatari"+a]}catch(a){}},e=function(a){try{return i+JSON.stringify(a)}catch(a){}},f=function(a){try{var b;if(b=a instanceof Array?jt.Util.uInt8ArrayToByteString(a.slice(0,i.length)):a.substr(0,i.length),b!==i)return;var c=a.slice(i.length);return c instanceof Array&&(c=jt.Util.uInt8ArrayToByteString(c)),c&&JSON.parse(c)}catch(a){}},g=function(b,c){a||h(),a.href&&(window.URL||window.webkitURL).revokeObjectURL(a.href), b&&(b+=j);var d=new Blob([c],{type:"data:application/octet-stream"});return a.download=b.trim(),a.href=(window.URL||window.webkitURL).createObjectURL(d),a.click(),!0},h=function(){a=document.createElement("a"),a.style.display="none",a.href="#",b.appendChild(a)},i="javatarijsstate!",j=".jst"},jt.ROMLoader=function(){var a=this;this.connect=function(a,d){b=a,c=d},this.registerForDnD=function(a){a.addEventListener("dragover",g,!1),a.addEventListener("drop",h,!1)},this.registerForFileInputElement=function(a){e=a},this.openFileChooserDialog=function(a){d||k(),l=a!==!1,d.click()},this.openURLChooserDialog=function(a){l=a!==!1;var b;try{b=localStorage&&localStorage[o]}catch(a){}if(b=prompt("Load ROM from URL:",b||""),b&&(b=b.toString().trim())){try{localStorage[o]=b}catch(a){}this.loadFromURL(b)}},this.loadFromFile=function(a){jt.Util.log("Reading ROM file: "+a.name);var b=new FileReader;b.onload=function(b){var c=new Uint8Array(b.target.result);i(a.name,c)},b.onerror=function(a){j("File reading error: "+a.target.error.name)},b.readAsArrayBuffer(a)},this.loadFromURL=function(a){jt.Util.log("Reading ROM from URL: "+a);var b=new XMLHttpRequest;b.withCredentials=!0,b.open("GET",a,!0),b.responseType="arraybuffer",b.timeout=2e3,b.onload=function(){if(200===b.status){var c=new Uint8Array(b.response);i(a,c)}else j("URL reading error: "+(b.statusText||b.status))},b.onerror=function(){j("URL reading error: "+(b.statusText||b.status))},b.ontimeout=function(){j("URL reading error: "+(b.statusText||b.status))},b.send()};var b,c,d,e,f=function(b){if(b.returnValue=!1,b.preventDefault&&b.preventDefault(),b.stopPropagation&&b.stopPropagation(),b.target.focus(),this.files&&this.files.length){var c=this.files[0];try{d.value=""}catch(a){}return a.loadFromFile(c),!1}},g=function(a){a.returnValue=!1,a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation(),Javatari.CARTRIDGE_CHANGE_DISABLED?a.dataTransfer.dropEffect="none":a.dataTransfer.dropEffect="link"},h=function(b){if(b.returnValue=!1,b.preventDefault&&b.preventDefault(),b.stopPropagation&&b.stopPropagation(),b.target.focus(),l=b.altKey!==!0,!Javatari.CARTRIDGE_CHANGE_DISABLED&&b.dataTransfer){var c=b.dataTransfer&&b.dataTransfer.files;if(c&&c.length>0)return void a.loadFromFile(c[0]);var d=b.dataTransfer.getData("URL");d&&d.length>0&&a.loadFromURL(d)}},i=function(a,d){var e,f,g;try{if(g=new Array(d.length),jt.Util.arrayCopy(d,0,g,0,g.length),c.loadStateFile(g))return void jt.Util.log("SaveState file loaded");f=new jt.ROM(a,g),e=jt.CartridgeDatabase.createCartridgeFromRom(f),b&&b.insert(e,l)}catch(a){if(!a.javatari)throw jt.Util.log(a.stack),a;try{for(var h=new JSZip(d),i=h.file(m),k=0;k
Settings
HELP
CONTROLS
ABOUT
Ctrl
+
1 - 0
Save State
Alt
+
1 - 0
Load State
F8
Save State File
Alt
+
P
Pause
Alt
+
F
Next Frame
Alt
+
V
NTSC/PAL
Alt
+
R
CRT Modes
Alt
+
T
CRT Filter
Alt
+
G
Show Info
Alt
+
D
Debug Modes
Alt
+
C
Collisions
Tab
Fast Speed
Alt
+
Enter
Full Screen
Ctrl
+
F1
Fry Console
F7
Remove Cartridge
Backspace
Screen Defaults
Shift
+
Arrows
Screen Size
Shift
Alt
+
Arrows
Screen Scale
Shift
Ctrl
+
Arrows
Viewport Size
Ctrl
Alt
+
Arrows
Viewport Origin
Drag/Drop Files or URLs to load ROMs
Player 1
Button
Space
Up
Up
Button
Del
Left
Left
Right
Right
Down
Down
Player 2
Button
A
Up
T
Button
Dot
Left
F
Right
H
Down
G
Modes
Alt
+
K
Swap Keys
Alt
+
J
Swap Gamepads
Alt
+
L
Toggle Paddles
REVERT
DEFAULTS
'+Javatari.VERSION+'
Created by Paulo Augusto Peccin
http://javatari.org
'},SettingsGUI.css=function(){return'#jt-cover {position: fixed;top: 0;right: 0;bottom: 0;left: 0;visibility: hidden;opacity: 0;background-color: rgba(0, 0, 0, 0.6);transition: all .2s ease-out;}#jt-cover.show {visibility: visible;opacity: 1;}#jt-modal {position: relative;overflow: hidden;width: 560px;top: 80px;left: -120px;margin: 0 auto;color: rgba(0, 0, 0, 0.90);font-family: arial, sans-serif;box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4);transition: all .2s ease-out;}#jt-modal.show {left: 0;}#jt-modal .hotkey {height: 27px;padding: 3px 5px;font-size: 13px;box-sizing: border-box;}#jt-modal .hotkey .command {position: relative;float: left;font-weight: 600;color: rgba(0, 0, 0, .50);}#jt-modal .hotkey .desc {float: left;padding-top: 3px;}#jt-modal .key {position: relative;display: inline-block;top: -1px;min-width: 25px;height: 21px;padding: 4px 6px 3px;box-sizing: border-box;font-weight: 600;font-size: 12px;line-height: 12px;color: rgba(0, 0, 0, .68);background-color: white;border-radius: 3px;border: 1px solid rgb(210, 210, 210);box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5);text-align: center;}#jt-modal .key-ctrlalt {width: 31px;padding-left: 0;padding-right: 2px;}#jt-menu {position: relative;background-color: white;border-bottom: 1px solid rgb(200, 200, 200);}#jt-menu #jt-back {position: absolute;width: 18px;height: 32px;margin: 3px;padding: 0 11px;font-size: 35px;color: white;cursor: pointer;}#jt-menu #jt-back:hover {background-color: rgba(0, 0, 0, .12);}#jt-menu #jt-back-arrow {position: relative;overflow: hidden;top: -7px;}#jt-menu .caption {height: 29px;margin: 0 -1px;padding: 9px 0 0 48px;font-size: 19px;color: white;background-color: rgb(235, 62, 35);box-shadow: 0 1px 4px rgba(0, 0, 0, .8);}#jt-menu .items {position: relative;width: 70%;height: 39px;margin: 0 auto;font-weight: 600;}#jt-menu .item {float: left;width: 33.3%;height: 100%;padding-top: 13px;font-size: 14px;color: rgba(0, 0, 0, .43);text-align: center;cursor: pointer}#jt-menu .selected {color: rgb(224, 56, 34);}#jt-menu #jt-menu-selection {position: absolute;left: 0;bottom: 0;width: 33.3%;height: 3px;background-color: rgb(235, 62, 35);transition: left 0.3s ease-in-out}#jt-content {position: relative;left: 0;width: 1680px;height: 370px;background-color: rgb(220, 220, 220);transition: left 0.3s ease-in-out}#jt-help, #jt-controls, #jt-about {position: absolute;width: 560px;height: 100%;box-sizing: border-box;}#jt-help {padding-top: 22px;}#jt-help .left {float: left;padding-left: 30px;}#jt-help .right {float: left;padding-left: 34px;}#jt-help .left .command {width: 104px;}#jt-help .right .command {width: 109px;}#jt-help .command.right-bottom {width: 164px;}#jt-controls {left: 560px;}#jt-controls .player {position: absolute;top: 15px;width: 217px;color: rgba(0, 0, 0, .8);}#jt-controls .p1 {left: 28px;}#jt-controls .p2 {right: 28px;}#jt-controls .title {padding-bottom: 4px;margin: 0 14px 8px 12px;font-size: 18px;text-align: center;border-bottom: 2px solid rgba(242, 66, 35, .55);}#jt-controls .player .command {position: relative;float: left;width: 33%;height: 45px;font-size: 13px;text-align: center;}#jt-controls .command.fire1, #jt-controls .command.fire2 {top: 14px;}#jt-controls .command.left, #jt-controls .command.right {top: 27px;}#jt-controls .command.down {float: none;clear: both;margin: 0 auto;}#jt-controls .command.controller {height: 90px;}#jt-controls #jt-control-p1-controller, #jt-controls #jt-control-p2-controller {width: 70px;height: 89px;margin-left: 1px;background: url("'+Javatari.IMAGES_PATH+'sprites.png") no-repeat -466px 0;}#jt-controls .player .key {min-width: 33px;height: 23px;padding: 5px 6px 4px;margin-top: 2px;cursor: pointer;}#jt-controls .player .key:hover {box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5), 1px 2px 6px 4px rgb(170, 170, 170);}#jt-controls .player .key.redefining {color: white;background-color: rgb(87, 128, 255);border-color: rgb(71, 117, 255);}#jt-controls .player .key.undefined {background-color: rgb(255, 150, 130);border-color: rgb(255, 130, 90);}#jt-controls .modes {position: absolute;top: 200px;left: 0;right: 0;width: 200px;margin: 0 auto;}#jt-controls .modes .hotkey {position: relative;padding-left: 8px;cursor: pointer;}#jt-controls .modes .hotkey:hover {background-color: white;box-shadow: 1px 1px 3px 1px rgb(180, 180, 180);}#jt-controls .modes .command {margin-right: 12px;}#jt-controls-defaults, #jt-controls-revert {position: absolute;bottom: 18px;padding: 7px 10px;font-size: 12px;font-weight: 600;border-radius: 1px;cursor: pointer}#jt-controls-defaults:hover, #jt-controls-revert:hover {background-color: white;box-shadow: 1px 1px 3px 1px rgb(180, 180, 180);}#jt-controls-revert {right: 30px;color: rgba(0, 0, 0, 0.8);}#jt-controls-defaults {right: 115px;color: rgb(0, 80, 230);}#jt-about {left: 1120px;}#jt-about #jt-logo-version {width: 248px;height: 220px;margin: 28px auto 14px;font-size: 18px;color: rgba(255, 255, 255, 0.97);padding-top: 190px;box-sizing: border-box;text-align: center;background: black url("'+Javatari.IMAGES_PATH+'logo.png") no-repeat 5px 13px;background-size: 233px 173px;box-shadow: 3px 3px 14px rgb(75, 75, 75);}#jt-about .info {font-size: 18px;line-height: 30px;text-align: center;}#jt-about a {color: rgb(0, 80, 230);text-decoration: none;}#jt-about #jt-browserinfo {position: absolute;left: 0;right: 0;bottom: 7px;font-size: 10px;text-align: center;color: transparent;}'; },jt.Room=function(a,b,c){function d(){g(),h()}var e=this;this.powerOn=function(a){i(),e.screen.powerOn(),e.consolePanel&&this.consolePanel.powerOn(),e.speaker.powerOn(),e.controls.powerOn(),f(),e.console.getCartridgeSocket().inserted()&&!e.console.powerIsOn&&e.console.powerOn(a)},this.powerOff=function(){e.console.powerOff(),e.controls.powerOff(),e.speaker.powerOff(),e.screen.powerOff(),e.consolePanel&&this.consolePanel.powerOff()};var f=function(){e.console.getCartridgeSocket().inserted()||c&&e.console.getCartridgeSocket().insert(c,!1)},g=function(){e.stateMedia=new jt.LocalStorageSaveStateMedia,e.romLoader=new jt.ROMLoader,e.screen=new jt.CanvasDisplay(a),e.screen.connectPeripherals(e.romLoader,e.stateMedia),b&&(e.consolePanel=new jt.ConsolePanel(b),e.consolePanel.connectPeripherals(e.screen,e.romLoader)),e.speaker=new jt.WebAudioSpeaker,e.controls=new jt.DOMConsoleControls,e.controls.connectPeripherals(e.screen,e.consolePanel)},h=function(){e.console=new jt.AtariConsole,e.stateMedia.connect(e.console.getSavestateSocket()),e.romLoader.connect(e.console.getCartridgeSocket(),e.console.getSavestateSocket()),e.screen.connect(e.console.getVideoOutput(),e.console.getControlsSocket(),e.console.getCartridgeSocket()),e.consolePanel&&e.consolePanel.connect(e.console.getControlsSocket(),e.console.getCartridgeSocket(),e.controls),e.speaker.connect(e.console.getAudioOutput()),e.controls.connect(e.console.getControlsSocket(),e.console.getCartridgeSocket())},i=function(){function a(){document.hidden?e.speaker.mute():e.speaker.play()}document.addEventListener("visibilitychange",a)};this.screen=null,this.consolePanel=null,this.speaker=null,this.controls=null,this.console=null,this.stateMedia=null,this.romLoader=null,d()},Javatari.start=function(){if(Javatari.preferences.load(),!Javatari.screenElement&&(Javatari.screenElement=document.getElementById(Javatari.SCREEN_ELEMENT_ID),!Javatari.screenElement))throw new Error('Javatari cannot be started. HTML document is missing screen element with id "'+Javatari.SCREEN_ELEMENT_ID+'"');Javatari.consolePanelElement||(Javatari.consolePanelElement=document.getElementById(Javatari.CONSOLE_PANEL_ELEMENT_ID)),Javatari.room=new jt.Room(Javatari.screenElement,Javatari.consolePanelElement),Javatari.room.powerOn(),Javatari.ROM_AUTO_LOAD_URL&&Javatari.room.romLoader.loadFromURL(Javatari.ROM_AUTO_LOAD_URL),Javatari.shutdown=function(){Javatari.room&&Javatari.room.powerOff(),jt.Util.log("shutdown"),delete Javatari},delete Javatari.start,delete Javatari.preLoadImagesAndStart,jt.Util.log(Javatari.VERSION+" started")},Javatari.preLoadImagesAndStart=function(){function a(a){Javatari.start&&Javatari.AUTO_START!==!1&&(a||d&&0===e)&&Javatari.start()}var b=["sprites.png","logo.png","screenborder.png"],c=b.length,d=!1,e=c;document.addEventListener("DOMContentLoaded",function(){d=!0,a(!1)});for(var f=0;f= 0: wait specified milliseconds before Power-ON CARTRIDGE_SHOW_RECENT: true, CARTRIDGE_CHANGE_DISABLED: false, CARTRIDGE_LABEL_COLORS: "", // Space-separated colors for Label, Background, Border. e.g. "#f00 #000 transparent". Leave "" for defaults SCREEN_RESIZE_DISABLED: false, SCREEN_CONSOLE_PANEL_DISABLED: false, SCREEN_ELEMENT_ID: "javatari-screen", CONSOLE_PANEL_ELEMENT_ID: -1, // -1: auto. Don't change! :-) SCREEN_FULLSCREEN_MODE: -1, // -2: disabled; -1: auto; 0: off; 1: on SCREEN_CRT_MODE: 0, // -1: auto; 0: off; 1: on SCREEN_FILTER_MODE: -3, // -3: user set (default auto); -2: browser default; -1: auto; 0..3: smoothing level SCREEN_DEFAULT_SCALE: -1, // -1: auto; 0.5..N in 0.1 steps: scale SCREEN_DEFAULT_ASPECT: 1, // in 0.1 steps SCREEN_CANVAS_SIZE: 2, // Internal canvas size factor. Don't change! :-) SCREEN_CONTROL_BAR: 1, // 0: on hover; 1: always SCREEN_FORCE_HOST_NATIVE_FPS: -1, // -1: auto. Don't change! :-) SCREEN_VSYNCH_MODE: -2, // -2: user set (default on); -1: disabled; 0: off; 1: on AUDIO_MONITOR_BUFFER_BASE: -3, // -3: user set (default auto); -2: disable audio; -1: auto; 0: browser default; 1..6: base value. More buffer = more delay AUDIO_MONITOR_BUFFER_SIZE: -1, // -1: auto; 256, 512, 1024, 2048, 4096, 8192, 16384: buffer size. More buffer = more delay. Don't change! :-) AUDIO_SIGNAL_BUFFER_RATIO: 2, // Internal Audio Signal buffer based on Monitor buffer AUDIO_SIGNAL_ADD_FRAMES: 3, // Additional frames in internal Audio Signal buffer based on Monitor buffer PADDLES_MODE: -1, // -1: auto; 0: off; 1: on TOUCH_MODE: -1, // -1: auto; 0: disabled; 1: enabled; 2: enabled (swapped) IMAGES_PATH: window.JAVATARI_IMAGES_PATH || "images/", PAGE_BACK_CSS: "", // CSS to modify page background color. Applied to the body element SERVER_ADDRESS: "webmsx.azurewebsites.net/", SERVER_KEEPALIVE: 0, RESET: 0, // if value = 1 clear all saved data on the client ALLOW_URL_PARAMETERS: true // Allows user to override any of these parameters via URL query parameters }; Javatari.PRESETS_CONFIG = { }; // No built-in Presets for now jt = window.jt || {}; // Namespace for all classes and objects ================================================ FILE: src/main/Launcher.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. Javatari.start = function (consolePowerOn) { "use strict"; // Emulator can only be started once delete Javatari.start; delete Javatari.preLoadImagesAndStart; // Init preferences Javatari.userPreferences.load(); // Get container elements if (!Javatari.screenElement) { Javatari.screenElement = document.getElementById(Javatari.SCREEN_ELEMENT_ID); if (!Javatari.screenElement) throw new Error('Javatari cannot be started. ' + 'HTML document is missing screen element with id "' + Javatari.SCREEN_ELEMENT_ID + '"'); } // Apply Configuration, including Machine Type and URL Parameters if allowed jt.Configurator.applyConfig(); // Build and start emulator if (consolePowerOn === undefined) consolePowerOn = Javatari.AUTO_POWER_ON_DELAY >= 0; Javatari.room = new jt.Room(Javatari.screenElement, consolePowerOn); Javatari.room.powerOn(); jt.Util.log("version " + Javatari.VERSION + " started"); // Prepare ROM Database jt.CartridgeDatabase.uncompress(); // Init KeepAlive jt.NetClient.initKeepAlive(); // NetPlay! auto-join Session? var joinSession = Javatari.NETPLAY_JOIN; // Auto-load BIOS, Expansions, State, Cartridges, Disks and Tape files if specified and downloadable if (!joinSession && Javatari.STATE_URL) { // State loading, Console will Auto Power on new jt.MultiDownloader( [{ url: Javatari.STATE_URL }], function onAllSuccess(urls) { Javatari.room.start(function() { Javatari.room.fileLoader.loadFromContent(urls[0].url, urls[0].content, jt.FileLoader.OPEN_TYPE.STATE, 0, false); }); } ).start(); } else { // Normal media loading. Power Console on only after all files are loaded and inserted var mediaURLs = joinSession ? [] : jt.Configurator.mediaURLSpecs(); // Skip media loading if joining Session new jt.MultiDownloader( mediaURLs, function onAllSuccess() { Javatari.room.start(joinSession ? function() { Javatari.room.getNetClient().joinSession(joinSession, Javatari.NETPLAY_NICK); } : undefined ); } ).start(); } Javatari.shutdown = function () { if (Javatari.room) Javatari.room.powerOff(); jt.Util.log("shutdown"); }; }; // Pre-load images if needed and start emulator as soon as all are loaded and DOM is ready Javatari.preLoadImagesAndStart = function() { var domReady = false; var imagesToLoad = jt.Images.embedded ? 0 : jt.Images.count; function tryStart(bypass) { if (Javatari.start && Javatari.AUTO_START && (bypass || (domReady && imagesToLoad === 0))) Javatari.start(); } document.addEventListener("DOMContentLoaded", function() { domReady = true; tryStart(false); }); if (imagesToLoad > 0) { for (var i in jt.Images.urls) { var img = new Image(); img.src = jt.Images.urls[i]; img.onload = function () { imagesToLoad--; tryStart(false); }; } } window.addEventListener("load", function() { tryStart(true); }); }; // AppCache update control if (window.applicationCache) { function onUpdateReady() { alert("A new version is available!\nJavatari will restart..."); window.applicationCache.swapCache(); window.location.reload(); } if (window.applicationCache.status === window.applicationCache.UPDATEREADY) onUpdateReady(); else window.applicationCache.addEventListener("updateready", onUpdateReady); } Javatari.VERSION = "5.0.4"; // Start pre-loading images right away Javatari.preLoadImagesAndStart(); ================================================ FILE: src/main/atari/audio/AudioSignal.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.AudioSignal = function(name, source, sampleRate, volume) { "use strict"; var self = this; this.flush = function() { nextSampleToGenerate = 0; nextSampleToRetrieve = 0; availSamples = maxAvailSamples; //console.log("FLUSH!"); }; this.setFps = function(fps) { // Calculate total samples per frame based on fps samplesPerFrame = (sampleRate / fps) | 0; updateBufferSize(); }; this.audioFinishFrame = function() { // Enough samples to complete frame, signal always ON if (frameSamples > 0) { //console.log(">>> Audio finish frame: " + frameSamples); while(frameSamples > 0) audioClockPulse(); } frameSamples = samplesPerFrame; }; this.retrieveSamples = function(quant, mute) { var generated = maxAvailSamples - availSamples; //var generated = nextSampleToGenerate >= nextSampleToRetrieve // ? nextSampleToGenerate - nextSampleToRetrieve // : maxSamples - nextSampleToRetrieve + nextSampleToGenerate; //console.log(">>> Samples available: " + generated); //if (nextSampleToGenerate === nextSampleToRetrieve) // console.log("MATCH: " + nextSampleToGenerate ); //if (nextSampleToGenerate < nextSampleToRetrieve) // console.log("WRAP: " + nextSampleToGenerate ); var missing = quant - generated; if (missing > 0) { if (missing > availSamples) missing = availSamples; generateMissingSamples(missing, mute); //jt.Util.log(">>> Missing samples generated: " + missing); } else { //jt.Util.log(">>> No missing samples"); } retrieveResult.start = nextSampleToRetrieve; var retrieved = generated + missing; availSamples += retrieved; nextSampleToRetrieve += retrieved; if (nextSampleToRetrieve >= maxSamples) nextSampleToRetrieve -= maxSamples; // Circular Buffer return retrieveResult; }; function audioClockPulse() { if (frameSamples > 0) { if (availSamples <= 0) { frameSamples = 0; return; } generateNextSample(); --frameSamples; --availSamples; } } this.audioClockPulse = audioClockPulse; this.getSampleRate = function() { return sampleRate; }; this.toString = function() { return "AudioSignal " + name; }; this.setAudioMonitorBufferSize = function (size) { monitorBufferSize = size; updateBufferSize(); }; function updateBufferSize() { var size = (monitorBufferSize * Javatari.AUDIO_SIGNAL_BUFFER_RATIO + samplesPerFrame * Javatari.AUDIO_SIGNAL_ADD_FRAMES) | 0; samples.length = size; if (size > maxSamples) jt.Util.arrayFill(samples, 0, maxSamples, size); maxSamples = size; retrieveResult.bufferSize = maxSamples; maxAvailSamples = maxSamples - 2; self.flush(); //console.log(">>> Buffer size for: " + name + ": " + maxSamples); } function generateNextSample() { samples[nextSampleToGenerate] = source.nextSample() * volume; if (++nextSampleToGenerate >= maxSamples) nextSampleToGenerate = 0; // Circular Buffer } function generateNextSampleMute() { samples[nextSampleToGenerate] = 0; if (++nextSampleToGenerate >= maxSamples) nextSampleToGenerate = 0; // Circular Buffer } function generateMissingSamples(quant, mute) { if (mute) for (var j = quant; j > 0; j = j - 1) generateNextSampleMute() else for (var i = quant; i > 0; i = i - 1) generateNextSample() availSamples -= quant; } this.name = name; var clock72xCountDown = 9; // 4 clocks out of 9 32x clocks. Count from 9 to 0 and misses every odd and the 8th clock var nextSampleToGenerate = 0; var nextSampleToRetrieve = 0; var samplesPerFrame; var frameSamples = 0; var maxSamples = 0; var availSamples = 0, maxAvailSamples = 0; var samples = jt.Util.arrayFill(new Array(maxSamples), 0); var monitorBufferSize = 0; var retrieveResult = { buffer: samples, bufferSize: maxSamples, start: 0 }; }; ================================================ FILE: src/main/atari/cartridge/Cartridge.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Cartridge = function() { "use strict"; this.powerOn = function() { }; this.powerOff = function() { }; this.connectBus = function(bus) { }; this.connectSaveStateSocket = function(socket) { }; this.read = function(address) { }; this.write = function(address, val) { // Writing to ROMs is possible, but nothing is changed }; this.getDataDesc = function() { return null; }; this.needsBusMonitoring = function() { return false; }; this.monitorBusBeforeRead = function(address) { }; this.monitorBusBeforeWrite = function(address, val) { }; this.needsAudioClock = function() { return false; }; this.audioClockPulse = function() { }; this.reinsertROMContent = function() { if (this.rom.content) return; this.rom.content = this.bytes || []; }; this.format = null; this.rom = null; this.bytes = null; // Savestate ------------------------------------------- this.saveState = function() { }; this.loadState = function(state) { }; }; jt.Cartridge.base = new jt.Cartridge(); ================================================ FILE: src/main/atari/cartridge/CartridgeCreator.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.CartridgeCreatorImpl = function() { "use strict"; this.createCartridgeFromRom = function(rom) { // ROM has User Set Format? var userFormatName = userROMFormats.getForROM(rom); if (userFormatName) { var userFormat = jt.CartridgeFormats[userFormatName]; if (userFormat.tryFormat(rom)) { jt.Util.log("USER Format selected: " + userFormat.desc); return userFormat.createCartridgeFromRom(rom); } } // Try to build the Slot with the best format, if a supported format is found var bestOption = this.getBestFormatOption(rom); if (!bestOption) return; jt.Util.log("AUTO Format selected: " + bestOption.name + ": " + bestOption.desc + ", priority: " + bestOption.priority + (bestOption.priorityBoosted ? " (" + bestOption.priorityBoosted + ")" : "")); return bestOption.createCartridgeFromRom(rom); }; this.recreateCartridgeFromSaveState = function(saveState, cartridge) { var cartridgeFormat = jt.CartridgeFormats[saveState.f]; if (!cartridgeFormat) throw new Error ("Unsupported ROM Format: " + saveState.f); if (cartridge && cartridge.format !== cartridgeFormat) cartridge = null; // Only possible to reuse cartridge if the format is the same! return cartridgeFormat.recreateCartridgeFromSaveState(saveState, cartridge); }; this.changeCartridgeFormat = function(cart, newFormat) { return newFormat.createCartridgeFromRom(cart.rom); }; this.getBestFormatOption = function(rom) { var options = getFormatOptions(rom); return options.length === 0 ? undefined : options[0]; }; this.getUserFormatOptionNames = function(rom) { var formatOptions = []; for (var i = 0, len = jt.CartridgeFormatsUserOptions.length; i < len; ++i) { var formatName = jt.CartridgeFormatsUserOptions[i]; var format = jt.CartridgeFormats[formatName].tryFormat(rom); if (format) formatOptions.push(formatName); } return formatOptions; }; this.produceInfo = function(rom, formatHint) { // Preserve original length as MD5 computation may increase it var origLen = rom.content.length; var hash = jt.MD5(rom.content); if (rom.content.length > origLen) rom.content.splice(origLen); // Get info from the library var info = jt.CartridgeDatabase[hash]; if (info) { jt.Util.log("" + info.n + " (" + hash + ")"); } else { info = buildInfo(rom.source); jt.Util.log("Unknown ROM: " + info.n + " (" + hash + ")"); } finishInfo(info, rom.source, hash, formatHint); return info; }; this.setUserROMFormats = function(pUserROMFormats) { userROMFormats = pUserROMFormats; }; var getFormatOptions = function(rom) { var formatOptions = []; var formatOption; var denialEx; for (var format in jt.CartridgeFormats) { try { formatOption = jt.CartridgeFormats[format].tryFormat(rom); if (!formatOption) continue; // rejected by format boostPriority(formatOption, rom.info); // adjust priority based on ROM info formatOptions.push(formatOption); } catch (ex) { if (!ex.formatDenial) throw ex; if (!denialEx) denialEx = ex; // Keep only the first one } } // Sort according to priority formatOptions.sort(function formatOptionComparator(a, b) { return (a.priorityBoosted || a.priority) - (b.priorityBoosted || b.priority); }); return formatOptions; }; var buildInfo = function(romSource) { var info = { n: "Unknown" }; if (!romSource || !romSource.trim()) return info; var name = romSource; // Get the last part of the URL (file name) var slash = name.lastIndexOf("/"); var bslash = name.lastIndexOf("\\"); var question = name.lastIndexOf("?"); var i = Math.max(slash, Math.max(bslash, question)); if (i >= 0 && i < name.length - 1) name = name.substring(i + 1); // Get only the file name without the extension var dot = name.lastIndexOf("."); if (dot >= 0) name = name.substring(0, dot); info.n = name.trim() || "Unknown"; return info; }; // Fill absent information based on ROM name var finishInfo = function(info, romSource, hash, formatHint) { // Saves the hash on the info info.h = hash; // Compute label based on name if (!info.l) info.l = produceCartridgeLabel(info.n); var name = info.n.toUpperCase(); // Adjust Paddles information if absent Paddles: if (!info.p) { info.p = 0; if (!name.match(HINTS_PREFIX_REGEX + "JOYSTICK(S)?" + HINTS_SUFFIX_REGEX)) { if (name.match(HINTS_PREFIX_REGEX + "PADDLE(S)?" + HINTS_SUFFIX_REGEX)) info.p = 1; else for (var i = 0; i < PADDLES_ROM_NAMES.length; i++) if (name.match(PADDLES_ROM_NAMES[i])) { info.p = 1; break Paddles; } } } // Adjust CRT Mode information if absent CrtMode: if (!info.c) { if (name.match(HINTS_PREFIX_REGEX + "CRT(_|-)?MODE" + HINTS_SUFFIX_REGEX)) info.c = 1; else for (i = 0; i < CRT_MODE_ROM_NAMES.length; i++) if (name.match(CRT_MODE_ROM_NAMES[i])) { info.c = 1; break CrtMode; } } // Adjust Format information if hint passed if (formatHint) { formatHint = formatHint.trim().toUpperCase(); for (var formatName in jt.CartridgeFormats) if (formatName.toUpperCase() === formatHint) { info.f = formatName; break; } } // Adjust Format information if absent Format: if (!info.f) { // First by explicit format hint var romURL = romSource.toUpperCase(); for (formatName in jt.CartridgeFormats) if (formatMatchesByHint(formatName, name) || formatMatchesByHint(formatName, romURL)) { info.f = formatName; break Format; } // Then by name for (formatName in FORMAT_ROM_NAMES) if (formatMatchesByName(formatName, name)) { info.f = formatName; break Format; } } }; var boostPriority = function(formatOption, info) { if (info.f && formatOption.name === info.f) formatOption.priorityBoosted = formatOption.priority - FORMAT_PRIORITY_BOOST; else formatOption.priorityBoosted = undefined; }; var produceCartridgeLabel = function(name) { return name.split(/(\(|\[)/)[0].trim(); // .toUpperCase(); // TODO Validate }; var formatMatchesByHint = function(formatName, hint) { return hint.match(HINTS_PREFIX_REGEX + formatName + HINTS_SUFFIX_REGEX); }; var formatMatchesByName = function(formatName, name) { var namesForFormat = FORMAT_ROM_NAMES[formatName]; if (!namesForFormat) return false; for (var i = 0; i < namesForFormat.length; i++) if (name.match(namesForFormat[i])) return true; return false; }; var FORMAT_ROM_NAMES = { "E0": [ "^.*MONTEZUMA.*$", "^.*MONTZREV.*$", "^.*GYRUS.*$", "^.*TOOTH.*PROTECTORS.*$", "^.*TOOTHPRO.*$", "^.*DEATH.*STAR.*BATTLE.*$", "^.*DETHSTAR.*$", "^.*JAMES.*BOND.*$", "^.*JAMEBOND.*$", "^.*SUPER.*COBRA.*$", "^.*SPRCOBRA.*$", "^.*TUTANKHAM.*$", "^.*TUTANK.*$", "^.*POPEYE.*$", "^.*(SW|STAR.?WARS).*ARCADE.*GAME.*$", "^.*SWARCADE.*$", "^.*Q.*BERT.*QUBES.*$", "^.*QBRTQUBE.*$", "^.*FROGGER.?(2|II).*$", "^.*DO.*CASTLE.*$" ], "FE": [ "^.*ROBOT.*TANK.*$", "^.*ROBOTANK.*$", "^.*DECATHLON.*$" , "^.*DECATHLN.*$" // There is also a 16K F6 version ], "E7": [ "^.*BUMP.*JUMP.*$", "^.*BNJ.*$", "^.*BURGER.*TIME.*$", "^.*BURGTIME.*$", "^.*POWER.*HE.?MAN.*$", "^.*HE_MAN.*$" ], "3F": [ "^.*POLARIS.*$", "^.*RIVER.*PATROL.*$", "^.*RIVERP.*$", "^.*SPRINGER.*$", "^.*MINER.*2049.*$", "^.*MNR2049R.*$", "^.*MINER.*2049.*VOLUME.*$", "^.*MINRVOL2.*$", "^.*ESPIAL.*$", "^.*ANDREW.*DAVIE.*$", "^.*DEMO.*IMAGE.*AD.*$" // Various 32K Image demos ], "3E": [ "^.*BOULDER.*DASH.*$", "^.*BLDRDASH.*$" ], "DPC": [ "^.*PITFALL.*II.*$" ] }; var PADDLES_ROM_NAMES = [ "^.*PADDLES.*$", // Generic hint "^.*BREAKOUT.*$", "^.*SUPER.*BREAKOUT.*$", "^.*SUPERB.*$", "^.*WARLORDS.*$", "^.*STEEPLE.*CHASE.*$", "^.*STEPLCHS.*$", "^.*VIDEO.*OLYMPICS.*$", "^.*VID(|_)OLYM(|P).*$", "^.*CIRCUS.*ATARI.*$", "^.*CIRCATRI.*$", "^.*KABOOM.*$", "^.*BUGS((?!BUNNY).)*", // Bugs, but not Bugs Bunny! "^.*BACHELOR.*PARTY.*$", "^.*BACHELOR.*$", "^.*BACHELORETTE.*PARTY.*$", "^.*BACHLRTT.*$", "^.*BEAT.*EM.*EAT.*EM.*$", "^.*BEATEM.*$", "^.*PHILLY.*FLASHER.*$", "^.*PHILLY.*$", "^.*JEDI.*ARENA.*$", "^.*JEDIAREN.*$", "^.*EGGOMANIA.*$", "^.*EGGOMANA.*$", "^.*PICNIC.*$", "^.*PIECE.*O.*CAKE.*$", "^.*PIECECKE.*$", "^.*BACKGAMMON.*$", "^.*BACKGAM.*$", "^.*BLACKJACK.*$", "^.*BLACK(|_)J.*$", "^.*CANYON.*BOMBER.*$", "^.*CANYONB.*$", "^.*CASINO.*$", "^.*DEMONS.*DIAMONDS.*$", "^.*DEMONDIM.*$", "^.*DUKES.*HAZZARD.*2.*$", "^.*STUNT.?2.*$", "^.*ENCOUNTER.*L.?5.*$", "^.*ENCONTL5.*$", "^.*G.*I.*JOE.*COBRA.*STRIKE.*$", "^.*GIJOE.*$", "^.*GUARDIAN.*$", "^.*MARBLE.*CRAZE.*$", "^.*MARBCRAZ.*$", "^.*MEDIEVAL.*MAYHEM.*$", "^.*MONDO.*PONG.*$", "^.*NIGHT.*DRIVER.*$", "^.*NIGHTDRV.*$", "^.*PARTY.*MIX.*$", "^.*POKER.*PLUS.*$", "^.*PONG.*SPORTS.*$", "^.*SCSICIDE.*$", "^.*SECRET.*AGENT.*$", "^.*SOLAR.*STORM.*$", "^.*SOLRSTRM.*$", "^.*SPEEDWAY.*$", "^.*STREET.*RACER.*$", "^.*STRTRACE.*$", "^.*STUNT.*CYCLE.*$", "^.*STUNT.?1.*$", "^.*TAC.?SCAN.*$", "^.*MUSIC.*MACHINE.*$", "^.*MUSCMACH.*$", "^.*VONG.*$", "^.*WARPLOCK.*$" ]; var CRT_MODE_ROM_NAMES = [ "^.*STAR.*CASTLE.*$", "^.*SEAWEED.*$", "^.*ANDREW.*DAVIE.*$", "^.*DEMO.*IMAGE.*AD.*$" // Various 32K Image demos ]; var userROMFormats; var HINTS_PREFIX_REGEX = "^(|.*?(\\W|_|%20))"; var HINTS_SUFFIX_REGEX = "(|(\\W|_|%20).*)$"; var FORMAT_PRIORITY_BOOST = 50; }; jt.CartridgeCreator = new jt.CartridgeCreatorImpl(); ================================================ FILE: src/main/atari/cartridge/CartridgeDatabase.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Many thanks to ROM Hunter for sharing the info! // Version 20170310 jt.CartridgeDatabase = { uncompress: function () { // Throw away the compressed version, will be garbage collected jt.CartridgeDatabase = JSON.parse(jt.Util.uncompressStringBase64ToString(this.data)); }, data: "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" }; ================================================ FILE: src/main/atari/cartridge/CartridgeDatabaseUncompressed.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Many thanks to ROM Hunter for sharing the info! jt.CartridgeDatabaseUncompressed = { version: 20170310, "0685BD0BCB975CEEF7041749A5454A48":{n:"11 Sprite Demo (Piero Cavina) (PD)"}, "1862FCA4F98E66F363308B859B5863AF":{n:"128-in-1 Junior Console (Chip 1 of 4) (1991) (Atari) (PAL)"}, "715DD9E0240638D441A3ADD49316C018":{n:"128-in-1 Junior Console (Chip 2 of 4) (1991) (Atari) (PAL)"}, "0D6B974FE58A1BDD453600401C407856":{n:"128-in-1 Junior Console (Chip 3 or 4) (1991) (Atari) (PAL)"}, "7F525B07BC98080CC8950F7284E52EDE":{n:"128-in-1 Junior Console (Chip 4 of 4) (1991) (Atari) (PAL)"}, "7F430C33044E0354815392B53A9A772D":{n:"2 Pak Special - Cavern Blaster, City War (1992) (HES) (PAL)"}, "7732E4E4CC2644F163D6650DDCC9D9DF":{n:"2 Pak Special - Challenge, Spitfallrfing (1990) (HES) (PAL)"}, "FD7464EDAA8CC264B97BA0D13E7F0678":{n:"2 Pak Special - Challenge, Surfing (1990) (HES) (PAL) [a]"}, "8C8A26ED57870DABA8E13162D497BAD1":{n:"2 Pak Special - Dolphin, Oink (1990) (HES) (PAL)"}, "ED1306436CE237AFC5A7ED3F77134202":{n:"2 Pak Special - Dolphin, Pigs 'n' Wolf (1990) (HES) (PAL)"}, "F8C1C4A41303BD40B0D6C81BFAF8573B":{n:"2 Pak Special - Dungeon Master, Creature Strike (1992) (HES) (PAL)"}, "AB434F4C942D6472E75D5490CC4DD128":{n:"2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL)"}, "5B9C2E0012FBFD29EFD3306359BBFC4A":{n:"2 Pak Special - Hoppy, Alien Force (1992) (HES) (PAL) [a]"}, "2E842C2EE22E9DAD9DF16EED091315C4":{n:"2 Pak Special - Motocross, Boom Bang (1990) (HES) (PAL)"}, "A94B8CA630F467B574B614808D813919":{n:"2 Pak Special - Space Voyage, Fire Alert (1992) (HES) (PAL)"}, "02A5FC90A0D183F870E8EEBAC1F16591":{n:"2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL)"}, "4D2CEF8F19CAFEEC72D142E34A1BBC03":{n:"2 Pak Special - Star Warrior, Frogger (1990) (HES) (PAL) [a]"}, "72FD08DEED1D6195942E0C6F392E9848":{n:"2 Pak Special - Wall Defender, Planet Patrol (1990) (HES) (PAL)"}, "9C40BF810F761FFC9C1B69C4647A8B84":{n:"2 in 1 - Frostbite, River Raid (Unknown)"}, "94E3FBC19107A169909E274187247A9D":{n:"2-in-1 Freeway and Tennis (Unknown)"}, "FA529EC88ECA679F6D5FD0CCB2120E46":{n:"20 Sprites at Once Demo 1 (PD)"}, "7A93D0C029EAA72236523EEDC3F19645":{n:"20 Sprites at Once Demo 2 (PD)"}, "6C449DB9BBBD90972AD1932D6AF87330":{n:"20 Sprites at Once Demo 3 (PD)"}, "BFA58198C6B9CD8062EE76A2B38E9B33":{n:"20 Sprites at Once Demo 4 (PD)"}, "D2D8C4F1EA7F347C8BCC7D24F45AA338":{n:"20 Sprites at Once Demo 5 (PD)"}, "AD2E6BFB3B9B9B36BA8BF493CE764C49":{n:"2600 Collison Demo 1 (Piero Cavina) (PD)"}, "777AECE98D7373998FFB8BC0B5EFF1A2":{n:"2600 Collison Demo 2 (Piero Cavina) (PD)"}, "EADA0DD61CE13F8317DE774DC1E68604":{n:"2600 Digital Clock (Demo 1) (PD)"}, "3E5CA1AFAA27C5DA3C54C9942FEC528B":{n:"2600 Digital Clock (Demo 2) (PD)"}, "F6EFA00AE99AAF33E427B674BCFD834D":{n:"2600 Digital Clock (Demo 3) (PD)"}, "75E8D8B9E9C5C67C2226DBFD77DCFA7D":{n:"2600 Digital Clock (V b1) (PD)"}, "5E99AA93D0ACC741DCDA8752C4E813CE":{n:"2600 Digital Clock (V b2) (PD)"}, "62FFD175CAC3F781EF6E4870136A2520":{n:"2600 Digital Clock (V x.xx) (PD)"}, "4FAEB04B1B7FB0FA25DB05753182A898":{n:"2600 Digital Clock (V x.xx) (PD) [a1]"}, "655C84E5B951258C9D20F0BF2B9D496D":{n:"2600_2003 Demo (PD)"}, "B95A6274CA0E0C773BFDC06B4C3DAA42":{n:"3-D Corridor (29-03-2003) (Paul Slocum)"}, "6B8FB021BB2E1F1E9BD7EE57F2A8E709":{n:"3-D Corridor (29-03-2003) (Paul Slocum) (PD) [a]"}, "8D00A38F4C8F8800F1C237215AC243FC":{n:"3-D Corridor (Green) (30-03-2003) (AD)"}, "7B6F3348DBF71ADA88DB0FDAF7FEEFE0":{n:"3-D Corridor (Pink Spiral) (31-03-2003) (AD)"}, "B6960BE26BEE87D53BA4E2E71CFE772F":{n:"3-D Corridor (Spiral Words) (31-03-2003) (AD)"}, "493DAAF9FB1BA450EBA6B8ED53FFB37D":{n:"3-D Corridor Demo (27-03-2003) (MP)"}, "4947C9DE2E28B2F5F3B0C40CE7E56D93":{n:"3-D Corridor Demo 2 (29-03-2003) (MP)"}, "0DB4F4150FECF77E4CE72CA4D04C052F":{n:"3-D Tic-Tac-Toe (1980) (Atari)"}, "F3213A8A702B0646D2EAF9EE0722B51C":{n:"3-D Tic-Tac-Toe (1980) (Atari) (4K)"}, "E3600BE9EB98146ADAFDC12D91323D0F":{n:"3-D Tic-Tac-Toe (1980) (Atari) (PAL)"}, "854B68B93E7123A3BE42B5A2A41F75D7":{n:"3-D Tic-Tac-Toe (1980) (Atari) (PAL) (4K)"}, "7B5207E68EE85B16998BEA861987C690":{n:"3-D Tic-Tac-Toe (32 in 1) (1988) (Atari) (PAL)"}, "402B1CA3C230A60FB279D4A2A10FA677":{n:"3-D Tic-Tac-Toe (Unknown) (PAL) (4K)"}, "291DD47588B9158BEEBE4ACCC3A093A6":{n:"32 in 1 Console ROM (02-10-1989) (Atari) (Prototype) (PAL)"}, "291BCDB05F2B37CDF9452D2BF08E0321":{n:"32 in 1 Game Cartridge (1988) (Atari) (Prototype) (PAL)"}, "792B1D93EB1D8045260C840B0688EC8F":{n:"3E Bankswitch Test (TIA @ $00)"}, "9B150A42FC788960FBB4CBE250259EE2":{n:"3E Bankswitch Test (TIA @ $40)"}, "703F0F7AF350B0FA29DFE5FBF45D0D75":{n:"4 Game in One Dark Green (1983) (BitCorp) (PAL)"}, "31BB9B8CEED46CB3E506777A9E65F3CE":{n:"4 Game in One Light Green (1983) (BitCorp) (PAL)"}, "FE6ABC0F63E31E2646C9C600926B5B7F":{n:"4 in 1 (02-19-1987) (Atari) (Prototype)"}, "6D218DAFBF5A691045CDC1F67CEB6A8F":{n:"6 Digit Score Display (1998) (Robin Harbron) (PD)"}, "7465B06B6E25A4A6C6D77D02242AF6D6":{n:"8 in 1 (01-16-92) (Atari) (Prototype)"}, "2CEFA695DF2ED020899A7DF7BB1E3A95":{n:"A-Team (2002) (Manuel Polik) (Hack)"}, "DAFC3945677CCC322CE323D1E9930BEB":{n:"A-Team (Atari) (Prototype) (PAL)"}, "C02E1AFA0671E438FD526055C556D231":{n:"A-Team (Atari) (Prototype) (PAL60)"}, "C00734A2233EF683D9B6E622AC97A5C8":{n:"A-Team, The (03-30-1984) (Atari) (Prototype)"}, "CD5AF682685CFECBC25A983E16B9D833":{n:"A-Team, The (05-08-1984) (Atari) (Prototype)"}, "537ED1E0D80E6C9F752B33EA7ACBE079":{n:"A-VCS-tec Challenge (beta 5) (PD)"}, "8786C1E56EF221D946C64F6B65B697E9":{n:"AKA Space Adventure"}, "00F7985C20B8BDF3C557FAC4D3F26775":{n:"AStar (NTSC)"}, "3FD1F9D66A418C9F787FC5799174DDB7":{n:"AStar (PAL)"}, "A3FEE8CE15525EA00D45A06F04C215D1":{n:"AStar (PAL60)"}, "17EE23E5DA931BE82F733917ADCB6386":{n:"Acid Drop (1992) (Salu) (PAL)"}, "09274C3FC1C43BF1E362FDA436651FD8":{n:"Acid Drop (TJ)"}, "B9F6FA399B8CD386C235983EC45E4355":{n:"Action Force (1983) (Parker Bros) (PAL)",p:1}, "D573089534CA596E64EFEF474BE7B6BC":{n:"Action Force (1983) (Parker Bros) (PAL) [a]",p:1}, "543B4B8FF1D616FA250C648BE428A75C":{n:"Adventure (1978) (Warren Robinett) (Hack)"}, "157BDDB7192754A45372BE196797F284":{n:"Adventure (1980) (Atari)"}, "4B27F5397C442D25F0C418CCDACF1926":{n:"Adventure (1980) (Atari) (PAL)"}, "9BE58A14E055B0E7581FC4D6C2F6B31D":{n:"Adventure (Color Scrolling) (Hack)"}, "A5B7F420CA6CC1384DA0FED523920D8E":{n:"Adventure (New Graphics) (Hack)"}, "171CD6B55267573E6A9C2921FB720794":{n:"Adventure 34 (Kurt Howe) (Hack)"}, "E923001015BEDD7901569F035D9C592C":{n:"Adventure II (Hack)"}, "E2846AF3E4D172B251AB77CBDD01761E":{n:"Adventure Plus (2003) (Steve Engelhardt) (Hack)"}, "CA4F8C5B4D6FB9D608BB96BC7EBD26C7":{n:"Adventures of TRON (1982) (M Network)"}, "06CFD57F0559F38B9293ADAE9128FF88":{n:"Adventures on GX-12 (1989) (Telegames) (PAL)"}, "35BE55426C1FEC32DFB503B4F0651572":{n:"Air Raid (Men-A-Vision) (PAL)",c:1}, "A9CB638CD2CB2E8E0643D7A67DB4281C":{n:"Air Raiders (1982) (M Network)"}, "F066BEA7AB0A37B83C83C924A87C5B67":{n:"Air Raiders (1982) (Unknown)"}, "DA0FB2A484D0D2D8F79D6E063C94063D":{n:"Air Raiders (1982) (Unknown) [a]"}, "CF3A9ADA2692BB42F81192897752B912":{n:"Air Raiders (Unknown) (PAL)"}, "16CB43492987D2F32B423817CDAAF7C4":{n:"Air-Sea Battle (1977) (Atari)"}, "1D1D2603EC139867C1D1F5DDF83093F1":{n:"Air-Sea Battle (1977) (Atari) (4K)"}, "0C7926D660F903A2D6910C254660C32C":{n:"Air-Sea Battle (1977) (Atari) (PAL)"}, "8AAD33DA907BED78B76B87FCEAA838C1":{n:"Air-Sea Battle (32 in 1) (1988) (Atari) (PAL)"}, "605DCB73D22F4EFDB90EF9DA2F290F7C":{n:"Air-Sea Battle (32 in 1) (1988) (Atari) (PAL) (4K)"}, "98E5E4D5C4DD9A986D30FD62BD2F75AE":{n:"Air-Sea Battle (Unknown) (Hack) (4K)"}, "E5FCC62E1D73706BE7B895E887E90F84":{n:"Air-Sea Battle (Unknown) (PAL) (4K)"}, "4D77F291DCA1518D7D8E47838695F54B":{n:"Airlock (1982) (Data Age)"}, "8C7E5E2329F4F4E06CBCC994A30FD352":{n:"Airlock (1982) (Data Age) (Prototype)"}, "F1A0A23E6464D954E3A9579C4CCD01C8":{n:"Alien (1982) (20th Century Fox)",c:1}, "956496F81775DE0B69A116A0D1AD41CC":{n:"Alien (CCE)",c:1}, "1287535256BF5DFF404839AC9E25C3E7":{n:"Alien Pac-Man (PacManPlus) (Hack)",c:1}, "E1A51690792838C5C687DA80CD764D78":{n:"Alligator People (1983) (20th Century Fox) (Prototype)"}, "DF95E4AF466C809619299F49ECE92365":{n:"Alpha Beam with Ernie (06-03-1983) (Atari) (Prototype) (PAL)"}, "8F5AC5139419C5D49BACC296E342A247":{n:"Alpha Beam with Ernie (12-22-1983) (Atari) (Prototype)"}, "9E01F7F95CB8596765E03B9A36E8E33C":{n:"Alpha Beam with Ernie (1983) (Atari)"}, "F2D40C70CF3E1D03BC112796315888D9":{n:"Alpha Beam with Ernie (1983) (Atari) (PAL)"}, "B0BA51723B9330797985808DB598FC31":{n:"Alpha Beam with Ernie (1983) (Atari) (PAL) [a]"}, "2A10053FD08664C7CFBBB104386ED77F":{n:"Alpha Demo - The Beta Demo (2000) (MP)"}, "FDF6680B2B1E8054293A39700A765692":{n:"Alpha Demo - The Beta Demo 2 (2000) (MP)"}, "26BC2BDF447A17376AEA7EF187FF6E44":{n:"Amanda Invaders (PD)"}, "51F15B39D9F502C2361B6BA6A73464D4":{n:"Amanda Invaders (PD) [a]"}, "ACB7750B4D0C4BD34969802A7DEB2990":{n:"Amidar (1982) (Parker Bros)"}, "056F5D886A4E7E6FDD83650554997D0D":{n:"Amidar (1982) (Parker Bros) (PAL)"}, "6354F9C7588A27109C66905B0405825B":{n:"Amidar DS (2003) (TJ) (Hack)"}, "93B9229FC0EA4FB959D604F83F8F603C":{n:"Amidar DS (Fast Enemies) (2003) (TJ) (Hack)"}, "5BD79139A0C03B63F6F2CF00A7D385D2":{n:"An Exercise In Minimalism (V1) (1999) (Marc de Smet) (PD)"}, "6F74ED915FFE73B524EF0F63819E2A1D":{n:"An Exercise In Minimalism (V2) (1999) (Eckhard Stolberg)"}, "E39A13B13DC82C5FDBFBBFD55BA1230E":{n:"Analog Clock (Additional Frame Info) (V0.0) (20-01-2003) (AD)"}, "0AE3497E731CA0BF6A77B23441D9D9F9":{n:"Analog Clock (V0.0) (20-01-2003) (AD)"}, "335793736CBF6FC99C9359ED2A32A49D":{n:"Analog Clock (V0.0) (20-01-2003) (AD) [a]"}, "63C5FEF3208BB1424D26CF1AB984B40C":{n:"Analog Clock (V0.1) (20-01-2003) (AD)"}, "FC9C1652FE3A2CADE6188F4D3692481F":{n:"Andrew Davies early notBoulderDash demo (NTSC)",c:1}, "4C606235F4EC5D2A4B89139093A69437":{n:"Andrew Davies early notBoulderDash demo (PAL)",c:1}, "0866E22F6F56F92EA1A14C8D8D01D29C":{n:"AndroMan on the Moon (1984) (Western Tech) (Prototype)"}, "6672DE8F82C4F7B8F7F1EF8B6B4F614D":{n:"Angeln I (Ariola) (PAL)"}, "ADF1AFAC3BDD7B36D2EDA5949F1A0FA3":{n:"Angriff der Luftflotten (1983) (Quelle) (PAL)"}, "AFE4EEFC7D885C277FC0649507FBCD84":{n:"Ant Party (32 in 1) (1988) (Atari) (PAL)",c:1}, "6B01A519B413F8CFA2F399F4D2841B42":{n:"Aphex Invaders (Hack)"}, "E73838C43040BCBC83E4204A3E72EEF4":{n:"Apples and Dolls (CCE)",c:1}, "038E1E79C3D4410DEFDE4BFE0B99CC32":{n:"Aquaventure (08-12-1983) (Atari) (Prototype)"}, "F69D4FCF76942FCD9BDF3FD8FDE790FB":{n:"Aquaventure (CCE)"}, "A7B584937911D60C120677FE0D47F36F":{n:"Armor Ambush (1982) (M Network)"}, "D0AF33865512E9B6900714C26DB5FA23":{n:"Armor Ambush (1989) (Telegames) (PAL)"}, "C77C35A6FC3C0F12BF9E8BAE48CBA54B":{n:"Artillery Duel (1983) (Xonox)"}, "589C73BBCD77DB798CB92A992B4C06C3":{n:"Artillery Duel (1983) (Xonox) (PAL)"}, "D341D39774277CEE6A1D378A013F92AC":{n:"Artillery Duel (1983) (Xonox) (PAL) [a]"}, "3F039981255691D3859D04EF813A1264":{n:"Artillery Duel (1983) (Xonox) [a]"}, "3750F2375252B6A20E4628692E94E8B1":{n:"Ases do Ar (Dismac)"}, "DE78B3A064D374390AC0710F95EDDE92":{n:"Assault (1983) (Bomb)"}, "327468D6C19697E65AB702F06502C7ED":{n:"Aster-Hawk (2002) (Charles Morgan) (Hack)",c:1}, "89A68746EFF7F266BBF08DE2483ABE55":{n:"Asterix (1983) (Atari)"}, "FAEBCB2EF1F3831B2FC1DBD39D36517C":{n:"Asterix (1983) (Atari) (PAL)"}, "C5C7CC66FEBF2D4E743B4459DE7ED868":{n:"Asterix (1983) (Atari) (PAL) [a]"}, "47B82D47E491AC7FDB5053A88FCCC832":{n:"Asteroid 2 (Atari Freak 1) (Hack)",c:1}, "18F299EDB5BA709A64C80C8C9CEC24F2":{n:"Asteroid Fire (1983) (Home Vision) (PAL)"}, "DD7884B4F93CAB423AC471AA1935E3DF":{n:"Asteroids (1981) (Atari)",c:1}, "8CF0D333BBE85B9549B1E6B1E2390B8D":{n:"Asteroids (1981) (Atari) (PAL)",c:1}, "A957DBE7D85EA89133346AD56FBDA03F":{n:"Asteroids (1981) (Atari) (PAL) [a1]",c:1}, "19ABAF2144B6A7B281C4112CFF154904":{n:"Asteroids (1981) (Atari) (PAL) [a2]",c:1}, "BB5049E4558DAADE0F87FED69A244C59":{n:"Asteroids (1981) (Atari) (PAL) [no copyright]",c:1}, "B227175699E372B8FE10CE243AD6DDA5":{n:"Asteroids (1981) (Atari) [a1]",c:1}, "D563BA38151B8204C9F5C9F58E781455":{n:"Asteroids (1981) (Atari) [a2]",c:1}, "CCBD36746ED4525821A8083B0D6D2C2C":{n:"Asteroids (1981) (Atari) [no copyright]",c:1}, "3E4B1137433CC1E617B5508619E13063":{n:"Asteroids (Genesis)",c:1}, "DF40AF244A8D68B492BFBA9E97DEA4D6":{n:"Asteroids 2 (Franlin Cruz) (Hack)",c:1}, "2DBDCA3058035D2B40C734DCF06A86D9":{n:"Asteroids DC+ (Thomas Jentzsch) (Hack)",c:1}, "8DF4BE9DDC54AC363B13DC57CEAF161A":{n:"Asteroids SS (Scott Stilphen) (Hack)",c:1}, "75169C08B56E4E6C36681E599C4D8CC5":{n:"Astroblast (1982) (M Network)",p:1}, "170E7589A48739CFB9CC782CBB0FE25A":{n:"Astroblast (1982) (M Network) [fixed]",p:1}, "46E9428848C9EA71A4D8F91FF81AC9CC":{n:"Astroblast (1989) (Telegames) (PAL)",p:1}, "8F53A3B925F0FD961D9B8C4D46EE6755":{n:"Astrowar (Unknown)"}, "E643AAEC9A9E1C8AB7FE1EAE90BC77D7":{n:"Asymmetric Playfield (Roger Williams)"}, "4B753A97AEE91E4B3E4E02F5E9758C72":{n:"Asymmetric Reflected Playfield (Glenn Saunders)"}, "A4AA7630E4C0AD7EBB9837D2D81DE801":{n:"Atari 2600 Invaders (Hack)"}, "D0A379946ED77B1B126230CA68461333":{n:"Atari Invaders (Ataripoll) (Hack)"}, "D61629BBBE035F45552E31CEF7D591B2":{n:"Atari Logo Demo (PD) (PAL)"}, "E932F44FAD2A66B6D5FAEC9ADDEC208E":{n:"Atari Logo Demo 1 (PD)"}, "13D8326BF5648DB4DAFCE45D25E62DDD":{n:"Atari Logo Demo 2 (PD)"}, "3E49DA621193D2611A4EA152D5D5CA3A":{n:"Atari Logo Demo 3 (PD)"}, "42E0EC5AB8F5DEBA53E4169FF2A5EFBE":{n:"Atari Logo Demo 5 (PD)"}, "9526E3DB3BDFBC27989A9CBFD0EE34BF":{n:"Atari Logo Demo 6 (PD)"}, "5DF32450B9FBCAF43F9D83BD66BD5A81":{n:"Atari Logo Playfield Demo (2001) (Eric Ball) (PD)"}, "4EDB251F5F287C22EFC64B3A2D095504":{n:"Atari VCS Point-of-Purchase ROM (1982) (Atari)"}, "3F540A30FDEE0B20AED7288E4A5EA528":{n:"Atari Video Cube (1982) (Atari)"}, "2CA6445204FFB7686DDEE3E33BA64D5B":{n:"AtariVox Test ROM"}, "9AD36E699EF6F45D9EB6C4CF90475C9F":{n:"Atlantis (1982) (Imagic)"}, "ACB962473185D7A652F90ED6591AE13B":{n:"Atlantis (1982) (Imagic) (16K)"}, "5324CF5B6DC17AF4C64BF8696C39C2C1":{n:"Atlantis (1982) (Imagic) (8K)"}, "3D2367B2B09C28F1659C082BB46A7334":{n:"Atlantis (1982) (Imagic) (PAL)"}, "41818738AB1745E879024A17784D71F5":{n:"Atlantis (1983) (CCE)"}, "0B33252B680B65001E91A411E56E72E9":{n:"Atlantis (1983) (CCE) [a]"}, "71B193F46C88FB234329855452DFAC5B":{n:"Atlantis (1983) (Digitel)"}, "3AAD0EF62885736A5B8C6CCAC0DBE00C":{n:"Atlantis (1983) (Dynacom)"}, "6CEA35DED079863A846159C3A1101CC7":{n:"Atlantis (208 in 1) (Unknown) (PAL) (Hack)"}, "A1403FEF01641DCD3980CAC9F24D63F9":{n:"Atlantis (Dactari - Milmar)"}, "72BDA70C75DFA2365B3F8894BACE9E6A":{n:"Atlantis (TJ) (Hack)"}, "C4BBBB0C8FE203CBD3BE2E318E55BCC0":{n:"Atlantis (Unknown) (PAL) (Hack)"}, "AC0DDBCFF34D064009591607746E33B8":{n:"Atlantis FH (2003) (TJ) (Hack)"}, "826481F6FC53EA47C9F272F7050EEDF7":{n:"Atlantis II (1982) (Imagic)"}, "A7CF2B9AFDBB3A161BF418DBCF0321DC":{n:"Attack Of The Mutant Space Urchins (2002) (Barry Laws Jr.) (Hack)",c:1}, "B5110F55ED99D5279F18266D001A8CD5":{n:"Auto-mobile Demo (2001) (Eckhard Stolberg)"}, "B4F87CE75F7329C18301A2505FE59CD3":{n:"Autorennen (Ariola) (PAL)"}, "7C757BB151269B2A626C907A22F5DAE7":{n:"BMX Air Master (1989) (TNT Games) (PAL)"}, "968EFC79D500DCE52A906870A97358AB":{n:"BMX Air Master (1990) (Atari)"}, "4F89B897444E7C3B36AED469B8836839":{n:"BMX Air Master (1990) (Atari) (PAL)"}, "4E2C884D04B57B43F23A5A2F4E9D9750":{n:"Baby Center Animation (PD)",c:1}, "5B124850DE9EEA66781A50B2E9837000":{n:"Bachelor Party (1982) (PlayAround)",p:1,c:1}, "274D17CCD825EF9C728D68394B4569D2":{n:"Bachelorette Party (1982) (Playaround)",p:1,c:1}, "8556B42AA05F94BC29FF39C39B11BFF4":{n:"Backgammon (1979) (Atari)",p:1}, "85B1BCA93E69F13905107CC802A02470":{n:"Backgammon (1979) (Atari) (PAL)",p:1}, "4E4895C3381AA4220F8C2795D6338237":{n:"Backwards Cannonball v1 (Hack)"}, "2A33E21447BF9E13DCFED85077FF6B40":{n:"Backwards Cannonball v2 (Hack)"}, "FCEA12625C071DDC49F4E409F4038C60":{n:"Balls! (16-09-2002) (Fabrizio Zavagli)",c:1}, "805F9A32EF97AC25F999A25014DC5C23":{n:"Balthazar (SnailSoft)",c:1}, "00CE0BDD43AED84A983BEF38FE7F5EE3":{n:"Bank Heist (1983) (20th Century Fox)"}, "83B8C01C72306D60DD9B753332EBD276":{n:"Bank Heist (208 in 1) (Unknown) (PAL)"}, "E9C71F8CDBA6037521C9A3C70819D171":{n:"Bank Heist (PAL)"}, "C2A37F1C7603C5FD97DF47D6C562ABFA":{n:"Bar-Score Demo (2001) (Roger Williams)"}, "73A710E621D44E97039D640071908AEF":{n:"Barber Pole Demo (PD)"}, "F8240E62D8C0A64A61E19388414E3104":{n:"Barnstorming (1982) (Activision)"}, "A29FC854838E08C247553A7D883DD65B":{n:"Barnstorming (1982) (Activision) (16K)"}, "9AEB5206C5BF974892A9CC59F1478DB3":{n:"Barnstorming (1982) (Activision) (8K)"}, "E7DD8C2E6C100044002C1086D02B366E":{n:"Barnstorming (1982) (Activision) (PAL)"}, "5AE73916FA1DA8D38CEFF674FA25A78A":{n:"Barnstorming (CCE)"}, "9AD362179C2EEA4EA115C7640B4B003E":{n:"Barnstorming (Unknown) (PAL)"}, "DCEC46A98F45B193F07239611EB878C2":{n:"Bars and Text Demo (PD)"}, "D7891B0FAA4C7F764482762D0ED427A5":{n:"Bars and Text Demo 2 (PD)"}, "600D48EEF5C0EC27DB554B7328B3251C":{n:"Bars and Text Demo 3 (PD)"}, "C469151655E333793472777052013F4F":{n:"Base Attack (Unknown) (Hack)"}, "034C1434280B0F2C9F229777D790D1E1":{n:"Baseball (1989) (Telegames) (PAL)"}, "9848B5EF7A0C02FE808B920A2AC566D2":{n:"Baseball (2002) (Skyworks)"}, "A41450333F8DD0E96E5E9F0AF3770AE9":{n:"Basic Math (208 in 1) (Unknown) (PAL)"}, "7EAB0284A0CD1043461D446A08D08CEC":{n:"Basic Math (Jone Yuan) (4K)"}, "9F48EEB47836CF145A15771775F0767A":{n:"Basic Programming (1979) (Atari)",c:1}, "B061E98A4C854A672AADEFA233236E51":{n:"Basic Programming (1979) (Atari) (PAL)",c:1}, "AB4AC994865FB16EBB85738316309457":{n:"Basketball (1978) (Atari)"}, "E13C7627B2E136B9C449D9E8925B4547":{n:"Basketball (1978) (Atari) (4K)"}, "218C0FE53DFAAA37F3C823F66EAFD3FC":{n:"Basketball (1978) (Atari) (PAL)"}, "F4AB6BD5F80D8988141EDDE4C84B23B5":{n:"Basketball (1978) (Atari) (PAL) (4K)"}, "77BE57D872E3F5B7ECF8D19D97F73281":{n:"Basketball (208 in 1) (Unknown) (PAL)"}, "5D132D121AABC5235DD039DFC46AA024":{n:"Basketball (208 in 1) (Unknown) (PAL) (Hack)"}, "1228C01CD3C4B9C477540C5ADB306D2A":{n:"Basketball (32 in 1) (1988) (Atari) (PAL)"}, "32D1260EA682E1BB10850FA94C04EC5F":{n:"Basketball (32 in 1) (1988) (Atari) (PAL) (4K)"}, "5C0227AD63300670A647FCEBF595EA37":{n:"Battle for Naboo (Josh) (Hack)"}, "E434C0E161DD3C3FB435EB6BAD2E182C":{n:"Battlezone (05-02-1983) (Atari) (Prototype)"}, "5B85E987E2B1618769D97BA9182333D0":{n:"Battlezone (05-12-1983) (Atari) (Prototype)"}, "41F252A66C6301F1E8AB3612C19BC5D4":{n:"Battlezone (1983) (Atari)"}, "FBE554AA8F759226D251BA6B64A9CCE4":{n:"Battlezone (1983) (Atari) (PAL)"}, "E38DC1F81A02E325562CD285123F579B":{n:"Battlezone (1983) (Atari) (PAL) [a1]"}, "2319922DF4D0C820B3E5F15FAA870CC3":{n:"Battlezone (1983) (Atari) (PAL) [a]"}, "6015A9CEF783E97E98A2AA2CF070AE06":{n:"Battlezone TC (Thomas Jentzsch) (Hack)"}, "38C362DCD5CAD5A62E73AE52631BD9D8":{n:"Baubles (14-11-2001) (Jake Patterson) (PD)"}, "3EB1E34A4F0EEC36F12E7336BADCECF2":{n:"Baubles (V0.001) (2001) (Jake Patterson) (PD)"}, "599CBF919D47A05AF975AD447DF29497":{n:"Baubles (V0.002) (2001) (Jake Patterson) (PD)"}, "FBFEBEE9C14694719E3EDA4854DC42EE":{n:"Baubles 3 (Jake Patterson) (PD)"}, "79AB4123A83DC11D468FB2108EA09E2E":{n:"Beamrider (1984) (Activision)"}, "FEC0C2E2AB0588ED20C750B58CF3BAA3":{n:"Beamrider (1984) (Activision) (PAL)"}, "F4204FC92D17ED4CB567C40361AD58F1":{n:"Beanie Baby Bash (Inky) (Hack)"}, "D0B9DF57BFEA66378C0418EC68CFE37F":{n:"Beany Bopper (1982) (20th Century Fox)"}, "6A9E0C72FAB92DF70084ECCD9061FDBD":{n:"Beany Bopper (1983) (CCE)"}, "235436AB0832370E73677C9C6F0C8B06":{n:"Beast Invaders (Double Shot) (Hack)"}, "4D0A28443F7DF5F883CF669894164CFA":{n:"Beast Invaders (Hack)"}, "B4F31EA8A6CC9F1FD4D5585A87C3B487":{n:"Beat 'Em & Eat 'Em (1982) (Mystique) (PAL)",p:1}, "59E96DE9628E8373D1C685F5E57DCF10":{n:"Beat 'Em & Eat 'Em (1982) (PlayAround)",p:1}, "6C25F58FD184632CA76020F589BB3767":{n:"Beat 'Em & Eat 'Em (1983) (Dynacom)",p:1}, "EE6665683EBDB539E89BA620981CB0F6":{n:"Berenstain Bears (1983) (Coleco)"}, "073D7AFF37B7601431E4F742C36C0DC1":{n:"Bermuda (Unknown) (PAL)"}, "B8ED78AFDB1E6CFE44EF6E3428789D5F":{n:"Bermuda Triangle (1982) (Data Age)"}, "36C993DC328933E4DD6374A8FFE224F4":{n:"Bermuda Triangle (1983) (Gameworld) (PAL)"}, "BCEF7880828A391CF6B50D5A6DCEF719":{n:"Bermuda, The (Rainbow Vision) (PAL)"}, "CF3C2725F736D4BCB84AD6F42DE62A41":{n:"Bermuda, The (Rainbow Vision) (PAL) [a]"}, "136F75C4DD02C29283752B7E5799F978":{n:"Berzerk (1982) (Atari)"}, "0805366F1B165A64B6D4DF20D2C39D25":{n:"Berzerk (1982) (Atari) (PAL)"}, "FAC28963307B6E85082CCD77C88325E7":{n:"Berzerk (CCE)"}, "4B205EF73A5779ACC5759BDE3F6D33ED":{n:"Berzerk (Unknown) (PAL)"}, "490E3CC59D82F85FAE817CDF767EA7A0":{n:"Berzerk (Unknown) (PAL) [a]"}, "BE41463CD918DAEF107D249F8CDE3409":{n:"Berzerk (Voice Enhanced) (Hack)"}, "5C618A50DFA23DAAC97BA459B9FF5206":{n:"Berzerk Renegade (2002) (Steve Engelhardt) (Hack)",c:1}, "4C4CE802CBFD160F7B3EC0F13F2A29DF":{n:"Beta Demo (V1.1) (26-09-2002) (MP)"}, "63A7445B1D3046D3CDCDBD488DCA38D9":{n:"Better Space Invaders (1999) (Rob Kudla) (Hack)"}, "012020625A3227815E47B37FD025E480":{n:"Better Space Invaders (1999) (Rob Kudla) (Hack) [a]"}, "4D5F6DB55F7F44FD0253258E810BDE21":{n:"Betterblast (Fabrizio Zavagli) (Hack)"}, "7CD900E9ECCBB240FE9C37FA28F917B5":{n:"Bi! Bi! (Jone Yuan) (PAL)"}, "F714A223954C28ECCF459295517DCAE6":{n:"Big - Move This Demo (PD)"}, "16CC6D1B4DDCE51C767A1BA8E5FF196C":{n:"Big - Move This Demo 2 (PD)",c:1}, "151FA3218D8D7600114EB5BCD79C85CB":{n:"Big Bird's Egg Catch (05-02-1983) (Atari) (Prototype)"}, "0B17ED42984000DA8B727CA46143F87A":{n:"Big Bird's Egg Catch (05-17-1983) (Atari) (Prototype)"}, "AFD2CF258D51AE4965EE21ABBA3627AB":{n:"Big Bird's Egg Catch (12-08-1982) (Atari) (Prototype)"}, "1802CC46B879B229272501998C5DE04F":{n:"Big Bird's Egg Catch (1983) (Atari)"}, "F283CC294ECE520C2BADF9DA20CFC025":{n:"Big Bird's Egg Catch (1983) (Atari) (PAL)"}, "2CB42CF62B2F25F59F909B5447821B14":{n:"Big Bird's Egg Catch (1983) (Atari) (PAL) [a]"}, "F8FF34B53D86F55BD52D7A520AF6D1DC":{n:"Big Dig (04-04-2003) (CT)"}, "7CCF350354EE15CD9B85564A2014B08C":{n:"Big Dig (13-04-2003) (CT)"}, "23E4CA038ABA11982E1694559F3BE10F":{n:"Big Dig (V3) (20-10-2002) (CT)"}, "93C9F9239A4E5C956663DD7AFFA70DA2":{n:"Billard (1983) (Quelle) (PAL)",c:1}, "BD1BD6F6B928DF17A702DEF0302F46F4":{n:"Binary To Decimal Routine (2001) (AD)"}, "84535AFB9A69712EC0AF4947329E08B8":{n:"Bingo (1983) (CCE) (PAL)"}, "10F0ECAF962AEF1FC28ABED870B01B65":{n:"Bionic Breakthrough (06-22-1984) (Atari) (Prototype)"}, "F0541D2F7CDA5EC7BAB6D62B6128B823":{n:"Bionic Breakthrough (1984) (Atari) (Prototype)"}, "AA8E4B2CB8A78FFE6B20580033F4DEC9":{n:"Bitmap Demo (13-01-2003) (AD)"}, "282A77841CB3D33AF5B56151ACBA770E":{n:"Black Hole (1983) (Quelle) (PAL)"}, "CBEAFD37F15E0DDDB0540DBE15C545A4":{n:"Black and White Fast Scolling Demo (PD)"}, "0A981C03204AC2B278BA392674682560":{n:"Blackjack (1977) (Atari)",p:1}, "B2761EFB8A11FC59B00A3B9D78022AD6":{n:"Blackjack (1977) (Atari) (4K)",p:1}, "FF3BD0C684F7144AEAA18758D8281A78":{n:"Blackjack (1977) (Atari) (PAL)",p:1}, "FF7627207E8AA03730C35C735A82C26C":{n:"Blackjack (32 in 1) (1988) (Atari) (PAL)",p:1}, "D726621C676552AFA503B7942AF5AFA2":{n:"Blackjack (32 in 1) (1988) (Atari) (PAL) (4K)",p:1}, "575C0FB61E66A31D982C95C9DEA6865C":{n:"Blackjack (Unknown) (PAL)",p:1}, "19A9D3F9FA1B1358FB53009444247AAF":{n:"Blackjack (Unknown) (PAL) (4K)",p:1}, "93420CC4CB1AF1F2175C63E52EC18332":{n:"Blair Witch Project (Tim Snider) (Hack)"}, "07C76F2D88552D20AD2C0ED7AEF406C6":{n:"Blob (Cody Pittman) (Hack)"}, "1086FF69F82B68D6776634F336FB4857":{n:"Bloody Human Freeway (Activision) (Prototype)"}, "FCF8E306F6615F74FEBA5CB25550038C":{n:"Blue Dot Demo (PD)"}, "2942680C47BEB9BF713A910706FFABFE":{n:"Blue Line Demo (PD)"}, "B7F184013991823FC02A6557341D2A7A":{n:"Blue Rod Demo (PD)"}, "DAD2AB5F66F98674F12C92ABCFBF3A20":{n:"Blue and White Sprite Demo (PD)"}, "33D68C3CD74E5BC4CF0DF3716C5848BC":{n:"Blueprint (1983) (CBS Electronics)",c:1}, "2432F33FD278DEA5FE6AE94073627FCC":{n:"Blueprint (1983) (CBS Electronics) (PAL)",c:1}, "345488D3B014B684A181108F0EF823CB":{n:"Blueprint (1983) (CBS Electronics) (Prototype)"}, "6FBD05B0AD65B2A261FA154B34328A7F":{n:"Boardgame Demo (20-12-2002) (CT)"}, "EBCB084A91D41865B2C1915779001CA7":{n:"Bob Is Going Home (JVP)"}, "521F4DD1EB84A09B2B19959A41839AAD":{n:"Bobby Is Going Home (1983) (BitCorp)"}, "2823364702595FEEA24A3FBEE138A243":{n:"Bobby Is Going Home (1983) (BitCorp) (PAL)"}, "CCB56107FF0492232065B85493DAA635":{n:"Bobby Is Going Home (1983) (BitCorp) (PAL) [demo cart]"}, "075069AD80CDE15ECA69E3C98BD66714":{n:"Bobby Is Going Home (1983) (CCE)"}, "3CBDF71BB9FD261FBC433717F547D738":{n:"Bobby Is Going Home (1983) (CCE) (PAL)"}, "F2F59629D7341C97644405DAEAC08845":{n:"Bobby Is Going Home (Jone Yuan)"}, "2F2F9061398A74C80420B99DDECF6448":{n:"Bobby Is Going Home (Rentacom)"}, "48E5C4AE4F2D3B62B35A87BCA18DC9F5":{n:"Bobby geht nach Hause (1983) (Quelle) (PAL)"}, "AFE776DB50E3378CD6F29C7CDD79104A":{n:"Bobby is Going Home (TJ)"}, "C59633DBEBD926C150FB6D30B0576405":{n:"Bogey Blaster (1989) (Telegames)"}, "B438A6AA9D4B9B8F0B2DDB51323B21E4":{n:"Bogey Blaster (1989) (Telegames) (PAL)"}, "A5855D73D304D83EF07DDE03E379619F":{n:"Boggle (08-07-1978) (Atari) (Prototype)",c:1}, "14C2548712099C220964D7F044C59FD9":{n:"Boing! (1983) (First Star Software)",c:1}, "C471B97446A85304BBAC021C57C2CB49":{n:"Boing! (1983) (First Star Software) (PAL)",c:1}, "0E08CD2C5BCF11C6A7E5A009A7715B6A":{n:"Boing! (PD) [a1]"}, "5D8FB14860C2F198472B233874F6B0C9":{n:"Boing! (PD) [a2]"}, "956B99511C0F47B3A11D18E8B7AC8D47":{n:"Bones (Arcade Golf Hack)"}, "E5359CBBBFF9C6D7FE8AEFF5FB471B46":{n:"Boom Bang (1983) (CCE)"}, "7F54FA6AA824001AF415503C313262F2":{n:"Boom Bang (HES) (PAL)"}, "A2AAE759E4E76F85C8AFEC3B86529317":{n:"Boom Bang (Unknown)"}, "2825F4D068FEBA6973E61C84649489FE":{n:"Boom Bang (Unknown) (PAL)"}, "02E3F4BA156FB578BEF7D7A0BF3400C1":{n:"Booster (Junkosoft) (PD)"}, "5BC9998B7E9A970E31D2CB60E8696CC4":{n:"Borgwars Asteroids (2003) (Jack Kortkamp) (Hack)",c:1}, "05F11FB2E45C4E47424D3CB25414D278":{n:"Boring (NTSC) (AD)"}, "9B246683F44C963A50E41D6B485BEE77":{n:"Boring (PAL) (AD)"}, "F0CACAE1D1B79EE92F0DC035F42E0560":{n:"Boring Donkey Kong (Hack)"}, "CE17325834BF8B0A0D0D8DE08478D436":{n:"Boring Freeway (Hack)"}, "1733772165D7B886A94E2B4ED0F74CCD":{n:"Boring Journey Escape (Hack)"}, "613ABF596C304EF6DBD8F3351920C37A":{n:"Boring Pac-Man (Hack)"}, "96670D0BF3610DA2AFCABD8E21D8EABF":{n:"Boring Pitfall (Hack)"}, "E8E7B9BDF4BF04930C2BCAA0278EE637":{n:"Boring Taz (Hack)"}, "8A49CF1785E3DEA2012D331A3AD476E1":{n:"Boulderdash (10 Blocks Wide) (02-04-2003) (AD)"}, "E0DE3773F5B867795DB557BE7B8A703E":{n:"Boulderdash (13 Blocks Wide) (02-04-2003) (AD)"}, "29DFA26B7988AF9984D617708E4FC6E2":{n:"Boulderdash Demo (05-04-2003) (AD)"}, "68CD2ADC6B1FC9A1F263AB4561112F30":{n:"Boulderdash Demo (09-12-2002) (TJ)",c:1}, "D90205E29BB73A4CDF28EA7662BA0C3C":{n:"Boulderdash Demo (Brighter Version) (09-12-2002) (TJ)",c:1}, "B2D1E63F7F22864096B7B6C154151D55":{n:"Bounce! (17-03-2003) (Fabrizio Zavagli)",c:1}, "7EAF009A892F03D90682DC1E67E85F07":{n:"Bounce! (18-03-2003) (Fabrizio Zavagli)",c:1}, "C9B7AFAD3BFD922E006A6BFC1D4F3FE7":{n:"Bowling (1979) (Atari)"}, "A28D872FC50FA6B64EB35981D0F4BB8D":{n:"Bowling (1979) (Atari) (4K)"}, "2AA5E56D36C2E58B6F2856109F2099A9":{n:"Bowling (1979) (Atari) (4K) [a]"}, "969B968383D9F0E9D8FFD1056BCAEF49":{n:"Bowling (1979) (Atari) (PAL)"}, "82C25D1C35E6AC6F893D1D7C2FC2F9C8":{n:"Bowling (1979) (Atari) (PAL) (4K)"}, "11E7E0D9437EC98FA085284CF16D0EB4":{n:"Bowling (208 in 1) (Unknown) (PAL)"}, "F69BB58B815A6BDCA548FA4D5E0D5A75":{n:"Bowling (32 in 1) (1988) (Atari) (PAL)"}, "4B71197153D651480830638CB6A03249":{n:"Bowling (32 in 1) (1988) (Atari) (PAL) (4K)"}, "32ECB5A652EB73D287E883EEA751D99C":{n:"Bowling (Dactar - Milmar)"}, "58746219D8094EDFF869F0F5C2AEAAD5":{n:"Bowling (Jone Yuan) (4K)"}, "7F07CD2E89DDA5A3A90D3AB064BFD1F6":{n:"Boxen (Ariola) (PAL)"}, "C3EF5C4653212088EDA54DC91D787870":{n:"Boxing (1980) (Activision)"}, "88F74EC75EF696E7294B7B6AC5CA465F":{n:"Boxing (1980) (Activision) (16K)"}, "277CCA62014FCEEBB46C549BAC25A2E3":{n:"Boxing (1980) (Activision) (4K)"}, "5A80B857EB8B908AB477EC4EF902EDC8":{n:"Boxing (1980) (Activision) (8K)"}, "25F2E760CD7F56B88AAC88D63757D41B":{n:"Boxing (1980) (Activision) (PAL)"}, "C2BCD8F2378C3779067F3A551F662BB7":{n:"Boxing (1980) (Activision) (PAL) (4K)"}, "A8B3EA6836B99BEA77C8F603CF1EA187":{n:"Boxing (1983) (CCE)"}, "2C45C3EB819A797237820A1816C532EB":{n:"Boxing (32 in 1) (1988) (Atari) (PAL)"}, "B77468D586957D1B7FB4CCCDA2684F47":{n:"Boxing (32 in 1) (1988) (Atari) (PAL) (4K)"}, "CFB3260C603B0341D49DDFC94051EC10":{n:"Boxing (Dactari - Milmar)"}, "34FD4FCB40FF5BABCE67F8B806D5969C":{n:"Boxing (Dactari) (4K)"}, "AFC194534C1B346609EF05EFF6D3CEF6":{n:"Boxing (Jone Yuan)"}, "FD6E507B5DF68BEEEDDEAF696B6828FA":{n:"Boxing (Unknown) (PAL)"}, "1CCA2197D95C5A41F2ADD49A13738055":{n:"Brain Games (1978) (Atari)"}, "CB9626517B440F099C0B6B27CA65142C":{n:"Brain Games (1978) (Atari) (4K)"}, "F280976D69D6E27A48506BD6BAD11DCD":{n:"Brain Games (1978) (Atari) (PAL)"}, "2162266B906C939B35C84FF9A0F50AD1":{n:"Brain Games (1978) (Atari) (PAL) (4K)"}, "4DBF47C7F5AC767A3B07843A530D29A5":{n:"Breaking News (2002) (Ric Pryor) (Hack)"}, "F34F08E5EB96E500E851A80BE3277A56":{n:"Breakout (1978) (Atari)",p:1}, "C738FC3F5AAE1E8F86F7249F6C82AC81":{n:"Breakout (1978) (Atari) (16K)",p:1}, "9A25B3CFE2BBB847B66A97282200CCA2":{n:"Breakout (1978) (Atari) (4K)",p:1}, "6C76FE09AA8B39EE52035E0DA6D0808B":{n:"Breakout (1978) (Atari) (PAL)",p:1}, "C5FE45F2734AFD47E27CA3B04A90213C":{n:"Breakout (1978) (Atari) (PAL) (4K)",p:1}, "4DF6124093CCB4F0B6C26A719F4B7706":{n:"Breakout (1978) (Atari) [a]",p:1}, "CFD6A8B23D12B0462BAF6A05EF347CD8":{n:"Bridge (1980) (Activision)"}, "413C925C5FDCEA62842A63A4C671A5F2":{n:"Bridge (1980) (Activision) [fixed]"}, "18A970BEA7AC4D29707C8D5CD559D03A":{n:"Bridge (208 in 1) (Unknown) (PAL)"}, "428B2D36F5D716765460701F7016AC91":{n:"Brooni (2001) (Andrew Wallace) (PD)"}, "A537879D8E82E1061D3AD800479D3B84":{n:"Brooni (2001) (Andrew Wallace) (PD) (PAL)"}, "1CF59FC7B11CDBCEFE931E41641772F6":{n:"Buck Rogers - Planet of Zoom (1983) (Sega)",c:1}, "CD88EF1736497288C4533BCCA339F881":{n:"Buck Rogers - Planet of Zoom (1983) (Sega) (PAL)",c:1}, "68597264C8E57ADA93BE3A5BE4565096":{n:"Bugs (1982) (Data Age)",p:1}, "E61210293B14C9C4ECC91705072C6A7E":{n:"Bugs (1983) (Gameworld) (PAL)",p:1}, "A3486C0B8110D9D4B1DB5D8A280723C6":{n:"Bugs Bunny (08-04-1983) (Atari) (Prototype)"}, "FA4404FABC094E3A31FCD7B559CDD029":{n:"Bugs Bunny (1983) (Atari) (Prototype)"}, "9E792A59F8795664CBAAFF1BA152D731":{n:"Bullet Demo (20-12-2002) (CT)"}, "76F53ABBBF39A0063F24036D6EE0968A":{n:"Bump 'n' Jump (1983) (M Network)"}, "9295570A141CDEC18074C55DC7229D08":{n:"Bump 'n' Jump (1989) (Telegames) (PAL)"}, "AA1C41F86EC44C0A44EB64C332CE08AF":{n:"Bumper Bash (1983) (Spectravideo)"}, "1BF503C724001B09BE79C515ECFCBD03":{n:"Bumper Bash (1983) (Spectravideo) (PAL)"}, "0443CFA9872CDB49069186413275FA21":{n:"BurgerTime (1983) (M Network)"}, "B42DF8D92E3118DC594CECD575F515D7":{n:"Burning Desire (1982) (Mystique) (PAL)",c:1}, "19D6956FF17A959C48FCD8F4706A848D":{n:"Burning Desire (1982) (PlayAround)",c:1}, "572D0A4633D6A9407D3BA83083536E0F":{n:"Busy Police (Funvision)"}, "8905D54F48B8024FC718ED643E9033F7":{n:"Cabbage Patch Kids (05-24-1984) (Coleco) (Prototype)"}, "E1486C7822C07117B4F94A32E5ED68C1":{n:"Cabbage Patch Kids (06-14-1984) (Coleco) (Prototype)"}, "80E5400470AC788143E6DB9BC8DD88CF":{n:"Cabbage Patch Kids (06-XX-1984) (Coleco) (Prototype)"}, "4605A00F5B44A9CBD5803A7A55DE150E":{n:"Cabbage Patch Kids (07-03-1984) (Coleco) (Prototype)"}, "7D726FA494F706784BAFEB1B50D87F23":{n:"Cabbage Patch Kids (07-27-1984) (Coleco) (Prototype)"}, "F4DABD5BCC603E8464A478208037D423":{n:"Cabbage Patch Kids (08-21-1984) (Coleco) (Prototype)"}, "1FA7A42C2C7D6B7A0C6A05D38C7508F4":{n:"Cabbage Patch Kids (09-04-1984) (Coleco) (Prototype)"}, "5D0E8A25CBD23E76F843C75A86B7E15B":{n:"Cabbage Patch Kids (09-07-1984) (Coleco) (Prototype)"}, "66FCF7643D554F5E15D4D06BAB59FE70":{n:"Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype)"}, "F6B5EBB65CBB2981AF4D546C470629D7":{n:"Cabbage Patch Kids (09-13-1984) (Coleco) (Prototype) [a]"}, "7F6533386644C7D6358F871666C86E79":{n:"Cakewalk (1983) (CommaVid)"}, "0060A89B4C956B9C703A59B181CB3018":{n:"Cakewalk (1983) (CommaVid) (PAL)"}, "0EEBFB60D437796D536039701EC43845":{n:"Cakewalk (Fabrizio Zavagli)"}, "9AB72D3FD2CC1A0C9ADB504502579037":{n:"California Games (1988) (Epyx)"}, "8068E07B484DFD661158B3771D6621CA":{n:"California Games (1988) (Epyx) (PAL)"}, "85478BB289DFA5C63726B9153992A920":{n:"Candi (Hack)"}, "0E0808227EF41F6825C06F25082C2E56":{n:"Candi (Hack) [a]"}, "FEEDCC20BC3CA34851CD5D9E38AA2CA6":{n:"Canyon Bomber (1979) (Atari)",p:1}, "3051B6071CB26377CD428AF155E1BFC4":{n:"Canyon Bomber (1979) (Atari) (4K)",p:1}, "457F4AD2CDA5F4803F122508BFBDE3F5":{n:"Canyon Bomber (208 in 1) (Unknown) (PAL)"}, "151C33A71B99E6BCFFB34B43C6F0EC23":{n:"Care Bears (1983) (Parker Bros) (Prototype)"}, "DE29E46DBEA003C3C09C892D668B9413":{n:"Carnival (1982) (CBS Electronics) (PAL)"}, "028024FB8E5E5F18EA586652F9799C96":{n:"Carnival (1982) (Coleco)"}, "8ED5A746C59571FEB255EAA7D6D0CF98":{n:"Carnival (208 in 1) (Unknown) (PAL) (Hack)"}, "5409D20C1AEA0B89C56993AEC5DC5740":{n:"Carnival Shooter (PD)"}, "B816296311019AB69A21CB9E9E235D12":{n:"Casino (1979) (Atari)",p:1}, "2BC26619E31710A9884C110D8430C1DA":{n:"Casino (1979) (Atari) (PAL)",p:1}, "681206A6BDE73E71C19743607E96C4BB":{n:"Casino (Unknown) (PAL)",p:1}, "76F66CE3B83D7A104A899B4B3354A2F2":{n:"Cat Trax (1983) (UA Limited) (Prototype)",c:1}, "D071D2EC86B9D52B585CC0382480B351":{n:"Cat Trax (1983) (UA Limited) (Prototype) [a]",c:1}, "B7903268E235310DC346A164AF4C7022":{n:"Cat Trax (Thomas Jentzsch) (PAL60)",c:1}, "A2DE0FC85548871279ED2A3C1325C13E":{n:"Cat and Mouse (George Veeder) (Hack)"}, "E2904748DA63DFEFC8816652B924B642":{n:"Catch Time (Jone Yuan)"}, "9E192601829F5F5C2D3B51F8AE25DBE5":{n:"Cathouse Blues (1982) (PlayAround)",c:1}, "8726C17EE7B559CB7BF2330D20972AD0":{n:"Cave Demo (21-04-2003) (CT)"}, "91C2098E88A6B13F977AF8C003E0BCA5":{n:"Centipede (1982) (Atari)"}, "17D000A2882F9FDAA8B4A391AD367F00":{n:"Centipede (1982) (Atari) (PAL)"}, "2F11BA54609777E2C6A5DA9B302C98E8":{n:"Centipede (1982) (Atari) (Prototype) (PAL)"}, "10958CD0A1A81D599005F1797AB0E51D":{n:"Centipede 2k (2000) (PD) (Hack)"}, "713FDE2AF865B6EC464DFD72E2EBB83E":{n:"Challenge (208 in 1) (Unknown) (PAL)",c:1}, "9905F9F4706223DADEE84F6867EDE8E3":{n:"Challenge (HES) (PAL)"}, "4311A4115FB7BC68477C96CF44CEBACF":{n:"Challenge (Unknown)"}, "73158EA51D77BF521E1369311D26C27B":{n:"Challenge (Zellers)"}, "5D799BFA9E1E7B6224877162ACCADA0D":{n:"Challenge of.... Nexar, The (1982) (Spectravision)"}, "1DA2DA7974D2CA73A823523F82F517B3":{n:"Challenge of.... Nexar, The (1982) (Spectravision) (PAL)"}, "45C4413DD703B9CFEA49A13709D560EB":{n:"Challenge of.... Nexar, The (Jone Yuan) (Hack)"}, "3D9C2FCCF8B11630762FF00811C19277":{n:"Challenge of.... Nexar, The (Unknown) (PAL)"}, "3E33AC10DCF2DFF014BC1DECF8A9AEA4":{n:"Chase the Chuckwagon (1983) (Spectravideo)",c:1}, "3F5A43602F960EDE330CD2F43A25139E":{n:"Checkers (1980) (Activision)"}, "7EDC8FCB319B3FB61CAC87614AFD4FFA":{n:"Checkers (1980) (Activision) (4K)"}, "191AC4EEC767358EE3EC3756C120423A":{n:"Checkers (208 in 1) (Unknown) (PAL)"}, "BCE93984B920E9B56CF24064F740FE78":{n:"Checkers (32 in 1) (1988) (Atari) (PAL)"}, "499B612F6544AE71D4915AA63E403E10":{n:"Checkers (32 in 1) (1988) (Atari) (PAL) (4K)"}, "3D7749FB9C2F91A276DFE494495234C5":{n:"Checkers (Jone Yuan)"}, "04E737C9D53CD84BFD5EE679954E4706":{n:"Checkers (Jone Yuan) (4K)"}, "E5ECD78EDD24326A968809DECBC7B916":{n:"Cheese (Dragonfire Beta) (05-21-1982) (Imagic) (Prototype)"}, "749FEC9918160921576F850B2375B516":{n:"China Syndrome (1982) (Spectravision)",c:1}, "E150F0D14F013A104B032305C0CE23EF":{n:"China Syndrome (1982) (Spectravision) (PAL)",c:1}, "36F9A953EBDD9A8BE97CCF27A2041903":{n:"Chinese Character Demo (PD)"}, "C1CB228470A87BEB5F36E90AC745DA26":{n:"Chopper Command (1982) (Activision)"}, "25D4BE3309B89583C6B39D9F93BF654F":{n:"Chopper Command (1982) (Activision) (16K)"}, "51F211C8FC879391FEE26EDFA7D3F11C":{n:"Chopper Command (1982) (Activision) (8K)"}, "114C599454D32F74C728A6E1F71012BA":{n:"Chopper Command (1982) (Activision) (PAL)"}, "85A4133F6DCF4180E36E70AD0FCA0921":{n:"Chopper Command (1983) (CCE)"}, "FFDC0EB3543404EB4C353FBDDDFA33B6":{n:"Chopper Command (1983) (CCE) [a]"}, "DA66D75E4B47FAB99733529743F86F4F":{n:"Chopper Command (1983) (Digitel)"}, "C2C7A11717E255593E54D0ACAF653EE5":{n:"Chopper Command (208 in 1) (Unknown) (PAL) (Hack)"}, "1CAD3B56CC0E6E858554E46D08952861":{n:"Chopper Command (Jone Yuan)"}, "F8811D45A9935CCA90C62F924712F8E6":{n:"Chopper Command (Jone Yuan) (Hack)"}, "B9F9C0FED0DB08C34346317F3957A945":{n:"Chopper Command (SuperVision) (PAL)"}, "ACB6787B938079F4E74313A905EC3CEB":{n:"Chronocolor Donkey Kong (PD)"}, "EE456542B93FA8D7E6A8C689B5A0413C":{n:"Chronocolor Donkey Kong Clean (PD)"}, "1D5EAC85E67B8CFF1377C8DBA1136929":{n:"Chronocolor Donkey Kong Sideways (PD)"}, "D605ED12F4EAAAEC3DCD5AA909A4BAD7":{n:"Chronocolor Frame Demo (10-01-2003) (AD)"}, "DB339AEA2B65B84C7CFE0EEAB11E110A":{n:"Chronocolor Frame Demo 2 (10-01-2003) (AD)"}, "A30ECE6DC4787E474FBC4090512838DC":{n:"Circus (Zellers)"}, "A7B96A8150600B3E800A4689C3EC60A2":{n:"Circus Atari (1980) (Atari)",p:1}, "A29DF35557F31DFEA2E2AE4609C6EBB7":{n:"Circus Atari (1980) (Atari) (Joystick)"}, "30E0AB8BE713208AE9A978B34E9E8E8C":{n:"Circus Atari (1980) (Atari) (PAL)",p:1}, "EFFFAFC17B7CB01B9CA35324AA767364":{n:"Circus Atari (Unknown)"}, "324CB4A749BCAC4F3DB9DA842B85D2F7":{n:"Climber 5 (01-05-2003) (Dennis Debro)"}, "9D4BC7C6FE9A7C8C4AA24A237C340ADB":{n:"Climber 5 (16-04-2003) (Dennis Debro)"}, "87B460DF21B7BBCFC57B1C082C6794B0":{n:"Climber 5 (20-03-2003) (Dennis Debro)"}, "D82C8A58098A6B46C5B81C16180354D1":{n:"Climber 5 (30-10-2002) (Dennis Debro) (Prototype)"}, "1E587CA91518A47753A28217CD4FD586":{n:"Coco Nuts (1982) (Telesys)"}, "5846B1D34C296BF7AFC2FA05BBC16E98":{n:"Codebreaker (1978) (Atari)"}, "83F50FA0FBAE545E4B88BB53B788C341":{n:"Codebreaker (1978) (Atari) (4K)"}, "A47E26096DE6F6487BF5DD2D1CCED294":{n:"Codebreaker (1978) (Atari) (PAL)"}, "71D005B60CF6E608D04EFB99A37362C3":{n:"Codebreaker (1978) (Atari) (PAL) (4K) [a]"}, "551A64A945D7D6ECE81E9C1047ACEDBC":{n:"Coffee Cup Soccer (Matthias Jaap) (Hack)"}, "76A9BF05A6DE8418A3EBC7FC254B71B4":{n:"Color Bar Generator (1984) (VideoSoft)"}, "E5A6E0BB7D56E2F08B237E15076E5699":{n:"Color Table Display Helper (PD)"}, "C221607529CABC93450EF25DBAC6E8D2":{n:"Color Test (26-09-2002) (Eckhard Stolberg)"}, "58C396323EA3E85671E34C98EB54E2A4":{n:"Color Tweaker (B. Watson)"}, "F6DAEBC0424FA0F8D9AAF26C86DF50F4":{n:"Color Tweaker (V1.0) (2001) (B. Watson)"}, "35AE903DFF7389755AD4A07F2FB7400C":{n:"Colored Wall Demo (PD)"}, "97A9BB5C3679D67F5C2CD17F30B85D95":{n:"Colors (1980) (Atari) (Prototype) (PAL)"}, "3F9431CC8C5E2F220B2AC14BBC8231F4":{n:"Colors Demo (PD)"}, "CC74DDB45D7BC4D04C2E6F1907416699":{n:"Colour Display Programme (1997) (Chris Cracknell)"}, "9989F974C3CF9C641DB6C8A70A2A2267":{n:"Colours Selector (Eckhard Stolberg)"}, "3C72DDAF41158FDD66E4F1CB90D4FD29":{n:"Comando Suicida (Dismac)"}, "4C8832ED387BBAFC055320C05205BC08":{n:"Combat (1977) (Atari)"}, "AC05C0E53A5E7009DDD75ED4B99949FC":{n:"Combat (1977) (Atari) (4K)"}, "BE35D8B37BBC03848A5F020662A99909":{n:"Combat (1977) (Atari) (4K) [a]"}, "E8AA36E3D49E9BFA654C25DCC19C74E6":{n:"Combat (1977) (Atari) (PAL)"}, "0EF64CDBECCCB7049752A3DE0B7ADE14":{n:"Combat (32 in 1) (1988) (Atari) (PAL)"}, "E2ECCBBE963F80F291CB1F18803BF557":{n:"Combat (32 in 1) (1988) (Atari) (PAL) (4K)"}, "E94632B0D863DD76459D689A9865BB33":{n:"Combat (Jone Yuan) (4K)"}, "331938989F0F33CA39C10AF4C09FF640":{n:"Combat - Tank AI (19-04-2003) (Zach Matley)"}, "176D3FBA7D687F2B23158098E103C34A":{n:"Combat AI (16-02-2003) (Zach Matley)"}, "5385CF2A04DE1D36AB55C73174B84DB0":{n:"Combat Rock (PD) (Hack)"}, "E63EFDFDA9A4003DCD77A854A781A06A":{n:"Combat Rock (PD) (Hack) [a]"}, "461029AB23800833E9645BE3E472D470":{n:"Combat TC (v0.1)"}, "B0C9CF89A6D4E612524F4FD48B5BB562":{n:"Combat Two (1982) (Atari) (Prototype)"}, "E25E173740F7ECC0E23025445C4591F3":{n:"Comitoid (Greg Zumwalt)"}, "99F7C6C26046BBE95F1C604B25DA8360":{n:"Comitoid beta 2 (SnailSoft)"}, "755FED16B48E81DE05130708A905D00D":{n:"Comitoid beta 3 (SnailSoft)"}, "E4E9125A8741977583776729359614E1":{n:"Comitoid beta 4 (SnailSoft)"}, "5D2CC33CA798783DEE435EB29DEBF6D6":{n:"Commando (1988) (Activision)"}, "DE1E9FB700BAF8D2E5AE242BFFE2DBDA":{n:"Commando (1988) (Activision) (PAL)"}, "61631C2F96221527E7DA9802B4704F93":{n:"Commando (1988) (Activision) [different logo]"}, "F457674CEF449CFD85F21DB2B4F631A7":{n:"Commando Raid (1982) (U.S. Games)"}, "5864CAB0BC21A60BE3853B6BCD50C59F":{n:"Commando Raid (208 in 1) (Unknown) (PAL)"}, "5F316973FFD107F7AB9117E93F50E4BD":{n:"Commando Raid (Unknown) (PAL)"}, "2C8835AED7F52A0DA9ADE5226EE5AA75":{n:"Communist Mutants from Space (1982) (Arcadia)"}, "E2C89F270F72CD256ED667507FA038A2":{n:"Communist Mutants from Space (1982) (Arcadia) (PAL)"}, "C4B73C35BC2F54B66CD786F55B668A82":{n:"Communist Mutants from Space (1982) (Arcadia) [a]"}, "D541B20EAE221A8EE321375E5971E766":{n:"Communist Mutants from Space (Preview) (1982) (Arcadia)"}, "7BA07D4EA18BF3B3245C374D8720AD30":{n:"Communist Mutants from Space (Preview) (1982) (Arcadia) (PAL)"}, "B98CC2C6F7A0F05176F74F0F62C45488":{n:"CompuMate (1983) (Spectravideo)",c:1}, "E7F005DDB6902C648DE098511F6AE2E5":{n:"CompuMate (1983) (Spectravideo) (PAL)",c:1}, "6A2C68F7A77736BA02C0F21A6BA0985B":{n:"Computer Chess (07-07-1978) (Atari) (Prototype)"}, "B49331B237C8F11D5F36FE2054A7B92B":{n:"Condor Attack (Unknown) (PAL)"}, "F965CC981CBB0822F955641F8D84E774":{n:"Confrontation (1983) (Answer) (Prototype)",c:1}, "00B7B4CBEC81570642283E7FC1EF17AF":{n:"Congo Bongo (1983) (Sega)"}, "335A7C5CFA6FEE0F35F5824D1FA09AED":{n:"Congo Bongo (1983) (Sega) (PAL)"}, "D078D25873C5B99F78FA267245A2AF02":{n:"Congo Bongo (1983) (Sega) [a]"}, "C2FBEF02B6EEA37D8DF3E91107F89950":{n:"Conquest Of Mars (NTSC)"}, "85BBEFB90E16BF386B304C1E9A1F6084":{n:"Conquest Of Mars (PAL60)"}, "A81B29177F258494B499FBAC69789CEF":{n:"Console Wars (Greg Thompson) (Hack)"}, "57C5B351D4DE021785CF8ED8191A195C":{n:"Cookie Monster Munch (1983) (Atari)"}, "A0297C4788F9E91D43E522F4C561B4AD":{n:"Cookie Monster Munch (1983) (Atari) (PAL)"}, "798B8921276EEC9E332DFCB47A2DBB17":{n:"Cookie Monster Munch (1983) (Atari) (PAL) [a]"}, "01E5C81258860DD82F77339D58BC5F5C":{n:"Corrida da Matematica (CCE)"}, "6A3B0C33CF74B1E213A629E3C142B73C":{n:"Cory The Interviewer (Cody Pittman) (Hack)"}, "EEB92F3F46DF841487D1504F2896D61A":{n:"Corys Adventure (Cody Pittman) (Hack)"}, "AB5BF1EF5E463AD1CBB11B6A33797228":{n:"Cosmic Ark (1982) (Imagic)"}, "C5124E7D7A8C768E5A18BDE8B54AEB1D":{n:"Cosmic Ark (1982) (Imagic) (PAL)"}, "0FD72A13B3B6103FC825A692C71963B4":{n:"Cosmic Ark (1982) (Imagic) (PAL) [selectable starfield]"}, "98EF1593624B409B9FB83A1C272A0AA7":{n:"Cosmic Ark (1983) (CCE)"}, "69DF0411D4D176E558017F961F5C5849":{n:"Cosmic Ark (1983) (CCE) [a]"}, "7D903411807704E725CF3FAFBEB97255":{n:"Cosmic Ark (Reaction) (1982) (Imagic) [selectable starfield]"}, "72D0ACB5DE0DB662DE0360A6FC59334D":{n:"Cosmic Ark (Unknown) (PAL)"}, "05D61B925D3D2474BAB83F0A79BB5DF1":{n:"Cosmic Ark Stars (1997) (Eckhard Stolberg)"}, "00CE76AD69CDC2FA36ADA01AE092D5A6":{n:"Cosmic Avenger (4 Game in One) (1983) (BitCorp) (PAL)"}, "133B56DE011D562CBAB665968BDE352B":{n:"Cosmic Commuter (1984) (Activision)"}, "BA657D940A11E807FF314BBA2C8B389B":{n:"Cosmic Commuter (1984) (Activision) (16K)"}, "59734E1CC41822373845A09C51E6BA21":{n:"Cosmic Commuter (1984) (Activision) (8K)"}, "5F1B7D5FA73AA071BA0A3C2819511505":{n:"Cosmic Commuter (CCE)"}, "8E879AA58DB41EDB67CBF318B77766C4":{n:"Cosmic Commuter (Thomas Jentzsch) (PAL60)"}, "F367E58667A30E7482175809E3CEC4D4":{n:"Cosmic Corridor (1983) (ZiMAG)"}, "3C853D864A1D5534ED0D4B325347F131":{n:"Cosmic Creeps (1982) (Telesys)",c:1}, "E2CA84A2BB63D1A210EBB659929747A9":{n:"Cosmic Creeps (1982) (Telesys) (PAL)",c:1}, "5835A78A88F97ACEA38C964980B7DBC6":{n:"Cosmic Creeps (Unknown) (PAL)",c:1}, "E5F17B3E62A21D0DF1CA9AEE1AA8C7C5":{n:"Cosmic Swarm (1982) (CommaVid)",c:1}, "9DEC0BE14D899E1AAC4337ACEF5AB94A":{n:"Cosmic Swarm (1982) (CommaVid) (4K)",c:1}, "2A2F46B3F4000495239CBDAD70F17C59":{n:"Cosmic Swarm (1982) (CommaVid) (PAL)",c:1}, "3E22C7EAF6459B67388602E4BEBBB3A8":{n:"Cosmic Swarm (1982) (CommaVid) (PAL) (4K)"}, "8AF58A9B90B25907DA0251EC0FACF3B8":{n:"Cosmic Swarm (Jone Yuan)"}, "1B0F3D7AF668EEEA38DDD6182D8F48FB":{n:"Cosmic Swarm (Jone Yuan) (4K)",c:1}, "36547BC6FAA5132B87504E18D088E1D7":{n:"Cosmic Swarm (Unknown) (PAL) (4K)",c:1}, "6C91AC51421CB9FC72C9833C4F440D65":{n:"Cosmic Town (1983) (ITT Family Games) (PAL)"}, "4981CEFE5493EA512284E7F9F27D1E54":{n:"Cosmic War (1983) (Home Vision) (PAL)"}, "BE561B286B6432CAC71BCCBAE68002F7":{n:"Counter Demo (PD)"}, "FE67087F9C22655CE519616FC6C6EF4D":{n:"Crack'ed (11-28-1988) (Atari) (Prototype)"}, "A184846D8904396830951217B47D13D9":{n:"Crackpots (1983) (Activision)"}, "88ED87C011F699DD27321DBE404DB6C8":{n:"Crackpots (1983) (Activision) (16K)"}, "5A17E30E6E911E74CCD7B716D02B16C6":{n:"Crackpots (1983) (Activision) (8K)"}, "3F3AD2765C874CA13C015CA6A44A40A1":{n:"Crackpots (1983) (CCE)"}, "3091AF0EF1A61E801F4867783C21D45C":{n:"Crackpots (1983) (CCE) [a]"}, "13448EB5BA575E8D7B8D5B280EA6788F":{n:"Crackpots (Digivision)"}, "606C2C1753051E03C1F1AC096C9D2832":{n:"Crackpots (Jone Yuan)"}, "F3C431930E035A457FE370ED4D230659":{n:"Crackpots (Unknown) (PAL)"}, "FB88C400D602FE759AE74EF1716EE84E":{n:"Crash Dive (1983) (20th Century Fox)"}, "0CEBB0BB45A856B23F56D21CE7D1BC34":{n:"Crash Dive (1983) (20th Century Fox) (PAL)"}, "9072C142728A3A3D994956D03BFACBA2":{n:"Crash Dive (Fabrizio Zavagli) (PAL60)"}, "55EF7B65066428367844342ED59F956C":{n:"Crazy Climber (1982) (Atari)"}, "4A7EEE19C2DFB6AEB4D9D0A01D37E127":{n:"Crazy Valet (Hozer Video Games)"}, "C17BDC7D14A36E10837D039F43EE5FA3":{n:"Cross Force (1982) (Spectravision)"}, "8F88309AFAD108936CA70F8B2B084718":{n:"Cross Force (1982) (Spectravision) (PAL)"}, "8372EEC01A08C60DBED063C5524CDFB1":{n:"Cross Force (Unknown) (PAL)"}, "8CD26DCF249456FE4AEB8DB42D49DF74":{n:"Crossbow (1987) (Atari)"}, "7E4783A59972AE2CD8384F231757EA0B":{n:"Crossbow (1987) (Atari) (PAL)"}, "384F5FBF57B5E92ED708935EBF8A8610":{n:"Crypts of Chaos (1982) (20th Century Fox)"}, "F12AFBFFA080DD3B2801DD14D4837CF6":{n:"Crystal Castles (01-04-1984) (Atari) (Prototype)",c:1}, "1C6EB740D3C485766CADE566ABAB8208":{n:"Crystal Castles (1984) (Atari)"}, "CA7ABC774A2FA95014688BC0849EEE47":{n:"Crystal Castles (1984) (Atari) (PAL)"}, "C68A6BAFB667BAD2F6D020F879BE1D11":{n:"Crystal Castles (1984) (Atari) (Prototype)"}, "A6127F470306EED359D85EB4A9CF3C96":{n:"Crystal Castles (1984) (Atari) [a]"}, "0ABF64CA504A116ADCA80F77F85E00FB":{n:"Cube Conquest (Billy Eno) (PD)"}, "58E313E2B5613B2439B5F12BB41E3EEF":{n:"Cube Conquest (Demo Interlace) (Billy Eno) (PD)",c:1}, "F1929BB9B5DB22D98DD992AA3FE72920":{n:"Cube Conquest (Improved Interlace) (Billy Eno) (PD)",c:1}, "36A701C60A9F9768D057BC2A83526A80":{n:"Cube Conquest (Interlaced) (Billy Eno) (PD)",c:1}, "292F2446A0325B7B423E88A2EBFEB5A0":{n:"Cube Conquest (Non Interlaced) (Billy Eno) (PD)",c:1}, "6FA0AC6943E33637D8E77DF14962FBFC":{n:"Cubicolor (1982) (Imagic) (Prototype)"}, "F74AD642552385C3DAA203A2A6FC2291":{n:"Cubis (1997) (Eckhard Stolberg)"}, "D2C957DD7746521B51BB09FDE25C5774":{n:"Cubis (6K) (1997) (Eckhard Stolberg)"}, "281FF9BD0470643853DE5CBD6D9E17F5":{n:"Cubis (EM) (1997) (Eckhard Stolberg)"}, "64CA518905311D2D9AEB56273F6CAA04":{n:"Cubo Magico (CCE)"}, "58513BAE774360B96866A07CA0E8FD8E":{n:"Custer's Revenge (1982) (Mystique)"}, "50200F697AEEF38A3CE31C4F49739551":{n:"Custer's Revenge (1982) (Mystique) (PAL60)"}, "D57EB282D7540051BC9B5427CF966F03":{n:"Custer's Viagra (Atari Troll) (Hack)"}, "93EB1795C8B1065B1B3D62BB9EC0CCDC":{n:"Custer's Viagra (JSK) (Hack)"}, "211F76DFF0B7DAD3F6FCAC9D938EE61A":{n:"Custer's Viagra (JSK) (Hack) [a]"}, "5355F80CACF0E63A49CBF4ADE4E27034":{n:"Cute Dead Things House (Christian Samuel) (Hack)"}, "60358EDF0C2CC76B1E549E031E50E130":{n:"Cyber Goth Galaxian (Manuel Polik) (Hack)"}, "52615AE358A68DE6E76467E95EB404C7":{n:"DJdsl-wopd (PD)",c:1}, "2B42DA79A682ED6E2D735FACBF70107E":{n:"DKjr Improved (Hack)"}, "B719ADA17771A8D206C7976553825139":{n:"DUP Space Invaders (Ron Corcoran) (Hack)"}, "929E8A84ED50601D9AF8C49B0425C7EA":{n:"Dancing Plate (1982) (BitCorp) (PAL)",c:1}, "ECE463ABDE92E8B89BCD867EC71751B8":{n:"Dancing Plate (1982) (Puzzy) (PAL)",c:1}, "F48735115EC302BA8BB2D2F3A442E814":{n:"Dancing Plate (Unknown) (PAL)",c:1}, "2D1CF85FBC732856BF76470CD4060F4A":{n:"Daredevil (V1) (Stunt_Cycle_Rules!) (PD)"}, "CD8FA2E9F6255EF3D3B9B5A4F24A54F7":{n:"Daredevil (V2) (Stunt_Cycle_Rules!) (PD)"}, "585F73010E205AE5B04EE5C1A67E632D":{n:"Daredevil (V3) (Stunt_Cycle_Rules!) (PD)"}, "A422194290C64EF9D444DA9D6A207807":{n:"Dark Cavern (1982) (M Network)"}, "106855474C69D08C8FFA308D47337269":{n:"Dark Chambers (1988) (Atari)",c:1}, "0D5AF65AD3F19558E6F8E29BF2A9D0F8":{n:"Dark Chambers (1988) (Atari) (PAL)",c:1}, "951E8CEC7A1A1D6C01FD649E7FF7743A":{n:"Dark Chambers (1988) (Atari) (Prototype) (PAL)"}, "DBA270850AE997969A18EE0001675821":{n:"Dark Mage (Greg Troutman) (PD) (4K)",c:1}, "6333EF5B5CBB77ACD47F558C8B7A95D3":{n:"Dark Mage (Greg Troutman) (PD) (8K)",c:1}, "6CD506509E8FD5627F55603780E862A8":{n:"Dark Mage (SuperCharger) (Greg Troutman) (PD)",c:1}, "2B71A59A53BE5883399917BF582B7772":{n:"Dark Mage (final beta) (Greg Troutman) (PD)",c:1}, "1345E972DBE08EA3E70850902E20E1A5":{n:"Dark Mage (rough beta) (Greg Troutman) (PD)",c:1}, "C1F209D80F0624DADA5866CE05DD3399":{n:"Deadly Discs (1989) (Telegames) (PAL)"}, "E4C00BEB17FDC5881757855F2838C816":{n:"Deadly Duck (1982) (20th Century Fox)"}, "80CD42881E670E4B74A9CCD10D0D7B2E":{n:"Deadly Duck (1982) (20th Century Fox) [a]"}, "4E15DDFD48BCA4F0BF999240C47B49F5":{n:"Death Trap (1983) (Avalon Hill)",c:1}, "AC7C2260378975614192CA2BC3D20E0B":{n:"Decathlon (1983) (Activision)"}, "883258DCD68CEFC6CD4D40B1185116DC":{n:"Decathlon (1983) (Activision) (PAL)"}, "525F2DFC8B21B0186CFF2568E0509BFC":{n:"Decathlon (1983) (Activision) [fixed]"}, "BF52327C2197D9D2C4544BE053CADED1":{n:"Decathlon (HES) (PAL) (16K)"}, "E1029676EDB3D35B76CA943DA7434DA8":{n:"Defender (10-30-1981) (Atari) (Prototype)"}, "0F643C34E40E3F1DAAFD9C524D3FFE64":{n:"Defender (1982) (Atari)"}, "E4BFF1D5DF70163C0428A1EAD309C22D":{n:"Defender (1982) (Atari) (PAL)"}, "808C3B1E60EE0E7C65205FA4BD772221":{n:"Defender (CCE)"}, "6596B3737AE4B976E4AADB68D836C5C7":{n:"Defender (Digivision)"}, "35B10A248A7E67493EC43AEB9743538C":{n:"Defender (Dor-x) (Hack)"}, "3C4223316C835CEAAD619651E25DF0F9":{n:"Defender (Genesis)"}, "047AC3B9FAEA64522B7A23C4465A7AA8":{n:"Defender (Unknown) (PAL)"}, "CE82A675C773FF21E0FFC0A4D1C90A71":{n:"Defender 2 (Genesis)"}, "6F3E3306DA2AA6E74A5E046FF43BF028":{n:"Defender Arcade (Genesis)"}, "3A771876E4B61D42E3A3892AD885D889":{n:"Defender II (1988) (Atari)"}, "5F786B67E05FB9985B77D4BEB35E06EE":{n:"Defender II (1988) (Atari) (PAL)"}, "278531CC31915747018D22145823D2C9":{n:"Defender MegaDrive (PAL) (Genesis)"}, "039CF18B459D33B8A8FCA31D06C4C244":{n:"Demo Image Series #0 (12-02-2003) (AD)"}, "A4AB331E8768EAFDC20CE8B0411FF77A":{n:"Demo Image Series #1 - Sam (19-02-2003) (AD)"}, "EA86176B27AB0DA8CCE8F0179884BFAA":{n:"Demo Image Series #10 - It's Art (28-02-2003) (AD)"}, "678C1D71A1616D9D022F03D8545B64BB":{n:"Demo Image Series #11 - Donald And Mario (28-02-2003) (AD)"}, "CB8399DC0D409FF1F531EF86B3B34953":{n:"Demo Image Series #12 - Luigi And Mario (01-03-2003) (AD)"}, "83F05ECECAE8BE59BA1E51135F4BDCBF":{n:"Demo Image Series #13 - Mario (4K Interleaved Chronocolour) (05-03-2003) (AD)"}, "3025BDC30B5AEC9FB40668787F67D24C":{n:"Demo Image Series #14 - Two Marios (4K Interleaved Chronocolour Vertical Movement) (05-03-2003) (AD)"}, "25710BDE8FA181B0C5CF0846B983BEC1":{n:"Demo Image Series #15 - Three Marios (NTSC) (06-03-2003) (AD)"}, "FB0C32EF7AF5B45486DB663510094BE8":{n:"Demo Image Series #15 - Three Marios (NTSC) (Non-Interleave) (06-03-2003) (AD)"}, "8D8B7D7B983F75DEBBDAAC651E814768":{n:"Demo Image Series #15 - Three Marios (PAL) (06-03-2003) (AD)"}, "14DBB3686DD31964332DC2EF0C55CAD0":{n:"Demo Image Series #15 - Three Marios (PAL) (Non-Interleave) (06-03-2003) (AD)"}, "EDE7E8BF865B0AFB4744F86D13624F9A":{n:"Demo Image Series #2 - Clown (19-02-2003) (AD)"}, "02066B17F29082412C6754C1A2D6302E":{n:"Demo Image Series #3 - Baboon (19-02-2003) (AD)"}, "C1B1049B88BCD98437D8872D1D62BA31":{n:"Demo Image Series #4 - Donald (19-02-2003) (AD)"}, "BB6A5A2F7B67BEE5D1F237F62F1E643F":{n:"Demo Image Series #5 - Animegirl (19-02-2003) (AD)"}, "A47878A760F5FA3AA99F95C3FDC70A0B":{n:"Demo Image Series #5 - Baboon (19-02-2003) (AD)"}, "373B8A081ACD98A895DB0CB02DF35673":{n:"Demo Image Series #5 - Boofly (19-02-2003) (AD)"}, "7CD379DA92C93679F3B6D2548617746A":{n:"Demo Image Series #5 - Clown (19-02-2003) (AD)"}, "CD38AD19F51B1048D8E5E99C86A2A655":{n:"Demo Image Series #5 - Flag (19-02-2003) (AD)"}, "A0D502DC8B90B1D7DAA5F6EFFB10D349":{n:"Demo Image Series #5 - Sam (19-02-2003) (AD)"}, "A310494AD5BA2B5B221A30D7180A0336":{n:"Demo Image Series #6 - Mario (19-02-2003) (AD)"}, "B451307B8B5E29F1C5F2CF064F6C7227":{n:"Demo Image Series #6 - Mario (Fixed) (26-02-2003) (AD)"}, "D1B4075925E8D3031A7616D2F02FDD1F":{n:"Demo Image Series #7 - Two Marios (27-02-2003) (AD)"}, "5C1B1AA78B7609D43C5144C3B3B60ADF":{n:"Demo Image Series #8 - Two Marios (Different Interlacing) (27-02-2003) (AD)"}, "C8C7DA12F087E8D16D3E6A21B371A5D3":{n:"Demo Image Series #9 - Genius (28-02-2003) (AD)"}, "D09935802D6760AE58253685FF649268":{n:"Demolition Herby (1983) (Telesys)",c:1}, "7DFD100BDA9ABB0F3744361BC7112681":{n:"Demolition Herby (1983) (Telesys) (PAL)",c:1}, "4A6BE79310F86F0BEBC7DFCBA4D74161":{n:"Demolition Herby (Unknown) (PAL)",c:1}, "F0E0ADDC07971561AB80D9ABE1B8D333":{n:"Demon Attack (1982) (Imagic)"}, "4901C05068512828367FDE3FB22199FE":{n:"Demon Attack (1982) (Imagic) (PAL)"}, "B12A7F63787A6BB08E683837A8ED3F18":{n:"Demon Attack (1982) (Imagic) [fixed]"}, "B24F6A5820A4B7763A3D547E3E07441D":{n:"Demon Attack (1983) (CCE)"}, "9718B85AC5A55CBC7348963C63FFA35A":{n:"Demon Attack (Robby)"}, "BAC28D06DFC03D3D2F4A7C13383E84EE":{n:"Demon Attack (Supergame)"}, "110AC8ECAF1B69F41BC94C59DFCB8B2D":{n:"Demon Attack (Unknown)"}, "442602713CB45B9321EE93C6EA28A5D0":{n:"Demon Attack (Unknown) (PAL)"}, "F91FB8DA3223B79F1C9A07B77EBFA0B2":{n:"Demons to Diamonds (1982) (Atari)",p:1}, "D62283AED0F4199ADB2333DE4C263E9C":{n:"Demons to Diamonds (1982) (Atari) (PAL)",p:1}, "BF84F528DE44225DD733C0E6A8E400A0":{n:"Demons to Diamonds (CCE)",p:1}, "698F569EAB5A9906EEC3BC7C6B3E0980":{n:"Demons! (2003) (SpkLeader) (Hack)"}, "2D16A8B59A225EA551667BE45F554652":{n:"Der Geheimkurier (1983) (Quelle) (PAL)"}, "A1CA372388B6465A693E4626CC98B865":{n:"Der Vielfrass (1983) (Quelle) (PAL)"}, "25A21C47AFE925A3CA0806876A2B4F3F":{n:"Der kleine Baer (1983) (Quelle) (PAL)"}, "A1F9159121142D42E63E6FB807D337AA":{n:"Der moderne Ritter (1983) (Quelle) (PAL)"}, "E9E6AD30549A6E2CD89FE93B7691D447":{n:"Desert Falcon (05-27-1987) (Atari) (Prototype) (PAL)"}, "FD4F5536FD80F35C64D365DF85873418":{n:"Desert Falcon (1987) (Atari)"}, "D4806775693FCAAA24CF00FC00EDCDF3":{n:"Desert Falcon (1987) (Atari) (PAL)"}, "626D67918F4B5E3F961E4B2AF2F41F1D":{n:"Diagnostic Test Cartridge 2.0 (1980) (Atari) (Prototype)"}, "38BD172DA8B2A3A176E517C213FCD5A6":{n:"Diagnostic Test Cartridge 2.6 (1982) (Atari)"}, "02AB2C47BC21E7FEAFA015F90D7DF776":{n:"Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype)"}, "09F89BBFA2AB00F1964D200E12D7CED0":{n:"Diagnostic Test Cartridge 2.6 (1982) (Atari) (Prototype) (4K)"}, "740F39E71104E90416C29A73560B9C6B":{n:"Diagnostic Test Cartridge 2.6P (1982) (Atari) (PAL) (4K)"}, "9222B25A0875022B412E8DA37E7F6887":{n:"Dice Puzzle (1983) (Panda)",c:1}, "E02156294393818FF872D4314FC2F38E":{n:"Dice Puzzle (1983) (Sancho) (PAL)",c:1}, "72876FD7C7435F41D571F1101FC456EA":{n:"Die Ente und der Wolf (1983) (Quelle) (PAL)"}, "31DF1C50C4351E144C9A378ADB8C10BA":{n:"Die Ratte und die Karotten (1983) (Quelle) (PAL)"}, "834A2273E97AEC3181EE127917B4B269":{n:"Die hungrigen Froesche (1983) (Quelle) (PAL)"}, "6DDA84FB8E442ECF34241AC0D1D91D69":{n:"Dig Dug (1983) (Atari)"}, "977294AE6526C31C7F9A166EE00964AD":{n:"Dig Dug (1983) (Atari) (PAL)"}, "21D2C435BCCCDE7792D82844B3CF60F4":{n:"Dig Dug (1983) (Atari) (PAL) [a]"}, "BAE1A23F9B6ACDADF465CFB330BA0ACB":{n:"Dig Dug (1983) (Atari) [a]"}, "EF66AF190840871409FE1702D2483554":{n:"DiscoTech (12-02-2003) (Andrew Davie)"}, "939CE554F5C0E74CC6E4E62810EC2111":{n:"Dishaster (1983) (ZiMAG)",c:1}, "740B47DF422372FBEF700B42CEA4E0BF":{n:"Dizzy Wiz (2001) (B. Watson)"}, "A5E9ED3033FB2836E80AA7A420376788":{n:"Dodge 'Em (1980) (Atari) (PAL)"}, "10F62443F1AE087DC588A77F9E8F43E9":{n:"Dodge 'Em (1980) (Atari) (PAL) [fixed]"}, "C3472FA98C3B452FA2FD37D1C219FB6F":{n:"Dodge 'Em (1980) (Atari) [a]"}, "83BDC819980DB99BF89A7F2ED6A2DE59":{n:"Dodge 'Em (1980) (Atari) [fixed]"}, "D28AFE0517A046265C418181FA9DD9A1":{n:"Dodge 'Em (Unknown) (PAL)"}, "BC526185AD324241782DC68BA5D0540B":{n:"Dodge Demo 1 (PD)"}, "5ACF9865A72C0CE944979F76FF9610F0":{n:"Dodge Demo 2 (PD)"}, "0C0392DB94A20E4D006D885ABBE60D8E":{n:"Dodge Demo 3 (PD)"}, "E2B682F6E6D76B35C180C7D847E93B4F":{n:"Dodge Demo 4 (PD)"}, "CA09FA7406B7D2AEA10D969B6FC90195":{n:"Dolphin (1983) (Activision)"}, "D09A7504EE8C8717AC3E24D263E7814D":{n:"Dolphin (1983) (Activision) (16K)"}, "E237EE91514D5ED535C95A14FC608C11":{n:"Dolphin (1983) (Activision) (8K)"}, "3889351C6C2100B9F3AEF817A7E17A7A":{n:"Dolphin (CCE)"}, "7FFC2D80FD49A124808315306D19868E":{n:"Domino (Ishido) (PD)"}, "937736D899337036DE818391A87271E0":{n:"Donald Duck's Speedboat (04-12-1983) (Atari) (Prototype)"}, "FA7CE62E7FD77E02B3E2198D70742F80":{n:"Donald Duck's Speedboat (04-18-1983) (Atari) (Prototype) (PAL)"}, "F473F99E47D4026A7A571184922EBF04":{n:"Donkey Claus (Philip R. Frey) (Hack)"}, "8B5B1E3A434EBBDC2C2A49DC68F46360":{n:"Donkey Kong (1982) (CBS Electronics) (PAL)"}, "3A526E6A1F9FE918AF0F2CE997DFEA73":{n:"Donkey Kong (1982) (CBS Electronics) (PAL) [a1]"}, "0894AA7BE77521F9DF562BE8D9555FE6":{n:"Donkey Kong (1982) (CBS Electronics) (PAL) [a2]"}, "B59417D083B0BE2D49A7D93769880A4B":{n:"Donkey Kong (1983) (Pet Boat) (PAL)"}, "36B20C427975760CB9CF4A47E41369E4":{n:"Donkey Kong (1987) (Atari)"}, "7511C34518A9A124EA773F5B0B5C9A48":{n:"Donkey Kong (208 in 1) (Unknown) (PAL)"}, "DE5AAB22E5ABA5EDCB29A3E7491FF319":{n:"Donkey Kong (Star Game)"}, "E7864CAAF9EC49ED67B1904CE8602690":{n:"Donkey Kong 2K3 Pic (PD)"}, "5B98E0536C3F60547DD708AE22ADB04B":{n:"Donkey Kong Gingerbread Man (Ben Hudman) (Prototype)"}, "5A6FEBB9554483D8C71C86A84A0AA74E":{n:"Donkey Kong Jr (1983) (CCE)"}, "2880C6B59BD54B153174676E465167C7":{n:"Donkey Kong Jr. (Tron)"}, "2091AF29B4E7B86914D79D9AAA4CBD20":{n:"Donkey Kong Junior (1983) (CBS Electronics) (PAL)"}, "C8FA5D69D9E555EB16068EF87B1C9C45":{n:"Donkey Kong Junior (1987) (Atari)"}, "278155FC9956E9B6EF2359EB238F7C7F":{n:"Donkey Kong Junior (Unknown) (Hack)"}, "200A9D2A7CB4441CE4F002DF6AA47E38":{n:"Doomzerk (PD) (Hack)"}, "7E2FE40A788E56765FE56A3576019968":{n:"Double Dragon (1989) (Activision)"}, "3624E5568368929FABB55D7F9DF1022E":{n:"Double Dragon (1989) (Activision) (PAL)"}, "47464694E9CCE07FDBFD096605BF39D4":{n:"Double Dragon (1989) (Activision) (PAL) [a]"}, "4999B45BE0AB5A85BAC1B7C0E551542B":{n:"Double Dragon (CCE) (PAL)"}, "740A7FA80F52CC7287BA37677AFB6B21":{n:"Double Dragon (PAL) (Genesis)"}, "368D88A6C071CABA60B4F778615AAE94":{n:"Double Dunk (1989) (Atari)"}, "CFC226D04D7490B69E155ABD7741E98C":{n:"Double Dunk (1989) (Atari) (PAL)"}, "3B966BF3C2CA34AC6CA1DE4CF6383582":{n:"Double-Height 6-Digit Score Display (2001) (AD)"}, "707ECD80030E85751EF311CED66220BC":{n:"Double-Height 6-Digit Score Display (Background Color Change) (2001) (AD)"}, "88DCE4037471424BB38AB6841AAA8CAB":{n:"Double-Height 6-Digit Score Display (Two Background Color Change) (2001) (AD)"}, "6A882FB1413912D2CE5CF5FA62CF3875":{n:"Dragon Defender (Ariola) (PAL)",c:1}, "24D9A55D8F0633E886A1B33EE1E0E797":{n:"Dragon Defender (Thomas Jentzsch)",c:1}, "41810DD94BD0DE1110BEDC5092BEF5B0":{n:"Dragon Treasure (Funvision)"}, "6FC394DBF21CF541A60E3B3631B817F1":{n:"Dragonfire (1982) (Imagic) (PAL)"}, "1267E3C6CA951FF1DF6F222C8F813D97":{n:"Dragonfire (Unknown) (PAL)"}, "78B84CFB1C57B0488D674D2374E656E6":{n:"Dragonstomper (1 of 3) (1982) (Arcadia)"}, "2D9E65959808A6098C16C82A59C9D9DC":{n:"Dragonstomper (1 of 3) (1982) (Arcadia) (PAL)"}, "90CCF4F30A5AD8C801090B388DDD5613":{n:"Dragonstomper (1982) (Arcadia)"}, "8B04E9D132B8E30D447ACAA6BD049C32":{n:"Dragonstomper (1982) (Arcadia) (PAL)"}, "5B7EA6AA6B35DC947C65CE665FDE624B":{n:"Dragonstomper (2 of 3) (1982) (Arcadia)"}, "66C4E0298D4120DF333BC2F3E163657E":{n:"Dragonstomper (2 of 3) (1982) (Arcadia) (PAL)"}, "DD8A2124D4EDA200DF715C698A6EA887":{n:"Dragonstomper (3 of 3) (1982) (Arcadia)"}, "AFF8CBA0F2D2EB239953DD7116894A08":{n:"Dragonstomper (3 of 3) (1982) (Arcadia) (PAL)"}, "A302B922A8DBEC47743F28B7F91D4CD8":{n:"Dragonstomper (Preview) (1982) (Arcadia)"}, "FBAC6476E7B2B20D246202AF81662C88":{n:"Dragonstomper (Preview) (1982) (Arcadia) (PAL)"}, "A867B76098786C4091DBA2FCEE5084C3":{n:"Dragrace (Hack)"}, "77057D9D14B99E465EA9E29783AF0AE3":{n:"Dragster (1980) (Activision)"}, "D763E3A9CDCDD56C715EC826106FAB6A":{n:"Dragster (1980) (Activision) (16K)"}, "63A6EDA1DA30446569AC76211D0F861C":{n:"Dragster (1980) (Activision) (4K)"}, "9D1556AE5890398BE7E3D57449774B40":{n:"Dragster (1980) (Activision) (8K)"}, "0C54811CF3B1F1573C9164D5F19ECA65":{n:"Dragster (1980) (Activision) (PAL)"}, "BB18189021D58362D9E4D317CD2E28B7":{n:"Dragster (1980) (Activision) (PAL) (4K)"}, "C216B91F5DB21A093DED6A5AAEC85709":{n:"Dragster (Jone Yuan)"}, "3BB9793C60C92911895CF44530846136":{n:"Dragster (Jone Yuan) (4K)"}, "B1339C56A9EA63122232FE4328373AC5":{n:"Dream Flight (1983) (Goliath) (PAL)"}, "2BC6C53B19E0097A242F22375A6A60FF":{n:"Droid Demo 2 (David Conrad Schweinsberg) (PD)"}, "37F42AB50018497114F6B0F4F01AA9A1":{n:"Droid Demo 2-M (David Conrad Schweinsberg) (PD)"}, "BFF8F8F53A8AEB1EE804004CCBB08313":{n:"Droid Demo 22 (David Conrad Schweinsberg) (PD)"}, "C1B7AEABC3EC41556D924C8372A9BA5B":{n:"Dukes of Hazard (1980) (Atari) (Prototype)"}, "34CA2FCBC8BA4A0B544ACD94991CFB50":{n:"Dukes of Hazzard (1980) (Atari) (Prototype) (4K)"}, "51DE328E79D919D7234CF19C1CD77FBC":{n:"Dukes of Hazzard (1983) (Atari)"}, "2BA02F509A4991AA176BA8D9E540DF3D":{n:"Dukes of Hazzard (1983) (Atari) [a]"}, "3897744DD3C756EA4B1542E5E181E02A":{n:"Dumbo's Flying Circus (05-05-1983) (Atari) (Prototype)"}, "1F773A94D919B2A3C647172BBB97F6B4":{n:"Dumbo's Flying Circus (07-11-1983) (Atari) (Prototype) (PAL)"}, "31FCBCE1CFA6EC9F5B6DE318E1F57647":{n:"Dumbo's Flying Circus (1983) (Atari) (Prototype) (PAL)"}, "469473FF6FED8CC8D65F3C334F963AAB":{n:"Dune (07-10-1984) (Atari) (Prototype)",c:1}, "AFB3BC45C6A82739CC82582127CD96E6":{n:"Dungeon (11-22-1985) (Atari) (Prototype)"}, "615A3BF251A38EB6638CDC7FFBDE5480":{n:"E.T. - The Extra-Terrestrial (1982) (Atari)"}, "8FEBDD9142960D084AB6EEB1D3E88969":{n:"E.T. - The Extra-Terrestrial (1982) (Atari) (PAL)"}, "A511F7EE13E4B35512F9217A677B4028":{n:"E.T. - The Extra-Terrestrial (1982) (Atari) (PAL) [a]"}, "C82EC00335CBB4B74494AECF31608FA1":{n:"E.T. - The Extra-Terrestrial (CCE)"}, "F71694BD8E89D5A28DAA73BF856635DF":{n:"E.T. Book Cart (NTSC)",c:1}, "91191666186117F5BF78B40623D79039":{n:"E.T. Book Cart (PAL)",c:1}, "84DF0704E6C777E1F9A16EC92AD80DF0":{n:"E.T. Book Cart (PAL60)",c:1}, "EFA1098C7D091B940C2543ABE372F036":{n:"E.T. The Extra-Terrestrial (Scott Stilphen) (Hack)"}, "13ABC32F803165C458BB086FA57195FB":{n:"E.T. The Extra-Testical (Christian Samuel) (Hack)"}, "6982854657A2CC87D712F718E402BF85":{n:"Earth Attack (Zellers)"}, "033E21521E0BF4E54E8816873943406D":{n:"Earth Dies Screaming, The (1983) (20th Century Fox)"}, "2C0DC885D5EDE94AA664BF3081ADD34E":{n:"Earth Dies Screaming, The (Unknown) (PAL)"}, "2BF34B6AD7D2317A2D0808B3FB93571B":{n:"Easy Playfield Graphics (1997) (Chris Cracknell)"}, "9CBB07F1993A027BC2F87D5205457EC9":{n:"Eckhard Stolberg's Scrolling Text Demo 1 (PD)"}, "F8BFD99163D2C4EC688357786E6FBA28":{n:"Eckhard Stolberg's Scrolling Text Demo 2 (PD)"}, "32E65D1E4DFCBCD9B57FEE72CAFE074C":{n:"Eckhard Stolberg's Scrolling Text Demo 3 (PD)"}, "3B5751A8D20F7DE41EB069F76FECD5D7":{n:"Eckhard Stolberg's Scrolling Text Demo 4 (PD)"}, "3E6DAB92009D6034618CB6B7844C5216":{n:"Ed Invaders (Hack)"}, "07973BE3ECFD55235BF59AA56BDEF28C":{n:"Eddy Langfinger, der Museumsdieb (1983) (Quelle) (PAL)",c:1}, "C6D48C6AE6461E0E82753540A985AC9E":{n:"Edtris (1994) (Ed Federmeyer)"}, "683DC64EF7316C13BA04EE4398E2B93A":{n:"Edtris (1995) (Ed Federmeyer)"}, "A00EE0AED5C8979ADD4C170F5322C706":{n:"Egghead (Barry Laws Jr.) (Hack)"}, "42B2C3B4545F1499A083CFBC4A3B7640":{n:"Eggomania (1982) (U.S. Games)",p:1}, "2B1589C7E1F394AE6A1C046944F06688":{n:"Eggomania (1983) (Carrere Video) (PAL)",p:1}, "A3F2A0FCF74BBC5FA763B0EE979B05B1":{n:"Eishockey-Fieber (1983) (Quelle) (PAL)"}, "71F8BACFBDCA019113F3F0801849057E":{n:"Elevator Action (1983) (Atari) (Prototype)"}, "B6812EAF87127F043E78F91F2028F9F4":{n:"Eli's Ladder (1982) (Simage)"}, "7EAFC9827E8D5B1336905939E097AAE7":{n:"Elk Attack (1987) (Atari) (Prototype)"}, "DBC8829EF6F12DB8F463E30F60AF209F":{n:"Encounter at L-5 (1982) (Data Age)",p:1}, "5188FEE071D3C5EF0D66FB45C123E4A5":{n:"Encounter at L-5 (1983) (Gameworld) (PAL)",p:1}, "94B92A882F6DBAA6993A46E2DCC58402":{n:"Enduro (1983) (Activision)",l:"ENDURO"}, "CFE62ED7125FF9FAE99B4C8A367C0399":{n:"Enduro (1983) (Activision) (16K)",l:"ENDURO"}, "265C74A956500BD31EFD24ADC6D5CCF6":{n:"Enduro (1983) (Activision) (8K)",l:"ENDURO"}, "6A82B8ECC663F371B19076D99F46C598":{n:"Enduro (1983) (Activision) (PAL)",l:"ENDURO"}, "DE62F8A30298E2325249FE112ECB5C10":{n:"Enduro (1983) (CCE)",l:"ENDURO"}, "360C0DCB11506E73BD0B77207C81BC62":{n:"Enduro (1983) (Digitel)",l:"ENDURO"}, "E1EFE2EF7664BB6758B1A22FF8EA16A1":{n:"Enduro (1983) (Dynacom)",l:"ENDURO"}, "07F84DB31E97EF8D08DC9FA8A5250755":{n:"Enduro (1984) (Supergame)",l:"ENDURO"}, "5DF559A36347D8572F9A6E8075A31322":{n:"Enduro (Digivision)",l:"ENDURO"}, "D2F713C78A9EBBA9DA6D10AEEFC6F20F":{n:"Enduro (Digivision) [a]",l:"ENDURO"}, "A8E49D7E24CE293629CA29614862821B":{n:"Enduro (Genesis)"}, "2BB0A1F1DEE5226DE648EB5F1C97F067":{n:"Enduro (Robby)",l:"ENDURO"}, "E9E646F730B8400CD5DA08C849EF3E3B":{n:"Enduro (Tron)",l:"ENDURO"}, "4279485E922B34F127A88904B31CE9FA":{n:"Enduro (Unknown)",l:"ENDURO"}, "61719A8BDAFBD8DAB3CA9CE7B171B9E2":{n:"Enduro (Unknown) (PAL)",l:"ENDURO"}, "9F5096A6F1A5049DF87798EB59707583":{n:"Entity, The (1983) (20th Century Fox) (Prototype)"}, "6B683BE69F92958ABE0E2A9945157AD5":{n:"Entombed (1982) (U.S. Games)",c:1}, "D7F5BF138CFC7FEAB7B8EF1534C8B477":{n:"Eric Bergstrom's KC-135 (Radar Map) (Aaron Bergstrom)"}, "8538C5E3EE83267774480649F83FA8D6":{n:"Escape Demo (PD)"}, "D1A1841B7F2007A24439AC248374630A":{n:"Escape from the Mindmaster (1 of 4) (1982) (Arcadia)"}, "3576037C9281656655FA114A835BE553":{n:"Escape from the Mindmaster (1 of 4) (1982) (Arcadia) (PAL)"}, "81F4F0285F651399A12FF2E2F35BAB77":{n:"Escape from the Mindmaster (1982) (Arcadia)"}, "C9E721EB29C940C2E743485B044C0A3F":{n:"Escape from the Mindmaster (1982) (Arcadia) (PAL)"}, "64198BB6470C78AC24FCF13FE76AB28C":{n:"Escape from the Mindmaster (1982) (Arcadia) [a]"}, "FDF0DE38517E0CF7F0885F98CCC95836":{n:"Escape from the Mindmaster (2 of 4) (1982) (Arcadia)"}, "A075AD332942740C386F4C3814925ECE":{n:"Escape from the Mindmaster (2 of 4) (1982) (Arcadia) (PAL)"}, "7A63D7EA3F2851BCF04F0BB4BA1A3929":{n:"Escape from the Mindmaster (3 of 4) (1982) (Arcadia)"}, "CC1939E4769D0C157ACE326EFCFDCF80":{n:"Escape from the Mindmaster (3 of 4) (1982) (Arcadia) (PAL)"}, "F0536303F49006806BAC3AEC15738336":{n:"Escape from the Mindmaster (4 of 4) (1982) (Arcadia)"}, "1EE2CFC7D0333B96BD11F7F3EC8CE8BC":{n:"Escape from the Mindmaster (4 of 4) (1982) (Arcadia) (PAL)"}, "F1127ADE54037236E75A133B1DFC389D":{n:"Escape from the Mindmaster (Preview) (1982) (Arcadia)"}, "271BFD5DC2673D382019F1FB6CAB9332":{n:"Escape from the Mindmaster (Preview) (1982) (Arcadia) (PAL)"}, "F344AC1279152157D63E64AA39479599":{n:"Espial (1984) (Tigervision)"}, "F7A138EED69665B5CD1BFA796A550B01":{n:"Espial (1984) (Tigervision) (PAL)"}, "66362890EB78D6EA65301592CCE65F5B":{n:"Euchre (13-07-2001) (Eric Eid) (PD)"}, "72097E9DC366900BA2DA73A47E3E80F5":{n:"Euchre (15-06-2001) (Eric Eid) (PD)"}, "524693B337F7ECC9E8B9126E04A232AF":{n:"Euchre (19-08-2001) (Eric Eid) (PD)"}, "8EE3F64DC0F349ADC893FE93DF5245D8":{n:"Euchre (20-07-2001) (Eric Eid) (PD)"}, "EB71743C6C7CCCE5B108FAD70A326AD9":{n:"Euchre (25-11-2001) (Erik Eid) (PD)"}, "65562F686B267B21B81C4DDDC129D724":{n:"Euchre (28-07-2001) (Eric Eid) (PD)"}, "29949F893EF6CB9E8ECB368B9E99EEE4":{n:"Euchre (Alpha) (NTSC) (31-08-2002) (Erik Eid)"}, "407A0C6CC0FF777F67B669440D68A242":{n:"Euchre (Alpha) (PAL) (31-08-2002) (Erik Eid)"}, "FFB1CD548563158CE33F9D10268187E7":{n:"Euchre (Beta) (NTSC) (12-09-2002) (Erik Eid)"}, "877A5397F3F205BF6750398C98F33DE1":{n:"Euchre (Beta) (PAL) (12-09-2002) (Erik Eid)"}, "873FB75A7788BA0F4AE715229A05545E":{n:"Euchre (Improved Colors) (PAL) (26-09-2002) (Erik Eid)"}, "15BF2EF7583BFCBBBA630847A1DC5539":{n:"Euchre (Jul 15) (2002) (Eric Eid) (PD)"}, "80E52315919BD8A8B82A407CCD9BB13F":{n:"Euchre (Jul 28) (2002) (Eric Eid) (PD)"}, "40AA851E8D0F1C555176A5E209A5FABB":{n:"Euchre (More for less) (NTSC) (22-08-2002) (Erik Eid)"}, "C9D02D3CFEEF8B48FB71CB4520A4AA84":{n:"Euchre (More for less) (PAL) (22-08-2002) (Erik Eid)"}, "B1B20536AEF4EED9C79DC5804F077862":{n:"Euchre (NTSC) (09-11-2001) (Erik Eid)"}, "D4AA89E96D2902692F5C45F36903D336":{n:"Euchre (NTSC) (Erik Eid) (PD)"}, "E5D5085123A98C1E61818CAA2971E999":{n:"Euchre (PAL) (Erik Eid) (PD)"}, "6205855CC848D1F6C4551391B9BFA279":{n:"Euchre (Release Candidate 2) (NTSC) (01-10-2002) (Erik Eid)"}, "199985CAE1C0123AB1AEF921DAACE8BE":{n:"Euchre (Release Candidate 2) (PAL) (01-10-2002) (Erik Eid)"}, "4690FDB70C86604BB35DA26696818667":{n:"Euchre (Release Candidate) (NTSC) (28-09-2002) (Erik Eid)"}, "BFFE34516AAA3CBF5D307EAB382A7E95":{n:"Euchre (Release Candidate) (PAL) (28-09-2002) (Erik Eid)"}, "77CD9A9DD810CE8042BDB9D40E256DFE":{n:"Evil Dead (2003) (Kyle Pittman) (Hack)"}, "B5657D4C1C732FBB6AF150668464247F":{n:"Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype)"}, "1B4B06C2A14ED3EE73B7D0FD61B6AAF5":{n:"Excalibur (Dragonstomper Beta) (1982) (Arcadia) (Prototype) [a]"}, "3AD58B53A1E972396890BD86C735E78D":{n:"Excalibur Version 36 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)"}, "2EAF8FA9E9FDF1FCFC896926A4BDBF85":{n:"Excalibur Version 39 (Dragonstomper Beta) (1982) (Arcadia) (Prototype)"}, "6362396C8344EEC3E86731A700B13ABF":{n:"Exocet (1983) (Panda)"}, "295F3679BDF91CA5E37DA3F787B29997":{n:"Exorcise (Hack)"}, "EBD2488DCACE40474C1A78FA53EBFADF":{n:"Extra Terrestrials (1983) (SSG)"}, "7926083AD423ED685DE3B3A04A914315":{n:"Face Invaders 2 (Barry Laws Jr.) (Hack)"}, "0AF51CEB4AECC7A8FC89781AC44A1973":{n:"Face Invaders Deluxe (Barry Laws Jr.) (Hack)"}, "B80D50ECEE73919A507498D0A4D922AE":{n:"Fantastic Voyage (1982) (20th Century Fox)"}, "0F24CA5668B4AB5DFAF217933C505926":{n:"Fantastic Voyage (208 in 1) (Unknown) (PAL)"}, "F7E07080ED8396B68F2E5788A5C245E2":{n:"Farmyard Fun (Ariola)"}, "9DE0D45731F90A0A922AB09228510393":{n:"Fast Eddie (1982) (20th Century Fox)"}, "A97733B0852EE3096300102CB0689175":{n:"Fast Eddie (1983) (CCE)"}, "665B8F8EAD0EEF220ED53886FBD61EC9":{n:"Fast Food (1982) (Telesys)"}, "48411C9EF7E2CEF1D6B2BEE0E6055C27":{n:"Fast Food (1982) (Telesys) (PAL)"}, "313243FC41E49EF6BD3AA9EBC0D372DD":{n:"Fast Food (Unknown) (PAL)"}, "6B7E1C11448C4D3F28160D2DE884EBC8":{n:"Fast Food (Zirok)"}, "63E783994DF824CAF289B69A084CBF3E":{n:"Fat Albert (David Marli) (Hack)"}, "8A159EE58B2F0A54805162984B0F07E5":{n:"Fatal Run (1989) (Atari) (PAL) [a]"}, "85470DCB7989E5E856F36B962D815537":{n:"Fatal Run (1989) (Atari) (Prototype)"}, "EF263D40A23483AB339CAC44D9515A56":{n:"Fatal Run (TJ)"}, "074EC425EC20579E64A7DED592155D48":{n:"Fatal Run (Ultimate Driving) (1989) (Atari) (PAL)"}, "0B55399CF640A2A00BA72DD155A0C140":{n:"Fathom (1983) (Imagic)",c:1}, "47CD61F83457A0890DE381E478F5CF5F":{n:"Fathom (1983) (Imagic) (PAL)",c:1}, "962FFD3EAF865230A7A312B80E6C5CFD":{n:"Fathom (1983) (Imagic) (PAL) [a]",c:1}, "540075F657D4B244A1F74DA1B9E4BF92":{n:"Festival (4 Game in One Dark Green) (1983) (BitCorp) (PAL)"}, "8E737A88A566CC94BD50174C2D019593":{n:"Feuerwehr im Einsatz (1983) (Quelle) (PAL)"}, "2AC3A08CFBF1942BA169C3E9E6C47E09":{n:"Fighter Pilot (1988) (Activision) (PAL)"}, "211FBBDBBCA1102DC5B43DC8157C09B3":{n:"Final Approach (1982) (Apollo)"}, "51E390424F20E468D2B480030CE95D7B":{n:"Fire Bird (Video Game Program) (PAL)"}, "01E60A109A6A67C70D3C0528381D0187":{n:"Fire Birds (1983) (ITT Family Games) (PAL)"}, "D09F1830FB316515B90694C45728D702":{n:"Fire Fighter (1982) (Imagic)"}, "90D77E966793754AB4312C47B42900B1":{n:"Fire Fighter (1982) (Imagic) (PAL)"}, "20DCA534B997BF607D658E77FBB3C0EE":{n:"Fire Fly (1983) (Mythicon)"}, "386FF28AC5E254BA1B1BAC6916BCC93A":{n:"Fireball (1982) (Arcadia)",p:1}, "CDB81BF33D830EE4EE0606EE99E84DBA":{n:"Fireball (1982) (Arcadia) (PAL)",p:1}, "5438E84B90E50A5362F01CC843B358D4":{n:"Fireball (1982) (Arcadia) (Prototype)",p:1}, "683BB0D0F0C5DF58557FBA9DFFC32C40":{n:"Fireball (1982) (Arcadia) [a]",p:1}, "66BC1BEF269EA59033928BAC2D1D81E6":{n:"Fireball (Preview) (1982) (Arcadia)",p:1}, "A3D7C299FBCD7B637898EE0FDCFC47FC":{n:"Fireball (Preview) (1982) (Arcadia) (PAL)",p:1}, "6C85098518D3F94F7622C42FD1D819AC":{n:"Firebug (Suntek) (PAL)"}, "D2901C34BB6496BB96C7BC78A9E6142A":{n:"Fish Revenge (2003) (Greg Zumwalt) (Hack)"}, "3FE43915E5655CF69485364E9F464097":{n:"Fisher Price (1983) (CCE)"}, "2517827950FEE41A3B9DE60275C8AA6A":{n:"Fishing (32 in 1) (1988) (Atari) (PAL)"}, "F9967369943209B4788D4E92CEFC0795":{n:"Fishing (32 in 1) (1988) (Atari) (PAL) (4K)"}, "B8865F05676E64F3BEC72B9DEFDACFA7":{n:"Fishing Derby (1980) (Activision)"}, "3C82E808FE0E6A006DC0C4E714D36209":{n:"Fishing Derby (1980) (Activision) (16K)"}, "85227160F37AAA29F5E3A6C7A3219F54":{n:"Fishing Derby (1980) (Activision) (4K)"}, "5131AB3797FE8C127E3E135B18B4D2C8":{n:"Fishing Derby (1980) (Activision) (8K)"}, "571C6D9BC71CB97617422851F787F8FE":{n:"Fishing Derby (1980) (Activision) (PAL)"}, "ECFA04523DDE82FE42CDC7315A8F61B6":{n:"Fishing Derby (1980) (Activision) (PAL) (4K)"}, "7628D3CADEEE0FD2E41E68B3B8FBE229":{n:"Fishing Derby (32 in 1) (1988) (Atari) (PAL)"}, "D782543818B6320E4F60D77DA2B596DE":{n:"Fishing Derby (32 in 1) (1988) (Atari) (PAL) (4K)"}, "DEA0ADE296F7093E71185E802B500DB8":{n:"Fishing Derby (CCE)"}, "804ED85EADF1CE3E93721547CBEA7592":{n:"Fishing Derby (CCE) (4K)"}, "0651216C4A4A9C9AC5ADA3013A317C72":{n:"Fishing Derby (Jone Yuan) (4K) (Hack)"}, "74023E0F2E739FC5A9BA7CAAEEEE8B6B":{n:"Fishing Derby (Jone Yuan) (Hack)"}, "1D2A28EB8C95DA0D6D6B18294211839F":{n:"Fishing Derby (Unknown) (PAL) (4K)"}, "6B72B691EA86F61438ED0D84C4D711DE":{n:"Fishing Derby (Unknown) (PAL) (4K) (Hack)"}, "458883F1D952CD772CF0057ABCA57497":{n:"Fishing Derby (Unknown) (PAL) (Hack)"}, "30512E0E83903FC05541D2F6A6A62654":{n:"Flag Capture (1978) (Atari)"}, "4B143D7DCF6C96796C37090CBA045F4F":{n:"Flag Capture (1978) (Atari) (4K)"}, "DA7A17DCDAA62D6971393C0A6FAF202A":{n:"Flag Capture (208 in 1) (Unknown) (PAL)"}, "F5445B52999E229E3789C39E7EE99947":{n:"Flag Capture (32 in 1) (1988) (Atari) (PAL)"}, "B897F9E3F939B9F21566D56DB812A84E":{n:"Flag Capture (32 in 1) (1988) (Atari) (PAL) (4K)"}, "19162393786098D50587827588198A86":{n:"Flag Capture (Jone Yuan) (4K)"}, "4AE8C76CD6F24A2E181AE874D4D2AA3D":{n:"Flash Gordon (Unknown) (PAL)"}, "7A2AF383014F5D810AD26D322823549D":{n:"FlickerSort Demo (20-04-2002) (MP)"}, "02811151906E477D47C135DB5B1699C6":{n:"FlickerSort Demo (Updated) (20-04-2002) (MP)"}, "5A2F2DCD775207536D9299E768BCD2DF":{n:"Flippern (Double-Game Package) (1983) (Quelle) (PAL)"}, "E549F1178E038FA88DC6D657DC441146":{n:"Football (1979) (Atari)"}, "D86DEB100C6ABED1588AA84B2F7B3A98":{n:"Football (1979) (Atari) (4K)"}, "5F9B62350B31BE8BD270D9A241CBD50E":{n:"Football (1989) (Telegames) (PAL)"}, "CFE2185F84CE8501933BEB5C5E1FD053":{n:"Football (208 in 1) (Unknown) (PAL)"}, "E6D5948F451A24994DFAACA51DFDB4E1":{n:"Football (Jone Yuan) (4K)"}, "213E5E82ECB42AF237CFED8612C128AC":{n:"Forest (1983) (Sancho) (PAL)",c:1}, "7AB210F448DE518FA61A5924120BA872":{n:"Fortress (20-04-2003) (CT)"}, "2008C76DEBA5953201EF75A09B2FF7DC":{n:"Fortress (21-04-2003) (CT)"}, "19D9B5F8428947EAE6F8E97C7F33BF44":{n:"Fortress (Dual Version) (20-04-2003) (CT)"}, "6D74EBABA914A5CFC868DE9DD1A5C434":{n:"Fortress (Smooth Version) (20-04-2003) (CT)"}, "76EE917D817EF9A654BC4783E0273AC4":{n:"Fox & Goat (Double-Game Package) (1983) (Quelle) (PAL)"}, "0856F202B18CD46E44FD1DC3B42E9BFB":{n:"Frame Counter 1 (2001) (Jake Patterson) (PD)"}, "DB1753CC702C18D3917EC7F3B0E8659F":{n:"Frame Counter 2 (2001) (Jake Patterson) (PD)"}, "8290DAEA8391F96D7C8E1482E184D19C":{n:"Frame Timed Sound Effects (Eckhard Stolberg)"}, "442B7863683E5F084716FDA050474FEB":{n:"Frame Timed Sound Effects-EM (Eckhard Stolberg)"}, "15DD21C2608E0D7D9F54C0D3F08CCA1F":{n:"Frankenstein's Monster (1983) (Data Age)"}, "7D0B49EA4FE3A5F1E119A6D14843DB17":{n:"Frankenstein's Monster (1983) (Gameworld) (PAL)"}, "8E0AB801B1705A740B476B7F588C6D16":{n:"Freeway (1981) (Activision)"}, "69974DD5D6420B90898CDE50AEC5EF39":{n:"Freeway (1981) (Activision) (16K)"}, "851CC1F3C64EAEDD10361EA26345ACEA":{n:"Freeway (1981) (Activision) (4K)"}, "0F95264089C99FC2A839A19872552004":{n:"Freeway (1981) (Activision) (8K)"}, "2EC6B045CFD7BC52D9CDFD1B1447D1E5":{n:"Freeway (1981) (Activision) (PAL)"}, "E4AFE157C09962CF39CDB25845D83D47":{n:"Freeway (1981) (Activision) (PAL) (4K)"}, "EDDEF10FDC0029301064115AE0CD41D4":{n:"Freeway (CCE)"}, "28148A52B1955CE12C7A74D3A3E620A4":{n:"Freeway (CCE) (4K)"}, "7D5C3B7B908752B98E30690E2A3322C2":{n:"Freeway (Dactari - Milmar)"}, "B822FBA8B7C8A97EA4E92AEB2C455EF9":{n:"Freeway (Dactari) (4K)"}, "7B7B4AC05232490C28F9B680C72998F9":{n:"Freeway (Zellers)"}, "914A8FEAF6D0A1BBED9EB61D33817679":{n:"Freeway Chicken (32 in 1) (1988) (Atari) (PAL)"}, "B7B1D3CE07E75976C43A2DCA3866237E":{n:"Freeway Chicken (32 in 1) (1988) (Atari) (PAL) (4K)"}, "481D20EC22E7A63E818D5EF9679D548B":{n:"Freeway Rabbit (32 in 1) (1988) (Atari) (PAL)"}, "060C865C782DEBB047E6FD101C8923FC":{n:"Freeway Rabbit (32 in 1) (1988) (Atari) (PAL) (4K)"}, "E80A4026D29777C3C7993FBFAEE8920F":{n:"Frisco (Unknown)"}, "056FF67DD9715FAFA91FB8B0DDCC4A46":{n:"Frisco (Unknown) (PAL) (Hack)"}, "45A4F55BB9A5083D470AD479AFD8BCA2":{n:"Frog Demo (1983) (CommaVid)"}, "F67181B3A01B9C9159840B15449B87B0":{n:"Frog Pond (08-27-1982) (Atari) (Prototype)"}, "5F73E7175474C1C22FB8030C3158E9B3":{n:"Frog Pond (1982) (Atari) (Prototype)"}, "081E2C114C9C20B61ACF25FC95C71BF4":{n:"Frogger (1982) (Parker Bros)"}, "02CED7EA2B7CB509748DB6BFA227EBEC":{n:"Frogger (1982) (Parker Bros) (PAL)"}, "27C6A2CA16AD7D814626CEEA62FA8FB4":{n:"Frogger II (1984) (Parker Bros)",c:1}, "FB91DFC36CDDAA54B09924AE8FD96199":{n:"Frogger II (1984) (Parker Bros) (PAL)",c:1}, "DCC2956C7A39FDBF1E861FC5C595DA0D":{n:"Frogs and Flies (1982) (M Network)"}, "1B8C3C0BFB815B2A1010BBA95998B66E":{n:"Frogs and Flies (1989) (Telegames) (PAL)"}, "4A196713A21EF07A3F74CF51784C6B12":{n:"Frogs and Flies (Jone Yuan) (Hack)"}, "E556E07CC06C803F2955986F53EF63ED":{n:"Front Line (1984) (Coleco)"}, "4CA73EB959299471788F0B685C3BA0B5":{n:"Frostbite (1983) (Activision)"}, "5A93265095146458DF2BAF2162014889":{n:"Frostbite (1983) (Activision) (PAL)"}, "70CE036E59BE92821C4C7FD735EC6F68":{n:"Frostbite (1983) (Activision) (PAL) (16K)"}, "9831EFC7F4CB8FFB4DF0082BAB2F07A3":{n:"Frostbite (1983) (Activision) (PAL) (8K)"}, "F4469178CD8998CB437FA110A228EACA":{n:"Frostbite (1983) (Digitel)"}, "C225379E7C4FB6F886EF9C8C522275B4":{n:"Frostbite (1983) (Video Mania)"}, "C6AE21CACEAAD734987CB24243793BD5":{n:"Frostbite (CCE)"}, "ADB79F9AC1A633CDD44954E2EAC14774":{n:"Frostbite (Digivision)"}, "6B71F20C857574B732E7A8E840BD3CB2":{n:"Frostbite (Unknown) (PAL)"}, "6A9B30CA46B0DBA9E719F4CBD340E01C":{n:"Frostbite (Unknown) (PAL) (Hack)"}, "415C11FCAC66BBD2ACE2096687774B5A":{n:"Fu Kung! (V0.00) (07-01-2003) (AD)"}, "EB3D680699F8762F71F38E28E321234D":{n:"Fu Kung! (V0.01) (08-01-2003) (AD)"}, "9F2D58DCE1B81C6BA201ED103507C025":{n:"Fu Kung! (V0.02) (2003) (AD)"}, "DFF33523CCD2FDC8912E84CAB8E0D982":{n:"Fu Kung! (V0.03) (10-01-2003) (AD)"}, "AB2EA35DCC1098C87455BB8210B018CF":{n:"Fu Kung! (V0.04 Single Line Resolution) (10-01-2003) (AD)"}, "81341F00B61AB37D19D1529F483D496D":{n:"Fu Kung! (V0.04) (10-01-2003) (AD)"}, "7ED7130A6E4020161836414332B11983":{n:"Fu Kung! (V0.05 Cuttle Card Compatible) (13-01-2003) (AD)"}, "61621A556AD3228F0234F5FEB3AB135C":{n:"Fu Kung! (V0.05 Cuttle Card Compattle Revision) (14-01-2003) (AD)"}, "D026716B3C5BE2C951CC4C064317C524":{n:"Fu Kung! (V0.06) (14-01-2003) (AD)"}, "CBAD928E10AEEE848786CC55394FB692":{n:"Fu Kung! (V0.06a Cuttle Cart Compatible) (15-01-2003) (AD)"}, "78C2DE58E42CD1FAAC2EA7DF783EAEB3":{n:"Fu Kung! (V0.07) (25-01-2003) (AD)"}, "9ECA521DB1959156A115DEE85A405194":{n:"Fu Kung! (V0.08) (2003) (AD)"}, "58D331C23297ED98663D11B869636F16":{n:"Fu Kung! (V0.09) (26-01-2003) (AD)"}, "2228C67D25E507603D4873D3934F0757":{n:"Fu Kung! (V0.10) (28-01-2003) (AD)"}, "52E9DB3FE8B5D336843ACAC234AAEA79":{n:"Fu Kung! (V0.11) (28-01-2003) (AD)"}, "D632B74FEA533D593AF82CF16E7C5E4A":{n:"Fu Kung! (V0.13) (01-02-2003) (AD)"}, "6076B187A5D8EA7A2A05111C19B5D5CD":{n:"Fu Kung! (V0.14) (01-02-2003) (AD)"}, "F80CF77164079D774B9B0FAE33DFFCA9":{n:"Fu Kung! (V0.15) (Negative Version) (05-02-2003) (AD)"}, "F1BECA5A198CF08190487E5C27B8E540":{n:"Fu Kung! (V0.16) (2003) (AD)"}, "2240655247D6DE1C585564004A853AB7":{n:"Fu Kung! (V0.17) (07-02-2003) (AD)"}, "0DE53160A8B54C3AA5AED8D68C970B62":{n:"Fuchs & Schweinchen Schlau (1983) (Quelle) (PAL)"}, "456453A54CA65191781AEF316343AE00":{n:"Full Screen Bitmap (3-D Green) (PD)"}, "C3F53993ADE534B0982CA3A286C85BB5":{n:"Full Screen Bitmap Drawing System (12-02-2003) (AD)"}, "819AEEB9A2E11DEB54E6DE334F843894":{n:"Fun with Numbers (1980) (Atari)"}, "DFC03EF371CF5163F54C50D8EE73C8CF":{n:"Fun with Numbers (1980) (Atari) (4K)"}, "5F46D1FF6D7CDEB4B09C39D04DFD50A1":{n:"Fun with Numbers (1980) (Atari) (PAL)"}, "D0CB28E1B7BD6C7F683A0917B59F707E":{n:"Fun with Numbers (1980) (Atari) (PAL) (4K)"}, "D816FEA559B47F9A672604DF06F9D2E3":{n:"Fun with Numbers (32 in 1) (1988) (Atari) (PAL)"}, "08989FA4FF537F5DBD611AFF4019521A":{n:"Fun with Numbers (32 in 1) (1988) (Atari) (PAL) (4K)"}, "D3BB42228A6CD452C111C1932503CC03":{n:"Funky Fish (1983) (UA Limited) (Prototype)",c:1}, "CD568D6ACB2F14477EBF7E59FB382292":{n:"Fussball (Ariola) (PAL)"}, "C1FDD44EFDA916414BE3527A47752C75":{n:"G.I. Joe - Cobra Strike (1983) (Parker Bros)",p:1}, "840A5A2EAEA24D95D289F514FD12F9BB":{n:"GBImprov (Hack)"}, "A3B9D2BE822EAB07E7F4B10593FB5EAA":{n:"GREGXM Demo (PD)"}, "13A991BC9C2FF03753AEB322D3E3E2E5":{n:"Galactic (Funvision) (PAL)"}, "C745487828A1A6A743488ECEBC55AD44":{n:"Galactic (Rainbow Vision) (PAL)"}, "EA7E25ADE3FE68F5B786EE0AA82B1FE5":{n:"Galatic (208 in 1) (Unknown) (PAL)"}, "590AC71FA5F71D3EB29C41023B09ADE9":{n:"Galaxian (01-05-1983) (Atari) (Prototype)"}, "803393ED29A9E9346569DD1BF209907B":{n:"Galaxian (02-04-1983) (Atari) (Prototype)"}, "211774F4C5739042618BE8FF67351177":{n:"Galaxian (1983) (Atari)"}, "13A37CF8170A3A34CE311B89BDE82032":{n:"Galaxian (1983) (Atari) (PAL)"}, "18DC28BC22402F21E1C9B81344B3B8C5":{n:"Galaxian (1983) (Atari) (PAL) [a1]"}, "218B76F5A4142DC2EA9051A768583D70":{n:"Galaxian (1983) (Atari) (PAL) [a2]"}, "D65028524761EF52FBBDEBAB46F79D0F":{n:"Galaxian (CCE)"}, "93C8D9D24F9C5F1F570694848D087DF7":{n:"Galaxian (Digivision)"}, "579BAA6A4AA44F035D245908EA7A044D":{n:"Galaxian Enhanced Graphics (Jess Ragan) (Hack)"}, "D6B8BEEB05E5B730084D4B8F381BBF8D":{n:"Game Select (208 in 1) (Unknown) (PAL)"}, "31F4692EE2CA07A7CE1F7A6A1DAB4AC9":{n:"Game of Concentration (1980) (Atari) (4K)"}, "F539E32BF6CE39C8CA47CB0CDD2C5CB8":{n:"GameLine Master Module ROM (1983) (Control Video)"}, "DB971B6AFC9D243F614EBF380AF0AC60":{n:"Gamma-Attack (1983) (Gammation)"}, "A7523DB9A33E9417637BE0E71FA4377C":{n:"Gangster (Ariola) (PAL)"}, "20EDCC3AA6C189259FA7E2F044A99C49":{n:"Gangster Alley (1982) (Spectravision)"}, "BAE66907C3200BC63592EFE5A9A69DBB":{n:"Gangster Alley (1982) (Spectravision) (PAL)"}, "DC13DF8420EC69841A7C51E41B9FBBA5":{n:"Garfield (06-21-1984) (Atari) (Prototype)"}, "E0EFF071F578ECF19EDC2AB276644E46":{n:"Gas Gauge Demo (2001) (Joe Grand) (PD)"}, "61EF8C2FC43BE9A04FE13FDB79FF2BD9":{n:"Gas Gauge Demo - Revisited (2001) (Joe Grand) (PD)"}, "728152F5AE6FDD0D3A9B88709BEE6C7A":{n:"Gas Hog (1983) (Spectravideo)"}, "5CBD7C31443FB9C308E9F0B54D94A395":{n:"Gas Hog (1983) (Spectravideo) [fixed]"}, "E64A8008812327853877A37BEFEB6465":{n:"Gauntlet (1983) (Answer Software)"}, "E784A9D26707CFCD170A4C1C60422A72":{n:"Gefecht im All (1983) (Quelle) (PAL)"}, "7E464186BA384069582D9F0C141F7491":{n:"General Re-Treat (1982) (PlayAround) (PAL)"}, "2BEE7F226D506C217163BAD4AB1768C0":{n:"Ghost Manor (1983) (Xonox)"}, "0EECB5F58F55DE9DB4EEDB3A0F6B74A8":{n:"Ghost Manor (1983) (Xonox) (4K)"}, "40D8ED6A5106245AA79F05642A961485":{n:"Ghost Manor (1983) (Xonox) (PAL)"}, "3B10106836565E5DB28C7823C0898FBB":{n:"Ghost Manor (1983) (Xonox) (PAL) [a]"}, "7B33407B2B198AF74906B936CE1EECBB":{n:"Ghostbuster 2 (King Atari)",c:1}, "D36308387241E98F813646F346E7F9F7":{n:"Ghostbuster 2 (King Atari) (PAL)",c:1}, "E314B42761CD13C03DEF744B4AFC7B1B":{n:"Ghostbusters (1985) (Activision)"}, "F7D6592DCB773C81C278140ED4D01669":{n:"Ghostbusters (1985) (Activision) (PAL)"}, "721A5567F76856F6B50A6707AA8F8316":{n:"Ghostbusters (1985) (Activision) (PAL) [a]"}, "C2B5C50CCB59816867036D7CF730BF75":{n:"Ghostbusters II (1992) (Salu) (PAL)",c:1}, "643E6451EB6B8AB793EB60BA9C02E000":{n:"Ghostbusters II (1992) (Salu) (PAL) [different tune]",c:1}, "718EE85EA7EC27D5BEA60D11F6D40030":{n:"Ghostbusters II (1992) (Thomas Jentzsch)",c:1}, "1C8C42D1AEE5010B30E7F1992D69216E":{n:"Gigolo (1982) (PlayAround)",c:1}, "F303630A2D7316787AECD67FFF6B2E33":{n:"Gingerbread Man (Fred Quimby)"}, "37E828675D556775AE8285C0CAF7D11C":{n:"Gingerbread Man (Fred Quimby) (Genesis)"}, "5E0C37F534AB5CCC4661768E2DDF0162":{n:"Glacier Patrol (1989) (Telegames)"}, "2D9E5D8D083B6367EDA880E80DFDFAEB":{n:"Glib (1983) (Selchow & Righter)"}, "A591B5E8587AAE0D984A0F6FE2CC7D1C":{n:"Globe Trotter Demo (24-03-2003) (Weston)"}, "0F6676B05621F80C670966E2995B227A":{n:"Globe Trotter Demo 1 (24-03-2003) (Weston)"}, "103F1756D9DC0DD2B16B53AD0F0F1859":{n:"Go Go Home Monster (1983) (Quelle) (PAL)"}, "4093382187F8387E6D011883E8EA519B":{n:"Go Go Home Monster (Unknown)"}, "CFB83A3B0513ACAF8BE4CAE1512281DC":{n:"Going-Up (1983) (Starpath) (Prototype)"}, "2E663EAA0D6B723B645E643750B942FD":{n:"Golf (1980) (Atari)"}, "F542B5D0193A3959B54F3C4C803BA242":{n:"Golf (1980) (Atari) (4K)"}, "9D522A3759AA855668E75962C84546F7":{n:"Golf (1980) (Atari) (PAL)"}, "BB756AA98B847DDDC8FC170BC79F92B2":{n:"Golf (208 in 1) (Unknown) (PAL)"}, "95351B46FA9C45471D852D28B9B4E00B":{n:"Golf (32 in 1) (1988) (Atari) (PAL)"}, "DB5073BD75EB05F7D62A7268396D1E77":{n:"Golf (32 in 1) (1988) (Atari) (PAL) (4K)"}, "C16C79AAD6272BAFFB8AAE9A7FFF0864":{n:"Gopher (1982) (U.S. Games)"}, "A56B642A3D3AB9BBEEE63CD44EB73216":{n:"Gopher (1983) (Carrere Video) (PAL)"}, "8F90590DBA143D783DF5A6CFF2000E4D":{n:"Gopher (208 in 1) (Unknown) (PAL)"}, "06DB908011065E5EBB37F4E253C2A0B0":{n:"Gopher (Unknown) (PAL)"}, "81B3BF17CF01039D311B4CD738AE608E":{n:"Gorf (1982) (CBS Electronics)",c:1}, "3E03086DA53ECC29D855D8EDF10962CB":{n:"Gorf (1982) (CBS Electronics) (PAL)",c:1}, "98BA601A60172CB46C5BF9A962FD5B1F":{n:"Gorilla Kong (Hack)"}, "2903896D88A341511586D69FCFC20F7D":{n:"Grand Prix (1982) (Activision)"}, "DE4436EAA41E5D7B7609512632B90078":{n:"Grand Prix (1982) (Activision) (16K)"}, "5E1B7A6078AF428EF056FE85A37A95CA":{n:"Grand Prix (1982) (Activision) (8K)"}, "757F529026696E13838364DEA382A4ED":{n:"Grand Prix (1982) (Activision) (PAL)"}, "41C4E3D45A06DF9D21B7AAE6AE7E9912":{n:"Grand Prix (1983) (CCE)"}, "E5F84930AA468DB33C0D0F7B26DD8293":{n:"Grand Prix (1983) (CCE) [a]"}, "D5D2D44FB73785996CCC24AE3A0F5CEF":{n:"Grand Prix (Robby)"}, "0F738DC44437557624EB277ED7AD91C9":{n:"Grand Prix (Unknown) (PAL)"}, "9E437229136F1C5E6EF4C5F36178ED18":{n:"Grand Prize (Funvision)"}, "5A9685C4D51A6C1D6A9544946D9E8DC3":{n:"Grandma's Revenge (AtariAge)"}, "4767356FA0ED3EBE21437B4473D4EE28":{n:"Gravitar (04-12-1983) (Atari) (Prototype)"}, "8AC18076D01A6B63ACF6E2CAB4968940":{n:"Gravitar (1983) (Atari)"}, "A81697B0C8BBC338AE4D0046EDE0646B":{n:"Gravitar (CCE)"}, "9245A84E9851565D565CB6C9FAC5802B":{n:"Great Escape (1983) (Bomb)"}, "ED014BEEEB77DBB2BBCF9B5F6850B2F4":{n:"Green Bar Text Demo (PD)"}, "ABC64037CA5D5B04AE8A7EEDBCA3ED74":{n:"Green and Yellow Number 1 Demo (PD)",c:1}, "B41FDD4A522E1D5A2721840028684AC2":{n:"Green and Yellow Number 1 Demo 2 (PD)",c:1}, "42B5E3A35B032F033809AFB0EA28802D":{n:"Gremlins (03-12-1984) (Atari) (Prototype)"}, "01CB3E8DFAB7203A9C62BA3B94B4E59F":{n:"Gremlins (1984) (Atari)"}, "9962034EA7B3D4A905D0991804670087":{n:"Grid Demo (PD)"}, "95A69CF8C08EF1522B050529464F0BCA":{n:"Grid Pattern Demo 1 (20-12-2002) (CT)"}, "8D9A06101EBB0F147936356E645309B8":{n:"Grid Pattern Demo 2 (20-12-2002) (CT)"}, "D65900FEFA7DC18AC3AD99C213E2FA4E":{n:"Grid and Purple Dot Demo (PD)"}, "EB46E99EC15858F8CD8C91CEF384CE09":{n:"Ground Zero (1983) (Goliath) (PAL)"}, "66B89BA44E7AE0B51F9EF000EBBA1EB7":{n:"Grover's Music Maker (01-18-1983) (Atari) (Prototype)"}, "4AC9F40DDFCF194BD8732A75B3F2F214":{n:"Grover's Music Maker (12-29-1982) (Atari) (Prototype)"}, "7AB2F190D4E59E8742E76A6E870B567E":{n:"Guardian (1982) (Apollo)",p:1}, "6A07836C382195DD5305CE61D992AAA6":{n:"Guardian (1982) (Apollo) (Prototype)",p:1}, "F750B5D613796963ACECAB1690F554AE":{n:"Gunfight 2600 (MP)"}, "18B28B386ABDADB3A700AC8FB68E639A":{n:"Gunfight 2600 (MP) (PAL)"}, "6CBE945E16D9F827D0D295546AC11B22":{n:"Gunfight 2600 - AI (MP)"}, "2ABC3D46B3F2140160759E2E10BC86D9":{n:"Gunfight 2600 - Beta Release! (2001) (MP)"}, "9853089672116117258097DBBDB939B7":{n:"Gunfight 2600 - Cowboy Hair (2001) (MP)"}, "A025A8F83A42A4D6D46C4887E799BFAC":{n:"Gunfight 2600 - Descissions had to be made (2001) (MP)"}, "25472DFDEEF6A42581A231D631D6B04D":{n:"Gunfight 2600 - Design thoughts (MP)"}, "14A56B493A8D9D10E94A3E100362E3A2":{n:"Gunfight 2600 - Early Play-kernel (2001) (MP)"}, "0FBA7D8C3520BDB681F75494E498EC36":{n:"Gunfight 2600 - Final Run (MP)"}, "91A3749FF7B7E72B7FA09E05396A0E7B":{n:"Gunfight 2600 - Final Run Part 2 (2002) (MP)"}, "29396DB58406084E416032C372734A3E":{n:"Gunfight 2600 - Fixed Beta Release! (2001) (MP)"}, "862CF669CBCED78F9ED31A5D375B2EBE":{n:"Gunfight 2600 - Flicker acceptance (2001) (MP)"}, "910DD9BF98CC5BC080943E5128B15BF5":{n:"Gunfight 2600 - Improved AI (MP)"}, "C21450C21EFB7715746E9FA87AD6F145":{n:"Gunfight 2600 - It could've been soooo cool, but... (2001) (MP)"}, "D17A671029B1532B197DEFCA5F3649A7":{n:"Gunfight 2600 - Limit broken again! (2001) (MP)"}, "E6F49A1053C79211F82BE4D90DC9FE3D":{n:"Gunfight 2600 - Little progress... (2001) (MP)"}, "C67FF409F28F44883BD5251CEA79727D":{n:"Gunfight 2600 - Music & Bugfixes 1 (2001) (MP)"}, "7D93071B3E3616093A6B5A98B0315751":{n:"Gunfight 2600 - Music & Bugfixes 2 (2001) (MP)"}, "BC703EA6AFB20BC089F04D8C9D79A2BD":{n:"Gunfight 2600 - Not mergeable with Colbert wizardry... (2001) (MP)"}, "111029770226B319524134193886A10E":{n:"Gunfight 2600 - One Limit Reached! (2001) (MP)"}, "68C80E7E1D30DF98A0CF67ECBF39CC67":{n:"Gunfight 2600 - One Step Forward & Two Steps Back (2001) (MP)"}, "E4A0B28BEFAAA2915DF1FA01238B1E29":{n:"Gunfight 2600 - Red River (MP)"}, "CFDB4D0427A1EA8085C6BC6EB90259D8":{n:"Gunfight 2600 - Release Candidate (2001) (MP)"}, "83D15FB9843D9F84AA3710538403F434":{n:"Gunfight 2600 - Release Candidate (2001) (MP) (PAL)"}, "DFCDD6F593BB7B05DBC2E8E1FC6EE0DE":{n:"Gunfight 2600 - Scenarios complete (MP)"}, "D245E2F27C84016041E9496B66B722FE":{n:"Gunfight 2600 - The Final Kernel (MP)"}, "991D57BBCD529AD62925098E0AEC1241":{n:"Gunfight 2600 - The Final Kernel (MP) [a1]"}, "A4F1CEA2C8479284E2A2292F8D51B5FA":{n:"Gunfight 2600 - The Final Kernel Part 2 (MP)"}, "D81BB6965E6C99B3BE99FFD8978740E4":{n:"Gunfight 2600 - The Final Kernel Part 3 (MP)"}, "A15B5831A1FAB52E4C416068C85EC011":{n:"Gunfight 2600 - The Good, The Bad, The Ugly (2001) (MP)"}, "24AD538291EB5F5CAC4B9998F3B851C3":{n:"Gunfight 2600 - This time it's your decission! (2001) (MP)"}, "801BA40F3290FC413E8C816C467C765C":{n:"Gunfight 2600 - Westward Ho! (2001) (MP)"}, "24759BE31E8FE55D2829FD86BDF3181F":{n:"Gunfight 2600 - Worst Nightmare... (2001) (MP)"}, "B311AB95E85BC0162308390728A7361D":{n:"Gyruss (1984) (Parker Bros)",c:1}, "E600F5E98A20FAFA47676198EFE6834D":{n:"Gyruss (1984) (Parker Bros) (PAL)",c:1}, "FCA4A5BE1251927027F2C24774A02160":{n:"H.E.R.O. (1984) (Activision)"}, "D9B49F0678776E04916FA5478685A819":{n:"H.E.R.O. (1984) (Activision) (PAL)"}, "48BCF2C5A8C80F18B24C55DB96845472":{n:"H.E.R.O. (1984) (Activision) (PAL) (16K)"}, "467340A18158649AA5E02A4372DCFCCD":{n:"H.E.R.O. (1984) (Activision) (PAL) [a1]"}, "66B92EDE655B73B402ECD1F4D8CD9C50":{n:"H.E.R.O. (1984) (Activision) (PAL) [a2]"}, "1D284D6A3F850BAFB25635A12B316F3D":{n:"H.E.R.O. (CCE)"}, "769DDC995DBB9EDB8167EFCEA9F34A7C":{n:"H.E.R.O. (Genesis)"}, "BDF1996E2DD64BAF8EFF5511811CA6CA":{n:"H.E.R.O. (Tron)"}, "98E7CAAAB8EC237558378D2776C66616":{n:"HMOVE Test (Bradford W. Mott) (1998) (PD)"}, "30516CFBAA1BC3B5335EE53AD811F17A":{n:"Halloween (1983) (Wizard Video Games)"}, "C450A285DAA7A3B65188C2C3CF04FB3E":{n:"Halloween (1983) (Wizard Video Games) [a]"}, "54DA3B0B3F43F5B37911C135B9432B49":{n:"Halloween III Revision (Hack)",p:1}, "4AFA7F377EAE1CAFB4265C68F73F2718":{n:"Halo 2600 (2010) (Ed Fries)"}, "F16C709DF0A6C52F47FF52B9D95B7D8D":{n:"Hangman (1978) (Atari)"}, "378C118B3BDA502C73E76190CA089EEF":{n:"Hangman (1978) (Atari) (PAL)"}, "C3E4AA718F46291311F1CCE53E6CCD79":{n:"Hangman Ghost 4letter (Hack)"}, "99A24D7BB31D49B720B422550B32C35F":{n:"Hangman Ghost Biglist1 (Hack)"}, "6AA66E9C3EEA76A0C40EF05513497C40":{n:"Hangman Ghost Biglist2 (Hack)"}, "A62E3E19280FF958407E05CA0A2D5EC7":{n:"Hangman Ghost Biglist3 (Hack)"}, "4E37992A37EA36489283F7EB90913BBC":{n:"Hangman Ghost Halloween (Kris) (Hack)"}, "8E822B39A71C84AC875F0107FB61D6F0":{n:"Hangman Ghost Original Words (Hack)"}, "9671B658286E276CC4A3D02AA25931D2":{n:"Hangman Ghost Wordlist (Hack)"}, "502044B1AC111B394E6FBB0D821FCA41":{n:"Hangman Invader 4letter (Hack)"}, "2C9FADD510509CC7F28F1CCBA931855F":{n:"Hangman Invader Biglist1 (Hack)"}, "6C658B52D03E01828B9D2D4718A998AC":{n:"Hangman Invader Biglist2 (Hack)"}, "8A9D953AC3DB52A313A90D6A9B139C76":{n:"Hangman Invader Biglist3 (Hack)"}, "E8F7679359C4F532F5D5E93AF7D8A985":{n:"Hangman Invader Original Words (Hack)"}, "8A42E2C7266439D8997A55D0124C912C":{n:"Hangman Invader Wordlist (Hack)"}, "898748D5EAAC3164B0391A64AE1E0E32":{n:"Hangman Man 4letter (Hack)"}, "135708B9A7DD20576C1B66AB2A41860D":{n:"Hangman Man Biglist1 (Hack)"}, "1F562B89D081E36D58E6FC943512EC05":{n:"Hangman Man Biglist2 (Hack)"}, "5CE98F22ADE915108860424D8DDE0D35":{n:"Hangman Man Biglist3 (Hack)"}, "227532D82505C3C185A878273C285D5F":{n:"Hangman Man Original Words (Hack)"}, "4CA90BA45ECED6F5AD560EA8938641B2":{n:"Hangman Man Wordlist (Hack)"}, "67CF913D1DF0BF2D7AE668060D0B6694":{n:"Hangman Monkey 4letter (Hack)"}, "1738B2E3F25AB3EEF3CECB95E1D0D957":{n:"Hangman Monkey Biglist1 (Hack)"}, "205070B6A0D454961DD9196A8E81D877":{n:"Hangman Monkey Biglist2 (Hack)"}, "DAC38B4DD3DA73BB7B2E9D70C61D2B7C":{n:"Hangman Monkey Biglist3 (Hack)"}, "30C92C685224DC7A72B9BBE5EB62D004":{n:"Hangman Monkey Original Words (Hack)"}, "7860716FA5DBC0FFFAB93FB9A4CB4132":{n:"Hangman Monkey Wordlist (Hack)"}, "CD032AB6764B55438A7B0BFB5E78595A":{n:"Hangman Pac-Man 4letter (Hack)"}, "0A1B98937911D621B004B1617446D124":{n:"Hangman Pac-Man Biglist1 (Hack)"}, "DCA941DAB5C6F859B71883B13ADE9744":{n:"Hangman Pac-Man Biglist2 (Hack)"}, "662ECA7E3D89175BA0802E8E3425DEDB":{n:"Hangman Pac-Man Biglist3 (Hack)"}, "9BD4E0D5F28BA6DA417C26649171F8E4":{n:"Hangman Pac-Man Original Words (Hack)"}, "79D4AF56036EC28F298CAD964A2E2494":{n:"Hangman Pac-Man Wordlist (Hack)"}, "BE1922BD8E09D74DA471287E1E968653":{n:"Hangman Pacman Demo (Cropsy) (Hack)"}, "A8435EC570141DE5D833C4ABEC499E55":{n:"Happy Birthday Demo (2001) (Dennis Debro) (PD)"}, "B9232C1DE494875EFE1858FC8390616D":{n:"Harbor Escape (1983) (Panda)"}, "A34560841E0878C7B14CC65F79F6967D":{n:"Harem (1982) (Multivision)"}, "F0A6E99F5875891246C3DBECBF2D2CEA":{n:"Haunted House (1982) (Atari)"}, "09E1ECF9BD2A3030D5670DBA7A65E78D":{n:"Haunted House (1982) (Atari) (PAL)"}, "06742CF522F23797157F215A1DC8A1A9":{n:"Healthbars (PD)"}, "260C787E8925BF3649C8AEAE5B97DCC0":{n:"Hell Driver (Thomas Jentzsch)"}, "E77F332B71F13884C84771E7A121182D":{n:"Hey! Stop! (Jone Yuan)"}, "FE9AE625D924B54C9F8A14AC9A0F6C6D":{n:"High Bid! (BG Dodson) (Hack)"}, "8FE00172E7FFF4C1878DABCF11BB8DCE":{n:"Hili Ball (1983) (Quelle) (PAL)",c:1}, "CD34B3B3EF9E485201E841BA71BEB253":{n:"Hit HMOVE At Various Cycles After WSYNC Test (Bradford W. Mott) (1998) (PD)"}, "3D48B8B586A09BDBF49F1A016BF4D29A":{n:"Hole Hunter (Video Game Cartridge)"}, "C52D9BBDC5530E1EF8E8BA7BE692B01E":{n:"Holey Moley (02-29-1984) (Atari) (Prototype)"}, "0BFABF1E98BDB180643F35F2165995D0":{n:"Home Run (1978) (Atari)"}, "9F901509F0474BF9760E6EBD80E629CD":{n:"Home Run (1978) (Atari) (4K)"}, "328949872E454181223A80389D03C122":{n:"Home Run (Unknown) (PAL)"}, "24B5F4BBDB853ECA38EA0CAE2DFE73A1":{n:"Home Run (Unknown) (PAL) (4K)"}, "CA7AAEBD861A9EF47967D31C5A6C4555":{n:"Homerun (32 in 1) (1988) (Atari) (PAL)"}, "63811ED69BDBC35C69D8AA7806C3D6E9":{n:"Homerun (32 in 1) (1988) (Atari) (PAL) (4K)"}, "F7A651972D78F9BA485B14690452D4BE":{n:"Homestar Runner Demo #2 (2004-03-29)",c:1}, "6B7A56B6AC2CA4BF9254474BF6ED7D80":{n:"Horizonal Color Bars Demo (PD)"}, "68449E4AABA677ABCD7CDE4264E02168":{n:"Horizonal Color Bars Demo 2 (PD)"}, "70A8480CFAF08776E5420365732159D2":{n:"Horizontally Scrolling Playfield Thing (Rob Kudla) (PD)"}, "78821EF76EBC3934850D1BC1B9E4F4B0":{n:"Hot Action Pak - Ghostbusters, Tennis, Plaque Attack (1990) (HES) (PAL)"}, "CCD6CE508EEE4B3FCA67212833EDCD85":{n:"Hot Wave (Double-Game Package) (1983) (Quelle) (PAL)"}, "2DBC92688F9BA92A7E086D62BE9DF79D":{n:"How to Draw a Playfield (1997) (Jim Crawford) (PD)"}, "D6D5DD8FD322D3CF874E651E7B6C1657":{n:"How to Draw a Playfield (1997) (Nick Bensema) (PD)"}, "9E904E2EAA471C050C491289B8B80F60":{n:"How to Draw a Playfield II (1997) (Erik Mooney) (PD)"}, "4A45C6D75B1BA131F94A9C13194D8E46":{n:"How to Draw a Playfield II (Joystick Hack) (1997) (Eric Bacher) (PD)"}, "7DC03A1F56D0E6A8AAE3E3E50D654A08":{n:"Hozer Video Demo (PD)"}, "11330EAA5DD2629052FAC37CFE1A0B7D":{n:"Human Cannonball (128-in-1 Junior Console) (PAL)"}, "C6C63DA3BC2E47291F63280E057061D0":{n:"Human Cannonball (128-in-1 Junior Console) (PAL) (4K)"}, "7972E5101FA548B952D852DB24AD6060":{n:"Human Cannonball (1979) (Atari)"}, "FFE51989BA6DA2C6AE5A12D277862E16":{n:"Human Cannonball (1979) (Atari) (4K)"}, "10A3CD14E5DCFDDE6FF216A14CE7B7DD":{n:"Human Cannonball (1979) (Atari) (PAL)"}, "AD42E3CA3144E2159E26BE123471BFFC":{n:"Human Cannonball (32 in 1) (1988) (Atari) (PAL)"}, "4BDAE9246D6EE258C26665512C1C8DE3":{n:"Human Cannonball (32 in 1) (1988) (Atari) (PAL) (4K)"}, "42DCC02777B0BCFACD85AEB61D33558A":{n:"Human Cannonball (Unknown) (PAL) (4K)"}, "5BE03A1FE7B2C114725150BE04B38704":{n:"Hunt & Score (1978) (Atari) (PAL)"}, "B26506FBF411009E5E3F7365F442960E":{n:"Hunt & Score (1978) (Atari) (PAL) (4K)"}, "102672BBD7E25CD79F4384DD7214C32B":{n:"Hunt & Score - Memory Match (1978) (Atari)"}, "F4C2E50B01DFF99BDDBE037B3489511C":{n:"Hypnotic (V0.04) (2001) (Inkling) (PD)"}, "7C9B3B8B25ACF2FE3B8DA834F69629C6":{n:"I Robot (1984) (Atari) (Prototype) [!]"}, "F6A282374441012B01714E19699FC62A":{n:"I Want My Mommy (1983) (ZiMAG)",c:1}, "DC33479D66615A3B09670775DE4C2A38":{n:"I.Q. Memory Teaser (Suntek) (PAL)"}, "2016726DB38AD6A68B4C48BA6FE51557":{n:"INV 2 (Piero Cavina, Erik Mooney)"}, "9EA8ED9DEC03082973244A080941E58A":{n:"INV+"}, "AB301D3D7F2F4FE3FDD8A3540B7A74F5":{n:"IQ 180 (Jone Yuan)"}, "4B9581C3100A1EF05EAC1535D25385AA":{n:"IQ 180 (Unknown)"}, "A4C08C4994EB9D24FB78BE1793E82E26":{n:"Ice Hockey (1981) (Activision)"}, "5BCC83677D68F7EF74C1B4A0697BA2A8":{n:"Ice Hockey (1981) (Activision) (16K)"}, "3EB21313EA5D5764C5ED9160A5A55A83":{n:"Ice Hockey (1981) (Activision) (8K)"}, "AC9ADBD6DE786A242E19D4BEC527982B":{n:"Ice Hockey (1981) (Activision) (PAL)"}, "C7D5819B26B480A49EB26AEB63CC831E":{n:"Ice Hockey (4 Game in One Light Green) (1983) (BitCorp) (PAL)"}, "47711C44723DA5D67047990157DCB5DD":{n:"Ice Hockey (CCE)"}, "C3AEB796FDAF9429E8CD6AF6346F337E":{n:"If It's Not One Thing It's Another (1997) (Chris Cracknell)"}, "9A21FBA9EE9794E0FADD7C7EB6BE4E12":{n:"Ikari Warriors (1989) (Atari)"}, "321C3451129357AF42A375D12AFD4450":{n:"Ikari Warriors (1989) (Atari) (PAL)"}, "9813B9E4B8A6FD919C86A40C6BDA8C93":{n:"Ikari Warriors (1989) (Atari) (PAL) [a]"}, "3F251C50AA7237E61A38AB42315EBED4":{n:"Ikari Warriors (1990) (Thomas Jentzsch)"}, "95E542A7467C94B1E4AB24A3EBE907F1":{n:"Im Schutz der Drachen (1983) (Quelle) (PAL)",c:1}, "C4BC8C2E130D76346EBF8EB544991B46":{n:"Imagic Selector ROM (1982) (Imagic)"}, "9B21D8FC78CC4308990D99A4D906EC52":{n:"Immies & Aggies (1983) (CCE)"}, "75A303FD46AD12457ED8E853016815A0":{n:"Immies & Aggies (1983) (ZiMAG) (Prototype)"}, "47ABFB993FF14F502F88CF988092E055":{n:"Inca Gold (Zellers)"}, "F137211537438B1FCE3D811BAEF25457":{n:"Incoming (02-10-2002) (Ben Larson) (PD)"}, "FE870018332A0221EB59FB18B0C6BCCC":{n:"Incoming (08-11-2002) (Ben Larson) (PD)"}, "86B4AA76BBEB70E1A4F9211A9880BA8E":{n:"Incoming (1 Player Version) (05-11-2002) (Ben Larson)"}, "3556E125681AEA864E17B09F3F3B2A75":{n:"Incoming (2 Player Demo) (PD)"}, "15BCD74F2F1F2A63E1AA93E90D2C0555":{n:"Incoming (22-08-2002) (Ben Larson) (PD)"}, "03B1051C9374678363C899914412CFC5":{n:"Incoming (30-10-2002) (Ben Larson) (PD)"}, "76C88341017EAE660EFC6E49C4B6AB40":{n:"Indiana Pitfall (Hack)"}, "C5301F549D0722049BB0ADD6B10D1E09":{n:"Indy 500 (1977) (Atari)"}, "08188785E2B8300983529946DBEFF4D2":{n:"Indy 500 (1977) (Atari) (4K)"}, "DAC762E4D01D445BDEF20B7771F6570E":{n:"Indy 500 (1977) (Atari) (4K) [a]"}, "81591A221419024060B890665BEB0FB8":{n:"Indy 500 (1977) (Atari) (PAL)"}, "63166867F75869A3592B7A94EA62D147":{n:"Indy 500 (Hack) [a1]"}, "30E012E8D50330C8972F126B8E913BC4":{n:"Indy 500 (Hack) [a2]"}, "4F781F0476493C50DC578336F1132A67":{n:"Indy 500 (Unknown) (PAL) (4K)"}, "0C7BD935D9A7F2522155E48315F44FA0":{n:"Infernal Tower (1983) (Carrere Video) (PAL)",c:1}, "AFE88AAE81D99E0947C0CFB687B16251":{n:"Infiltrate (1981) (Apollo)",c:1}, "3B69F8929373598E1752F43F8DA61AA4":{n:"Infiltrate (1981) (Apollo) (PAL)",c:1}, "FB5C8AF97BD8FFE88323656F462645A7":{n:"Interlace Demo (Glenn Saunders)",c:1}, "463E66AD98806A49106CFFA49C08E2ED":{n:"Interlace Game Demo (01-09-2002) (Billy Eno)"}, "91FDB6541F70C40B16AABF8308123BE8":{n:"Interlacing Game (19-08-2002) (Billy Eno)"}, "888DEBB162D7D1AE71025B4AB794257F":{n:"Interleaved ChronoColour - Nude Art (17-04-2003) (AD)"}, "A25BB76E9E773117E567FD4300B1BB23":{n:"Interleaved ChronoColour Demo (NTSC) (05-03-2003) (AD)"}, "3B097A7ED5BD2A84DC3D3ED361E9C31C":{n:"Interleaved ChronoColour Demo (PAL) (05-03-2003) (AD)"}, "FB0E84CEE4C108D24253BCB7E382CFFD":{n:"Interleaved ChronoColour Demo (SECAM) (05-03-2003) (AD)"}, "B4030C38A720DD84B84178B6CE1FC749":{n:"International Soccer (1982) (M Network)"}, "29630A20D356FB58685B150BFA8F00C3":{n:"International Soccer (1982) (Mattel) [a]"}, "CE904C0AE58D36D085CD506989116B0B":{n:"International Soccer (1989) (Telegames) (PAL)"}, "A0185C06297B2818F786D11A3F9E42C3":{n:"International Soccer (Unknown) (PAL)"}, "ADB770FF70E9ADF08BBB907A7ECCD240":{n:"Inv Demo 3 (2001) (Erik Mooney) (PD)"}, "E0CF2DCC4C1348C468F5BB1E421C9164":{n:"Invader Sprites in a Line Demo (PD)"}, "425EE444A41D218598893D6B6E03431A":{n:"Invaders Demo (2001) (TJ)"}, "46C43FDCBCE8FDE3A91EBEAFC05B7CBD":{n:"Invaders Demo (PAL) (2001) (Eckhard Stolberg)"}, "CD139AE6D09F3665AD09EB79DA3F9E49":{n:"Invaders by Erik Mooney (4-24-97) (PD)"}, "8874B68751FD2BA6D3306A263AE57A7D":{n:"Invaders by Erik Mooney (Alpha 1) (PD)"}, "6D475019EA30D0B29F695E9DCFD8F730":{n:"Invaders by Erik Mooney (Alpha 2) (PD)"}, "62992392EA651A16AA724A92E4596ED6":{n:"Invaders by Erik Mooney (Beta) (PD)"}, "4868A81E1B6031ED66ECD60547E6EC85":{n:"Invaders by Erik Mooney (V2.1) (1-3-98) (PD)"}, "80CEC82239913CB8C4016EB13749DE44":{n:"Invaders from Space by David Marli (Space Invaders Hack)"}, "850FFD5849C911946B24544EA1E60496":{n:"Invasion (07-10-2002) (CT)"}, "273CE50DB5A0D6DA7EA827A54F44DEE9":{n:"Island Flyer Demo (PD)"}, "C2778507B83D9540E9BE5713758FF945":{n:"Island Flyer Demo 2 (PD)"}, "2F0546C4D238551C7D64D884B618100C":{n:"Ixion (1984) (Sega) (Prototype)"}, "9C729017DD2F9CCBADCB511187F80E6B":{n:"J-Pac (Hack)"}, "A5262FE6D01D6A1253692682A47F79DD":{n:"JKH Text Scrolling Demo (PD)"}, "CE243747BF34A2DE366F846B3F4CA772":{n:"Jacky Jump (1983) (Home Vision) (PAL)"}, "98EA10C47C13F1B3306C7B13DB304865":{n:"Jam Demo 1 (PD)"}, "60D304582D33E2957B73EB300A7495BB":{n:"Jam Demo 2 (PD)"}, "E51030251E440CFFAAB1AC63438B44AE":{n:"James Bond 007 (1983) (Parker Bros)",c:1}, "04DFB4ACAC1D0909E4C360FD2AC04480":{n:"Jammed (2001) (XYPE) (NTSC)"}, "BA317F83CDFCD58CBC65AAC1CCB87BC5":{n:"Jammed (2001) (XYPE) [a1]"}, "911D385EE0805FF5B8F96C5A63DA7DE5":{n:"Jammed (V0.1) (Demo) (2001) (TJ)"}, "15B498199ED0ED28057BF0DBDCE9B8D8":{n:"Jammed (V0.2) (Demo) (2001) (TJ)"}, "EF5C02C95A1E7ED24F24193935755CD3":{n:"Jammed Demo (1999) (Hozer Video Games)"}, "58A82E1DA64A692FD727C25FAEF2ECC9":{n:"Jaw Breaker (1983) (CCE)"}, "A406D2F6D84E61D842F4CB13B2B1CFA7":{n:"Jawbreaker (1982) (Tigervision) (PAL)"}, "97327D6962F8C64E6F926F79CD01C6B9":{n:"Jawbreaker (Unknown) (PAL)"}, "8F33BCE5BA1053DCF4CEA9C1C69981E4":{n:"Jawbreaker (Unknown) (PAL) [a]"}, "EB4252FAFF7A4F2BA5284A98B8F78D1A":{n:"John K Harvey's Equalizer (NTSC) (PD)",c:1}, "30997031B668E37168D4D0E299CCC46F":{n:"John K Harvey's Equalizer (PAL) (PD)",c:1}, "4FC1B85B8074B4B9436D097900E34F29":{n:"John K. Harvey's Equalizer (John K. Harvey)",c:1}, "E39843C56B7A4A08B18FA7949EC3EE6B":{n:"Joshua Invaders (Hack)"}, "718AE62C70AF4E5FD8E932FEE216948A":{n:"Journey Escape (1982) (Data Age)",c:1}, "6B4EB5B3DF80995B8D9117CB7E9AEB3C":{n:"Journey Escape (1983) (Gameworld) (PAL)",c:1}, "B2D3BCEE001CFF2BD2D8A21B2CB55109":{n:"Joust (08-09-1983) (Atari) (Prototype)",c:1}, "3276C777CBE97CDD2B4A63FFC16B7151":{n:"Joust (1983) (Atari)",c:1}, "640A08E9CA019172D612DF22A9190AFB":{n:"Joust (1983) (Atari) (PAL)",c:1}, "17EE158D15E4A34F57A837BC1CE2B0CE":{n:"Joust (1983) (Atari) (PAL) [a]",c:1}, "22319BE7A640AF5314EC3C482CCEB676":{n:"Joustpong (05-07-2002) (Kirk Israel) (PD)"}, "706E3CC4931F984447213B92D1417AFF":{n:"Joustpong (06-07-2002) (Kirk Israel) (PD)"}, "94102FEBC53B4A78342D11B645342ED4":{n:"Joustpong (14-07-2002) (Kirk Israel) (PD)"}, "814210C0E121F7DBC25661B93C06311C":{n:"Joustpong (16-09-2002) (Kirk Israel) (PD)"}, "C225ABFB584960EFE1F359FC94B73379":{n:"Joustpong (21-09-2002) (Kirk Israel) (PD)"}, "36C29CEEE2C151B23A1AD7AA04BD529D":{n:"Jr. Pac-Man (1984) (Atari)"}, "297C405AFD01F3AC48CDB67B00D273FE":{n:"Jr. Pac-Man (1984) (Atari) (PAL)"}, "25265D0E7F88B3026003809F25EE025E":{n:"Jr. Pac-Man (1984) (Atari) [a]"}, "161DED4A85D3C78E44FFFD40426F537F":{n:"JtzBall (Alpha) (TJ)"}, "80E1410EC98089E0733CC09E584DBA4B":{n:"Jumping Jack (1983) (Dynamics) (PAL)"}, "2CCCC079C15E9AF94246F867FFC7E9BF":{n:"Jungle Fever (1982) (PlayAround)",c:1}, "FD16949913AAAB5BEAEFED73BF2CA67C":{n:"Jungle Hunt (02-03-1983) (Atari) (Prototype)"}, "0EC93F519BB769E0D9F80E61F6CC8023":{n:"Jungle Hunt (02-25-1983) (Atari) (Prototype)"}, "2BB9F4686F7E08C5FCC69EC1A1C66FE7":{n:"Jungle Hunt (1983) (Atari)"}, "9FC2D1627DCDD8925F4C042E38EB0BC9":{n:"Jungle Hunt (1983) (Atari) (PAL)"}, "C47244F5557AE12C61E8E01C140E2173":{n:"Jungle Hunt (1983) (Atari) (PAL) [a1]"}, "2DCF9CE486393CD36CA0928CD53B96CB":{n:"Jungle Hunt (1983) (Atari) (PAL) [a2]"}, "88A6C9C88CB329EE5FA7D168BD6C7C63":{n:"Jungle Hunt (1983) (CCE)"}, "2496D404BFC561A40A80BEA6A69695C3":{n:"Jungle Hunt (1983) (CCE) [a]"}, "000509D1ED2B8D30A9D94BE1B3B5FEBB":{n:"Jungle Jane (2003) (Greg Zumwalt) (Hack)"}, "E1D5C8213E82820128FA9C4775F1E166":{n:"Jungle King (2003) (Jess Ragan) (Hack)"}, "65917AE29A8C9785BB1F2ACB0D6AAFD0":{n:"Junkosoft One Year Demo (1999) (PD)"}, "90B647BFB6B18AF35FCF613573AD2EEC":{n:"Juno First (2009)",c:1}, "FA98D48CD609C9BABC819E0A1BD8D598":{n:"Juno First (2009) (PAL60)",c:1}, "72A5B5052272AC785FA076709D16CEF4":{n:"KC Munckin (29-01-2003) (J. Parlee)"}, "B9D1E3BE30B131324482345959AED5E5":{n:"Kabobber (07-25-1983) (Activision) (Prototype)"}, "5428CDFADA281C569C74C7308C7F2C26":{n:"Kaboom! (1981) (Activision)",p:1}, "E14DC36B24FE22C04FA076E298F2E15F":{n:"Kaboom! (1981) (Activision) (16K)",p:1}, "AF6AB88D3D7C7417DB2B3B3C70B0DA0A":{n:"Kaboom! (1981) (Activision) (4K)",p:1}, "ED8F319E82D355832195EB7715644795":{n:"Kaboom! (1981) (Activision) (8K)",p:1}, "F9E99596345A84358BC5D1FBE877134B":{n:"Kaboom! (1981) (Activision) (PAL)",p:1}, "B09B79C9628878BE051E89F7F1E77378":{n:"Kaboom! (1981) (Activision) (PAL) (4K)",p:1}, "DBDAF82F4F0C415A94D1030271A9EF44":{n:"Kaboom! (CCE)",p:1}, "E49AC0EC879A0D7820BC2598FC2CFCD4":{n:"Kaboom! (CCE) (4K)",p:1}, "A93E8EA1F565C3C1E86B708CF0DC2FA9":{n:"Kabul! (Jess Ragan) (Hack)",p:1}, "7B43C32E3D4FF5932F39AFCB4C551627":{n:"Kamikaze Saucers (1983) (Syncro) (Prototype)"}, "73AA02458B413091AC940C0489301710":{n:"Kampf dem Steinfresser (1983) (Quelle) (PAL)"}, "4326EDB70FF20D0EE5BA58FA5CB09D60":{n:"Kangaroo (1983) (Atari)"}, "6FE67F525C39200A798985E419431805":{n:"Kangaroo (1983) (Atari) (PAL)"}, "DD08E18CFEE87A0E7FC19A684B36E124":{n:"Kangaroo (1983) (Atari) (PAL) [a]"}, "4431428A7500C96FC0E2798A5DBD36D6":{n:"Kangaroo (Genesis)"}, "6D8A04EE15951480CB7C466E5951EEE0":{n:"Kanguru (1983) (Zirok)"}, "10EAE73A07B3DA044B72473D8D366267":{n:"Karate (1982) (Funvision) (PAL)"}, "CEDBD67D1FF321C996051EEC843F8716":{n:"Karate (1982) (Ultravision)"}, "DD17711A30AD60109C8BEACE0D4A76E8":{n:"Karate (Unknown) (PAL)"}, "65BA1A4C643D1AB44481BDDDEB403827":{n:"Katastrophen-Einsatz (1983) (Quelle) (PAL)"}, "A1770EF47146AB7B12E2C4BECCD68806":{n:"Kaystone Kapers (1983) (Digitel)"}, "810D8952AF5A6036FCA8D0C4E1B23DB6":{n:"Keystone (Tiger Vision)"}, "BE929419902E21BD7830A7A7D746195D":{n:"Keystone Kapers (1983) (Activision)"}, "6C1F3F2E359DBF55DF462CCBCDD2F6BF":{n:"Keystone Kapers (1983) (Activision) (PAL)"}, "BEDFBDE71FB606601F936B5B057F26F7":{n:"Keystone Kapers (1983) (Activision) (PAL) (16K)"}, "91925ABCE3A29E33B6A8B81482F4F5AF":{n:"Keystone Kapers (1983) (Activision) (PAL) (8K)"}, "1351C67B42770C1BD758C3E42F553FEA":{n:"Keystone Kapers (Digivision)"}, "F5A3E051730D45FEA518F2E8B926565B":{n:"Keystone Kapers (Robby)"}, "E558BE88EEF569F33716E8E330D2F5BC":{n:"Keystone Kapers (Shock Vision)"}, "8DB152458ABAEF3CFA7A4E420DDBDA59":{n:"Keystone Kapers (Unknown)"}, "05AEDF04803C43EB5E09DFD098D3FD01":{n:"Keystone Kapers (Unknown) (PAL)"}, "4FBE0F10A6327A76F83F83958C3CBEFF":{n:"Keystone Kappers (1983) (CCE)"}, "E28113D10C0C14CC3B5F430B0D142FCB":{n:"Keystone Kappers (1983) (CCE) [a]"}, "7187118674FF3C0BB932E049D9DBB379":{n:"Keystone Keypers (1983) (Zirok)"}, "7A7F6AB9215A3A6B5940B8737F116359":{n:"Killer Satellites (1983) (Arcadia)"}, "75E276BA12DC4504659481C31345703A":{n:"Killer Satellites (1983) (Arcadia) (PAL)"}, "C0A68837C60E15D1FC5A40C9A62894BC":{n:"Killer Satellites (1983) (Arcadia) (Prototype)"}, "9C27EF3BD01C611CDB80182A59463A82":{n:"Killer Satellites (1983) (Arcadia) [a]"}, "05CCF96247AF12EEF59698F1A060A54F":{n:"King Arthur (1983) (Quelle) (PAL)"}, "E21EE3541EBD2C23E817FFB449939C37":{n:"King Kong (1982) (Tigervision)"}, "0DD4C69B5F9A7AE96A7A08329496779A":{n:"King Kong (1982) (Tigervision) (PAL)"}, "0B1056F1091CFDC5EB0E2301F47AC6C3":{n:"King Kong (1982) (Tigervision) (PAL) [a]"}, "E4D41F2D59A56A9D917038682B8E0B8C":{n:"Kiss Meets Pacman (Cody Pittman) (Hack)"}, "B5EFE0271D2214E4D5DC798881486884":{n:"Klax (06-14-1990) (Atari) (Prototype)"}, "2C29182EDF0965A7F56FE0897D2F84BA":{n:"Klax (08-18-1990) (Atari) (Prototype)"}, "EED9EAF1A0B6A2B9BC4C8032CB43E3FB":{n:"Klax (1990) (Atari) (PAL)"}, "7FCD1766DE75C614A3CCC31B25DD5B7A":{n:"Knight on the Town (1982) (PlayAround)",c:1}, "ED0451010D022B96A464FEBCBA70B9C4":{n:"Knight on the Town (1982) (PlayAround) (PAL)",c:1}, "A2EB84CFEED55ACD7FECE7FEFDC83FBB":{n:"Kool Aid Man (Fixed) (15-11-2002) (CT)"}, "2C8C11295D8613F875B7BCF5253AB9BB":{n:"Kool Aid Man (PAL Conversion) (16-11-2002) (Fabrizio Zavagli) (PAL60)"}, "534E23210DD1993C828D944C6AC4D9FB":{n:"Kool-Aid Man (1983) (M Network)"}, "071F84D10B343C7C05CE3E32AF631687":{n:"Krieg der Sterne (Ariola) (PAL)"}, "CC724EBE74A109E39C0B2784DDC980CA":{n:"Krull (05-27-1983) (Atari) (Prototype)"}, "4BAADA22435320D185C95B7DD2BCDB24":{n:"Krull (1983) (Atari)"}, "00DC28B881989C39A6CF87A892BD3C6B":{n:"Krull (CCE)"}, "6805734A0B7BCC8925D9305B071BF147":{n:"Kung Fu (4 Game in One Dark Green) (1983) (BitCorp) (PAL)"}, "0B4E793C9425175498F5A65A3E960086":{n:"Kung Fu Master (CCE)"}, "A9E3C23599C0D77151602F8E31DAF879":{n:"Kung Fu Master (Genesis)"}, "A8101CB667E50A46165C6FB48C608B6B":{n:"Kung Fu Sprite Demo (PD)",c:1}, "CE89529D6E98A13DDF3D84827BBDFE68":{n:"Kung Fu Sprite Demo 2 (PD)",c:1}, "3F58F972276D1E4E0E09582521ED7A5B":{n:"Kung Fu Superkicks (1989) (Telegames)"}, "E5D72FF8BAB4450BE57785CC9E83F3C0":{n:"Kung Fu Superkicks (1989) (Telegames) (PAL)"}, "5B92A93B23523FF16E2789B820E2A4C5":{n:"Kung-Fu Master (1987) (Activision)"}, "4474B3AD3BF6AABE719A2D7F1D1FB4CC":{n:"Kung-Fu Master (1987) (Activision) (PAL)"}, "9945A22F60BBAF6D04A8D73B3CF3DB75":{n:"Kung-Fu Master (1987) (Activision) (PAL) [a]"}, "7AD782952E5147B88B65A25CADCDF9E0":{n:"Kwibble (1983) (Imagic) (Prototype)"}, "B86552198F52CFCE721BAFB496363099":{n:"Kyphus (1982) (Apollo) (Prototype)"}, "0FBF618BE43D4396856D4244126FE7DC":{n:"Labyrinth (1983) (Quelle) (PAL)"}, "01F584BF67B0E464014A8C8B5EA470E3":{n:"Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia)"}, "710497DF2CAAB69CDCC45E919C69E13F":{n:"Labyrinth (Escape from the Mindmaster Beta) (1982) (Arcadia) [a]"}, "ADFBD2E8A38F96E03751717F7422851D":{n:"Lady Bug (NTSC)",c:1}, "F1489E27A4539A0C6C8529262F9F7E18":{n:"Lady Bug (PAL60)",c:1}, "95A89D1BF767D7CC9D0D5093D579BA61":{n:"Lady in Wading (1982) (PlayAround)",c:1}, "EC407A206B718A0A9F69B03E920A0185":{n:"Landung in der Normandie (1983) (Quelle) (PAL)"}, "B7345220A0C587F3B0C47AF33EBE533C":{n:"Landungskommando (1983) (Quelle) (PAL)"}, "85564DD0665AA0A1359037AEF1A48D58":{n:"Laser Base (1983) (ITT Family Games) (PAL) [a]",c:1}, "8C103A79B007A2FD5AF602334937B4E1":{n:"Laser Base (Thomas Jentzsch)"}, "D2C8E6AA8172B16C8AA9AAE739AC9C5E":{n:"Laser Blast (08-08-1980) (Activision) (Prototype)"}, "931B91A8EA2D39FE4DCA1A23832B591A":{n:"Laser Blast (1981) (Activision)"}, "9EC1B259A1BCFFA63042A3C2B3B90F0A":{n:"Laser Blast (1981) (Activision) (16K)"}, "D5E27051512C1E7445A9BF91501BDA09":{n:"Laser Blast (1981) (Activision) (4K)"}, "F6676E3FE901EB8515FC7AE310302C3C":{n:"Laser Blast (1981) (Activision) (8K)"}, "8A8E401369E2B63A13E18A4D685387C6":{n:"Laser Blast (1981) (Activision) (PAL)"}, "F7F50D9C9D28BCC9F7D3075668B7AC89":{n:"Laser Blast (1981) (Activision) (PAL) (4K)"}, "0D1B3ABF681A2FC9A6AA31A9B0E8B445":{n:"Laser Blast (32 in 1) (1988) (Atari) (PAL)"}, "303242C239474F2D7763B843DE58C1C3":{n:"Laser Blast (CCE)"}, "F9420173EFCB4B9F2B01C2A7B595CCA7":{n:"Laser Blast (CCE) (4K)"}, "D078674AFDF24A4547B4B32890FDC614":{n:"Laser Blast (Jone Yuan)"}, "3F6938AA6CE66E6F42E582C1EB19B18C":{n:"Laser Blast (Jone Yuan) (4K) (Hack)"}, "91B007F33F9B790BE64F57220EC52E80":{n:"Laser Blast (Jone Yuan) (Hack)"}, "D339B95F273F8C3550DC4DAA67A4AA94":{n:"Laser Blast (Unknown) (PAL) (4K)"}, "0277C449FAE63F6F1C8F94DEDFCF0058":{n:"Laser Demo (B. Watson)"}, "68760B82FC5DCF3FEDF84376A4944BF9":{n:"Laser Gate (1983) (CCE)"}, "CD4DED1EDE63C4DD09F3DD01BDA7458C":{n:"Laser Gate (Future Video Games) (PAL)"}, "1FA58679D4A39052BD9DB059E8CDA4AD":{n:"Laser Gates (1983) (Imagic)"}, "8E4CD60D93FCDE8065C1A2B972A26377":{n:"Laser Gates (1983) (Imagic) (PAL)"}, "48287A9323A0AE6AB15E671AC2A87598":{n:"Laser Volley (Zellers)"}, "1FAB68FD67FE5A86B2C0A9227A59BB95":{n:"Lasercade (1983) (20th Century Fox) (Prototype)"}, "19098C46DA0640F2B5763167DEA6C716":{n:"Laseresal 2002 (NTSC) (PD)"}, "F9655ED51462ECFC690C7B97CEC649F9":{n:"Laseresal 2002 (PAL) (PD)"}, "02DCBA28C614FEC7CA25955327128ABB":{n:"Laseresal 2002 (PAL) (PD) [a]"}, "9C6FD6ED3599978AB7B6F900484B9BE6":{n:"Laseresal 2002 (PAL60) (PD)"}, "FABCA526D57DE46768B392F758F1A008":{n:"Laseresal 2600 (16-12-2001) (Andrew Wallace) (PD)"}, "31E518DEBBA46DF6226B535FA8BD2543":{n:"Last Starfighter (1984) (Atari) (Prototype)"}, "BB579404924C40CA378B4AFF6CCF302D":{n:"Lightbulb Lightens, The (PD) (Non Functional)"}, "D0CDAFCB000B9AE04AC465F17788AD11":{n:"Lilly Adventure (1983) (Quelle) (PAL)"}, "3947EB7305B0C904256CDBC5C5956C0F":{n:"Lilly Adventure (Jone Yuan)"}, "64D43859258DC8CA54949E9FF4174202":{n:"Lilly Adventure (Thomas Jentzsch)"}, "FE0B7F27E3AD50BBF9FF468EE56D553D":{n:"Lines Demo (Eckhard Stolberg) (PAL) (PD)"}, "86128001E69AB049937F265911CE7E8A":{n:"Lochjaw (1981) (Apollo)"}, "71464C54DA46ADAE9447926FDBFC1ABE":{n:"Lock 'n' Chase (1982) (M Network)"}, "493E90602A4434B117C91C95E73828D1":{n:"Lock 'n' Chase (1989) (Telegames) (PAL)"}, "E88340F5BD2F03E2E9CE5ECFA9C644F5":{n:"Lock 'n' Chase (Unknown) (PAL)"}, "B4E2FD27D3180F0F4EB1065AFC0D7FC9":{n:"London Blitz (1983) (Avalon Hill)"}, "5BABE0CAD3EC99D76B0AA1D36A695D2F":{n:"Looping (1983) (Coleco) (Prototype)"}, "E24D7D879281FFEC0641E9C3F52E505A":{n:"Lord of the Rings (1983) (Parker Bros) (Prototype)"}, "C6D7FE7A46DC46F962FE8413C6F53FC9":{n:"Lord of the Rings (1983) (Parker Bros) (Prototype) [a]"}, "DAEF7D8E5A09981C4AA81573D4DBB380":{n:"Lord of the Rings (Adam Thornton) (Hack)",c:1}, "E4B12DEAAFD1DBF5AC31AFE4B8E9C233":{n:"Lord of the Rings (Adam Thornton) (Hack) [a]",c:1}, "7C00E7A205D3FDA98EB20DA7C9C50A55":{n:"Lost Luggage (1981) (Apollo)"}, "D0B26E908370683AD99BC6B52137A784":{n:"Lost Luggage (1981) (Apollo) (PAL)"}, "2D76C5D1AAD506442B9E9FB67765E051":{n:"Lost Luggage (1981) (Apollo) [no opening scene]"}, "DF5CC5CCCDC140EB7107F5B8ADFACDA1":{n:"Lumberman (Cracker Jack) (Hack)"}, "97D0151BEB84ACBE82AA6DB18CD91B98":{n:"Lunar Attack (2002) (Steve Engelhardt) (Hack)"}, "393E41CA8BDD35B52BF6256A968A9B89":{n:"M.A.D. (1982) (U.S. Games)"}, "090F0A7EF8A3F885048D213FAA59B2F8":{n:"M.A.D. (1983) (Carrere Video) (PAL)"}, "835759FF95C2CDC2324D7C1E7C5FA237":{n:"M.A.S.H (1983) (20th Century Fox)"}, "43C6CFFFEDDAB6B3787357FED9D44529":{n:"M.A.S.H (1983) (20th Century Fox) (PAL)"}, "E97EAFD0635651D3999CECE953C06BD5":{n:"M.A.S.H (208 in 1) (Unknown) (PAL)"}, "9193B6FFF6897D43274741D4F9855B6D":{n:"M.A.S.H (Unknown) (PAL) (Hack)"}, "CF63FFAC9DA89EF09C6C973083061A47":{n:"MASH (1983) (CCE)"}, "1423F560062C4F3C669D55891A2BCBE7":{n:"MASH (1983) (CCE) [a]"}, "E9BE3E8E4A7E73DD63ED4235A3A1A25F":{n:"MMetall (Hack)"}, "47AAD247CCE2534FD70C412CB483C7E0":{n:"Mafia (Rainbow Vision) (PAL)"}, "CDDABFD68363A76CD30BEE4E8094C646":{n:"MagiCard (1981) (CommaVid)"}, "7DA9DE8D62FCDD3A2C545B2E720C2A61":{n:"MagiCard (1981) (CommaVid) (4K)"}, "CCB5FA954FB76F09CAAE9A8C66462190":{n:"Malagai (1983) (Answer Software)",c:1}, "402D876EC4A73F9E3133F8F7F7992A1E":{n:"Man Goes Down (2006) (A. Herbert) (Prototype)"}, "54A1C1255ED45EB8F71414DADB1CF669":{n:"Mangia' (1983) (Spectravideo)"}, "D8295EFF5DCC43360AFA87221EA6021F":{n:"Mangia' (1983) (Spectravideo) (PAL)"}, "E4C2077A18E3C27F4819AA7757903AA0":{n:"Many Blue Bars Demo (PD)"}, "CEF01595000627EE50863D4290372C27":{n:"Many Blue Bars and Text Demo (PD)"}, "163E7E757E2DC44469123FF0E5DAEC5E":{n:"Many Blue Bars and Text Demo 2 (PD)"}, "F032B2F2D8323404A6B4541F92DD1825":{n:"Many Blue Bars and Text Demo 3 (PD)"}, "EF60B06FDDB675B0D783AFBFA5FC5232":{n:"Many Blue Bars and Text Demo 4 (PD)"}, "13895EF15610AF0D0F89D588F376B3FE":{n:"Marauder (1982) (Tigervision)"}, "512E874A240731D7378586A05F28AEC6":{n:"Marauder (1982) (Tigervision) (PAL)"}, "CC03C68B8348B62331964D7A3DBEC381":{n:"Marauder (Jone Yuan)"}, "319A142AAB6260842AB616382848C204":{n:"Marble Craze (05-02-2002) (Paul Slocum)"}, "F777444FC21A5925E066B68B1D350575":{n:"Marble Craze (Kernel Works) (Paul Slocum)"}, "F2E4FB2D3600C0F76D05864E658CC57B":{n:"Marble Craze (Kernel) (17-02-2002) (Paul Slocum)"}, "89A65B83203980D5D4D60F52A584A5B8":{n:"Marble Craze (PAL) (02-02-2003) (Paul Slocum)"}, "21B09C40295C2D7074A83AE040F22EDF":{n:"Marble Craze (V0.90) (Easy Version) (Paul Slocum)"}, "097074F24CDE141FE6A0F26A10333265":{n:"Marble Craze (V0.90) (Paul Slocum)"}, "34B269387FA1AA5A396636F5ECDD63DD":{n:"Marble Craze (mc7_23) (Paul Slocum)"}, "CD9FEA12051E414A6DFE17052067DA8E":{n:"Marble Craze Demo (PD)"}, "966B11D3C147D894DD9E4EBB971EA309":{n:"Marble Craze Song (Paul Slocum) (PD)"}, "6141C095D0AEE4E734BEBFAAC939030A":{n:"Mariana (Rainbow Vision) (PAL)"}, "EE84BDC5DAE268E227E407C7B5E6B6B7":{n:"Marilyn Monroe Demo (PD)"}, "CADE123747426DF69570A2BC871D3BAF":{n:"Marine Wars (1983) (Gakken) (PAL)"}, "B00E8217633E870BF39D948662A52AAC":{n:"Marine Wars (1983) (Konami)"}, "1B8D35D93697450EA26EBF7FF17BD4D1":{n:"Marineflieger (1983) (Quelle) (PAL)"}, "E908611D99890733BE31733A979C62D8":{n:"Mario Bros. (1983) (Atari)"}, "C49FE437800AD7FD9302F3A90A38FB7D":{n:"Mario Bros. (1983) (Atari) (PAL)"}, "2A9F9001540C55A302BEFD8E9D54B47B":{n:"Mario Bros. (1983) (Atari) (PAL) [a]"}, "9A165C39AF3F050FDEE6583FDFCDC9BE":{n:"Mario Bros. (Zirok)"}, "B1D1E083DC9E7D9A5DC1627869D2ADE7":{n:"Mario's Bros. (1983) (CCE)"}, "C446288FE62C0C2737639FD788AE4A21":{n:"Mark's Sound Demo (PD)",c:1}, "B2F0D7217147160B2F481954CEDF814B":{n:"Marquee Drawer (2001) (B. Watson)",c:1}, "B1486E12DE717013376447AC6F7F3A80":{n:"Marspatrouille (1983) (Quelle) (PAL)"}, "36E47ED74968C365121EAB60F48C6517":{n:"Master Builder (1983) (Quelle) (PAL)"}, "AE4BE3A36B285C1A1DFF202157E2155D":{n:"Master Builder (1983) (Spectravideo)"}, "3B76242691730B2DD22EC0CEAB351BC6":{n:"Masters of the Universe (1983) (M Network)",c:1}, "470878B9917EA0348D64B5750AF149AA":{n:"Math Gran Prix (1982) (Atari)"}, "45BEEF9DA1A7E45F37F3F445F769A0B3":{n:"Math Gran Prix (1982) (Atari) (PAL)"}, "7996B8D07462A19259BAA4C811C2B4B4":{n:"Math Gran Prix (208 in 1) (Unknown) (PAL)"}, "5E2495D43B981010304AF55EFED1E798":{n:"Math Gran Prix (Jone Yuan)"}, "244C6DE27FAFF527886FC7699A41C3BE":{n:"Matt Demo (PD)"}, "DDD1EFC1862CD3EB3BAF4CBA81FF5050":{n:"Max3 (2001) (Maxime Beauvais) (PD)"}, "AE83541CF4A4C0BCE0ADCCD2C1BF6288":{n:"Maze 003 Demo (PD)"}, "F825C538481F9A7A46D1E9BC06200AAF":{n:"Maze Craze (1980) (Atari)"}, "ED2218B3075D15EAA34E3356025CCCA3":{n:"Maze Craze (1980) (Atari) (PAL)"}, "8108AD2679BD055AFEC0A35A1DCA46A4":{n:"Maze Craze (Unknown)"}, "69EBF910AB9B63E5B8345F016095003B":{n:"Maze Demo 1 (PD)"}, "F9DE91D868D6EBFB0076AF9063D7195E":{n:"Maze Demo 2 (PD)"}, "35B43B54E83403BB3D71F519739A9549":{n:"McDonald's (06-06-1983) (Parker Bros) (Prototype)"}, "F7FAC15CF54B55C5597718B6742DBEC2":{n:"Medieval Mayhem (NTSC)",p:1}, "D00F6F8BA89559E4B20972A478FC0370":{n:"Medieval Mayhem (PAL)",p:1}, "DAEB54957875C50198A7E616F9CC8144":{n:"Mega Force (1982) (20th Century Fox)"}, "ECF51385384B468834611D44A8429C03":{n:"Mega Force (1982) (20th Century Fox) (PAL)"}, "BDBAEFF1F7132358EA64C7BE9E46C1AC":{n:"Mega Force (1982) (20th Century Fox) (PAL) [a]"}, "E37C8055D70979AF354251EBE9F1B7DD":{n:"Mega Funpak - Gorf, P. Patrol, Pacman, Skeet Shoot (HES) (PAL)"}, "28A2BEA8F84936CB2E063F857414CDA0":{n:"Mega Mania Raid (1999) (Thiago Paiva) (Hack)"}, "B65D4A38D6047735824EE99684F3515E":{n:"MegaBoy (Dynacom)"}, "318A9D6DDA791268DF92D72679914AC3":{n:"MegaMania (1982) (Activision)"}, "A35D47898B2B16EC641D1DFA8A45C2B7":{n:"MegaMania (1982) (Activision) (16K)"}, "D45BF71871B196022829AA3B96BFCFD4":{n:"MegaMania (1982) (Activision) (8K)"}, "3D934BB980E2E63E1EAD3E7756928CCD":{n:"MegaMania (1982) (Activision) (PAL)"}, "6604F72A966CA6B2DF6A94EE4A68EB82":{n:"MegaMania (208 in 1) (Unknown) (PAL)"}, "049626CBFB1A5F7A5DC885A0C4BB758E":{n:"MegaMania (Unknown) (PAL)"}, "FC92D74F073A44BC6E46A3B3FA8256A2":{n:"Megademo (19xx) (PD)"}, "6BB22EFA892B89B69B9BF5EA547E62B8":{n:"Megamania (1982) (Dynacom)"}, "D5618464DBDC2981F6AA8B955828EEB4":{n:"Megamania (1983) (CCE)"}, "12937DB3D4A80DA5C4452B752891252D":{n:"Megamania (1983) (Digitel)"}, "1E0EF01E330E5B91387F75F700CCAF8F":{n:"Mein Weg (1983) (Quelle) (PAL)"}, "96E798995AF6ED9D8601166D4350F276":{n:"Meltdown (1983) (20th Century Fox) (Prototype)",c:1}, "50568C80AC61CAB789D9923C9B05B68E":{n:"Merlin's Walls - Standard Edition (1999) (Ebivision)"}, "8FBABAA87941CDF3A377C15E95BDB0F3":{n:"Meteor Smasher (SnailSoft)"}, "08BF437D012DB07B05FF57A0C745C49E":{n:"Meteoroids (1982) (Arcadia) (Prototype)",c:1}, "F1554569321DC933C87981CF5C239C43":{n:"Midnight Magic (1984) (Atari)",c:1}, "DA732C57697AD7D7AF414998FA527E75":{n:"Midnight Magic (1984) (Atari) (PAL)",c:1}, "C47B7389E76974FD0DE3F088FEA35576":{n:"Mighty Mouse (Funvision)"}, "0BF19E40D5CD8AA5AFB33B16569313E6":{n:"Millipede (01-04-1984) (Atari) (Prototype)"}, "3C57748C8286CF9E821ECD064F21AAA9":{n:"Millipede (1984) (Atari)"}, "A7673809068062106DB8E9D10B56A5B3":{n:"Millipede (1984) (Atari) (PAL)"}, "11BCF5C752088B5AAF86D6C7A6A11E8D":{n:"Millipede (1984) (Atari) (Prototype)"}, "EFD387430A35A659FF569A9A0EC22209":{n:"Millipede (1984) (Atari) (Prototype) (PAL)"}, "0E224EA74310DA4E7E2103400EB1B4BF":{n:"Mind Maze (10-10-1984) (Atari) (Prototype)"}, "FA0570561AA80896F0EAD05C46351389":{n:"Miner 2049er (1982) (Tigervision)"}, "C517144E3D3AC5C06F2F682EBF212DD7":{n:"Miner 2049er (1982) (Tigervision) (PAL)"}, "598A4E6E12F8238B7E7555F5A7777B46":{n:"Miner 2049er (1982) (Tigervision) (Prototype)"}, "3B040ED7D1EF8ACB4EFDEEBEBDAA2052":{n:"Miner 2049er (1982) (Tigervision) [fixed]"}, "2A1B454A5C3832B0240111E7FD73DE8A":{n:"Miner 2049er Volume II (1983) (Tigervision)",c:1}, "468F2DEC984F3D4114EA84F05EDF82B6":{n:"Miner 2049er Volume II (1983) (Tigervision) (PAL)",c:1}, "4543B7691914DFD69C3755A5287A95E1":{n:"Mines of Minos (1982) (CommaVid)",c:1}, "B5CB9CF6E668EA3F4CC2BE00EA70EC3C":{n:"Mines of Minos (1982) (CommaVid) (PAL)",c:1}, "73CB1F1666F3FD30B52B4F3D760C928F":{n:"Mines of Minos (Unknown) (PAL)",c:1}, "635CC7A0DB33773959D739D04EFF96C2":{n:"Minesweeper (V.90) (Soren Gust) (PD)"}, "AC5F78BAE0638CF3F2A0C8D07EB4DF69":{n:"Minesweeper (V.99) (Soren Gust) (PD)"}, "2982E655DFFC89D218A0A3072CFC6811":{n:"Mini Golf 812631 (Hack)"}, "DF62A658496AC98A3AA4A6EE5719C251":{n:"Miniature Golf (1979) (Atari)"}, "384DB97670817103DD8C0BBDEF132445":{n:"Miniature Golf (1979) (Atari) (4K)"}, "ED5CCFC93AD4561075436EE42A15438A":{n:"Miniature Golf (1979) (Atari) (PAL)"}, "8B8152D6081F31365406CB716BD95567":{n:"Miniature Golf (1979) (Atari) (PAL) (4K)"}, "4F82D8D78099DD71E8E169646E799D05":{n:"Miniature Golf (Unknown) (PAL) (4K)"}, "73521C6B9FED6A243D9B7B161A0FB793":{n:"Miniaturer Golf (32 in 1) (1988) (Atari) (PAL)"}, "6979F30204149BE3E227558CFFE21C1D":{n:"Miniaturer Golf (32 in 1) (1988) (Atari) (PAL) (4K)"}, "391764720140C432AEC454A468F77A40":{n:"Miss Pack Man (Video Game Program) (PAL)"}, "4181087389A79C7F59611FB51C263137":{n:"Miss Piggy's Wedding (06-24-1983) (Atari) (Prototype) (8K)"}, "855A42078B14714BCFD490D2CF57E68D":{n:"Miss Piggy's Wedding (1983) (Atari) (Prototype)"}, "25E73EFB9A6EDF119114718BD2F646BA":{n:"Miss Piggy's Wedding (1983) (Atari) (Prototype) [a]"}, "3A2E2D0C6892AA14544083DFB7762782":{n:"Missile Command (1981) (Atari)",l:"missile command",c:1}, "9364AD51C321E0F15C96A8C0AFF47CEB":{n:"Missile Command (1981) (Atari) (PAL)",l:"missile command",c:1}, "1A8204A2BCD793F539168773D9AD6230":{n:"Missile Command (1981) (Atari) [no initials]",l:"missile command"}, "94E7CC6342D11E508E7E8B2DDF53C255":{n:"Missile Command (208 in 1) (Unknown) (PAL) (Hack)"}, "8D1E2A6D2885966E6D86717180938F87":{n:"Missile Command (Amiga Mouse) (2002) (TJ)",l:"missile command",c:1}, "183020A80848E06A1238A1AB74079D52":{n:"Missile Command (Amiga Mouse) (2002) (TJ) (PAL)",l:"missile command",c:1}, "8CE9126066F2DDD5173E9F1F9CE1494E":{n:"Missile Command (CX-22 Trackball) (2002) (TJ)",l:"missile command",c:1}, "8BEBAC614571135933116045204F0F00":{n:"Missile Command (CX-22 Trackball) (2002) (TJ) (PAL)",l:"missile command",c:1}, "2365E1534D67F94D8670394AB99150CE":{n:"Missile Command (CX-80 Trackball) (2002) (TJ)",l:"missile command",c:1}, "96ECCC2277043508A6C481EA432D7DD9":{n:"Missile Command (CX-80 Trackball) (2002) (TJ) (PAL)",l:"missile command",c:1}, "F6A9EA814D15B85BFFE980C927DF606B":{n:"Missile Command (Unknown) (PAL)",l:"missile command",c:1}, "CB24210DC86D92DF97B38CF2A51782DA":{n:"Missile Control (1983) (Video Gems) (PAL)"}, "E6E5BB0E4F4350DA573023256268313D":{n:"Missile Control (Thomas Jentzsch)"}, "53D181CDE2E0219B5754CAAD246FCB66":{n:"Missile Demo (1998) (Ruffin Bailey) (PD)"}, "317A4CDBAB090DCC996833D07CB40165":{n:"Missile War (1983) (Goliath) (PAL)"}, "4C6AFB8A44ADF8E28F49164C84144BFE":{n:"Mission 3,000 A.D. (1983) (BitCorp)"}, "6EFE876168E2D45D4719B6A61355E5FE":{n:"Mission 3,000 A.D. (1983) (BitCorp) (PAL)",c:1}, "CFAD2B9CA8B8FEC7FB1611D656CC765B":{n:"Mission 3,000 A.D. (1983) (BitCorp) (PAL) [demo cart]",c:1}, "B83579C4450FCBDF2B108903731FA734":{n:"Mission 3,000 A.D. (208 in 1) (Unknown) (PAL)",c:1}, "CF9069F92A43F719974EE712C50CD932":{n:"Mission Survive (1983) (Video Gems) (PAL)",c:1}, "B5CDBAB514EA726A14383CFF6DB40E26":{n:"Mission Survive (1983) (Video Gems) (PAL) [a]",c:1}, "3783F12821B88B08814DA8ADB1A9F220":{n:"Mission Survive (PAL) (Genesis)",c:1}, "B676A9B7094E0345A76EF027091D916B":{n:"Mission Survive (Thomas Jentzsch)",c:1}, "E13818A5C0CB2F84DD84368070E9F099":{n:"Misterious Thief, A (1983) (CCE)",c:1}, "5D9592756425192EC621D2613D0E683D":{n:"Misterious Thief, A (1983) (CCE) [a]"}, "B4A4C87840613F102ACB5B3A647D0A67":{n:"Mobile 48 Sprite Kernel (04-01-2003) (Eric Ball)"}, "073CB76B006AF034FD150BE3F5E0E7E6":{n:"Mobile 48 Sprite Kernel (Bug Fixed) (10-01-2003) (Eric Ball)"}, "63E9E612BBEE31045F8D184A4E53F8EC":{n:"Moby Blues (2002) (ATARITALIA) (Hack)"}, "7AF40C1485CE9F29B1A7B069A2EB04A7":{n:"Mogul Maniac (1983) (Amiga)"}, "F802FA61011DD9EB6F80B271BAC479D0":{n:"Mole Hunter (Suntek) (PAL)"}, "6BDE3F6AC31ACEEF447CE57D4D2C2EC0":{n:"Mondo Pong V1 (Piero Cavina) (PD)",p:1}, "1F60E48AD98B659A05CE0C1A8E999AD9":{n:"Mondo Pong V2 (Piero Cavina) (PD)",p:1}, "6913C90002636C1487538D4004F7CAC2":{n:"Monster Cise (1984) (Atari) (Prototype)"}, "3347A6DD59049B15A38394AA2DAFA585":{n:"Montezuma's Revenge (1984) (Parker Bros)"}, "4AB2EBD95A8F861EA451ABEBDAD914A5":{n:"Montezuma's Revenge (PAL) (Genesis)"}, "9F59EDDF9BA91A7D93BCE7EE4B7693BC":{n:"Montezuma's Revenge (Thomas Jentzsch) (PAL60)"}, "7B8A481E0C5AA78150B5555DFF01F64E":{n:"Moon Patrol (05-16-1983) (Atari) (Prototype)"}, "AC3DD22DD945724BE705DDD2785487C2":{n:"Moon Patrol (06-15-1983) (Atari) (Prototype)"}, "E2C1B60EAA8EDA131632D73E4E0C146B":{n:"Moon Patrol (07-04-1983) (Atari) (Prototype)"}, "5256F68D1491986AAE5CFDFF539BFEB5":{n:"Moon Patrol (07-26-1983) (Atari) (Prototype)"}, "94FF6B7489ED401DCAAF952FECE10F67":{n:"Moon Patrol (07-31-1983) (Atari) (Prototype)"}, "515046E3061B7B18AA3A551C3AE12673":{n:"Moon Patrol (1983) (Atari)"}, "65490D61922F3E3883EE1D583CE10855":{n:"Moon Patrol (1983) (Atari) (PAL)"}, "0AFE6AE18966795B89314C3797DD2B1E":{n:"Moon Patrol (1983) (Atari) (PAL) [a]"}, "6DE924C2297C8733524952448D54A33C":{n:"Moon Patrol (1983) (CCE)"}, "2854E5DFB84173FAFC5BF485C3E69D5A":{n:"Moon Patrol (Canal 3)"}, "5643EE916F7DC760148FCA4DB3AA7D10":{n:"Moon Patrol (Genesis)"}, "1B22A3D79DDD79335B69C94DD9B3E44E":{n:"Moon Patrol (Tron)"}, "44E9C4A047C348DBEB7ACE60F45484B4":{n:"Moon Patrol Arcade (Genesis)"}, "203ABB713C00B0884206DCC656CAA48F":{n:"Moonsweeper (1983) (Imagic)",c:1}, "4AF4103759D603C82B1C9C5ACD2D8FAF":{n:"Moonsweeper (1983) (Imagic) (PAL)",c:1}, "B79FE32320388A197AC3A0B932CC2189":{n:"Moonsweeper (1983) (Imagic) (PAL) [a]",c:1}, "B06050F686C6B857D0DF1B79FEA47BB4":{n:"Moonsweeper (1988) (Activision)",c:1}, "AE6CB335470788B94BEB5787976E8818":{n:"Mortal Kurling (02-01-2003) (CT)"}, "EB503CC64C3560CD78B7051188B7BA56":{n:"Moto Laser (Star Game)"}, "378A62AF6E9C12A760795FF4FC939656":{n:"MotoRodeo (1990) (Atari)",c:1}, "B1E2D5DC1353AF6D56CD2FE7CFE75254":{n:"MotoRodeo (1990) (Atari) (PAL)",c:1}, "A20B7ABBCDF90FBC29AC0FAFA195BD12":{n:"Motocross (1983) (Quelle) (PAL)"}, "5641C0FF707630D2DD829B26A9F2E98F":{n:"Motocross (Joystik)"}, "F5A2F6EFA33A3E5541BC680E9DC31D5B":{n:"Motocross (Suntek) (PAL)"}, "DE0173ED6BE9DE6FD049803811E5F1A8":{n:"Motocross Racer (1983) (Xonox)"}, "DB4EB44BC5D652D9192451383D3249FC":{n:"Mountain King (1983) (CBS Electronics)",c:1}, "7E51A58DE2C0DB7D33715F518893B0DB":{n:"Mountain King (1983) (CBS Electronics) [a]",c:1}, "23D445EA19A18FB78D5035878D9FB649":{n:"Mouse Trap (1982) (CBS Electronics) (PAL)",c:1}, "5678EBAA09CA3B699516DBA4671643ED":{n:"Mouse Trap (1982) (Coleco)",c:1}, "35156407E54F67EB1F625450D5C093E1":{n:"Mouse Trap (Genesis)"}, "24FBF8250A71611E40EF18552E61B009":{n:"Movable Grid Demo (PD)"}, "6342AFE9C9AD1B6120B8F6FB040D0926":{n:"Move a Blue Blob Demo (PD)"}, "F69A39B215852A0C2764D2A923C1E463":{n:"Move a Blue Blob Demo 2 (PD)"}, "140909D204ABD6841C64CDAD4D7765B4":{n:"Moving Blue Ladder Demo (PD)"}, "703D32062436E4C20C48313DFF30E257":{n:"Moving Maze Demo (PD)",c:1}, "AA7BB54D2C189A31BB1FA20099E42859":{n:"Mr. Do! (1983) (CBS Electronics) (PAL)",c:1}, "0164F26F6B38A34208CD4A2D0212AFC3":{n:"Mr. Do! (1983) (Coleco)",c:1}, "B7A7E34E304E4B7BC565EC01BA33EA27":{n:"Mr. Do!'s Castle (1984) (Parker Bros)",c:1}, "0CB7AF80FD0DDEF84844481D85E5D29B":{n:"Mr. Pac-Man (El Destructo)"}, "0DFBDADF8F1BC718E7E1BB3CCD5FEF3D":{n:"Mr. Pac-Man (New start tune) (El Destructo)"}, "603C7A0D12C935DF5810F400F3971B67":{n:"Mr. Postman (1983) (BitCorp) (PAL)"}, "8644352B806985EFDE499AE6FC7B0FEC":{n:"Mr. Postman (1983) (CCE)"}, "9A4274409216FF09ECDE799F2A56AC73":{n:"Mr. Postman (1983) (CCE) [a]"}, "2327456F86D7E0DEDA94758C518D05B3":{n:"Mr. Postman (Digitel)"}, "F0DAAA966199EF2B49403E9A29D12C50":{n:"Mr. Postman (Unknown)"}, "CFF9950D4E650094F65F40D179A9882D":{n:"Mr. Roboto (Paul Slocum) (Hack)",c:1}, "87E79CD41CE136FD4F72CC6E2C161BEE":{n:"Ms. Pac-Man (1982) (Atari)"}, "1EE9C1BA95CEF2CF987D63F176C54AC3":{n:"Ms. Pac-Man (1982) (Atari) (PAL)"}, "D4942F4B55313FF269488527D84CE35C":{n:"Ms. Pac-Man (1982) (Atari) (PAL) [a]"}, "1EA980574416BFD504F62575BA524005":{n:"Ms. Pac-Man (1982) (Atari) (Prototype)"}, "AEB104F1E7B166BC0CBACA0A968FDE51":{n:"Ms. Pac-Man (1999) (Hack)"}, "9469D18238345D87768E8965F9F4A6B2":{n:"Ms. Pac-Man (CCE)"}, "4066309EB3FA3E7A725585B9814BC375":{n:"Multi Ball Demo (PD)"}, "079FE9103515D15BC108577E234A484D":{n:"Multi-Color Demo 0 (Bob Colbert) (PD)"}, "4AFE528A082F0D008E7319EBD481248D":{n:"Multi-Color Demo 1 (Bob Colbert) (PD)"}, "191449E40B0C56411C70772706F79224":{n:"Multi-Color Demo 2 (Bob Colbert) (PD)"}, "AE18C11E4D7ED2437F0BF5D167C0E96C":{n:"Multi-Color Demo 3 (Bob Colbert) (PD)"}, "C28B29764C2338B0CF95537CC9AAD8C9":{n:"Multi-Color Demo 4 (Bob Colbert) (PD)"}, "D34B933660E29C0A0A04004F15D7E160":{n:"Multi-Color Demo 5 (Bob Colbert) (PD)"}, "14163EB2A3DDD35576BD8527EAE3B45E":{n:"Multi-Color Demo 6 (Bob Colbert) (PD)"}, "B1FD0B71DE9F6EEB5143A97963674CB6":{n:"Multi-Color Demo 7 (Bob Colbert) (PD)"}, "25F9CF703575C5D63048C222F5463758":{n:"Multi-Sprite Demo 1 (PD)"}, "42AE81AE8AC51E5C238639F9F77D91AE":{n:"Multi-Sprite Demo 2 (Piero Cavina) (PD)"}, "17515A4D0B7EA5029FFFF7DFA8456671":{n:"Multi-Sprite Demo V1.1 (Piero Cavina) (PD)"}, "EF71E9FB0D8D477226D8D42261FBF0A7":{n:"Multi-Sprite Demo V2.0 (Piero Cavina) (PD)"}, "B958D5FD9574C5CF9ECE4B9421C28ECD":{n:"Multi-Sprite Game V1.0 (Piero Cavina) (PD)"}, "59135F13985B84C4F13CC9E55EEC869A":{n:"Multi-Sprite Game V2.0 (Piero Cavina) (PD)"}, "7197B6CBDE6ECD10376155E6B848E80D":{n:"Multi-Sprite Game V2.1 (Piero Cavina) (PD)"}, "585600522B1F22F617652C962E358A5D":{n:"Multi-Sprite Game V2.2 (Piero Cavina) (PD)"}, "E609E8A007127B8FCFF79FFC380DA6B1":{n:"Multi-Sprite Game V2.3 (Piero Cavina) (PD)"}, "50EF88F9A5E0E1E6B86E175362A27FDB":{n:"Multi-Sprite Game V2.4 (Piero Cavina) (PD)"}, "157356F80C709AB675961D8B8B207E20":{n:"Multi-Sprite Game V2.5 (Piero Cavina) (PD)"}, "072A6EA2181CA0DF88AC0DEDC67B239D":{n:"Multiple Missiles Demo (19-12-2002) (CT)"}, "7550B821EE56FB5833DCA2BE88622D5A":{n:"Multiple Moving Objects Demo (B. Watson)"}, "CD3E26786136A4692FD2CB2DFBC1927E":{n:"Multiple Moving Objects Demo 2 (B. Watson)"}, "A100EFF2D7AE61CA2B8E65BAF7E2AAE8":{n:"Muncher (David Marli) (Hack)"}, "5BBA254E18257E578C245ED96F6B003B":{n:"Music Effects Demo (21-01-2003) (Paul Slocum)",c:1}, "F5AA6BD10F662199C42E43863A30106C":{n:"Music Kit (V1.0) - Song Player (Paul Slocum)",c:1}, "6F084DAF265599F65422EF4173B69BC7":{n:"Music Kit (V2.0) - Song Player (Paul Slocum)",c:1}, "65B106EBA3E45F3DAB72EA907F39F8B4":{n:"Music Machine, The (1983) (Sparrow)",p:1}, "04FCCC7735155A6C1373D453B110C640":{n:"My Golf (1990) (HES) (PAL)"}, "936F555B4B1A2CD061B659FF63F4F5F2":{n:"My Golf (1990) (HES) (PAL) [a1]"}, "DFAD86DD85A11C80259F3DDB6151F48F":{n:"My Golf (1990) (HES) (PAL) [fixed]"}, "EE6CBEDF6C0AAC90FAA0A8DBC093FFBE":{n:"My Golf (CCE) (PAL)"}, "0546F4E6B946F38956799DD00CAAB3B1":{n:"My Golf (Thomas Jentzsch)"}, "FCBBD0A407D3FF7BF857B8A399280EA1":{n:"Mysterious Thief, A (1983) (ZiMAG) (Prototype)",c:1}, "48F18D69799A5F5451A5F0D17876ACEF":{n:"Mysterious Thief, A (1983) (ZiMAG) (Prototype) [a]",c:1}, "FA7E11A3DBEA4365975CD2F094E61D25":{n:"Mystery Science Theater 2600 (1999) (Tim Snider) (Hack)"}, "7608ABDFD9B26F4A0ECEC18B232BEA54":{n:"NFL Football (32 in 1) (1988) (Atari) (PAL)"}, "67C05AE94BF8B83A666C3AE2C4BC14DE":{n:"NFL Football (32 in 1) (1988) (Atari) (PAL) (4K)"}, "C58708C09CCB61625CDA9D15DDCD8BE6":{n:"NOIZ Invaders (SPIKE) (2002) (Hack)"}, "36306070F0C90A72461551A7A4F3A209":{n:"Name This Game (1982) (U.S. Games)"}, "F98D2276D4A25B286135566255AEA9D0":{n:"Name This Game (1983) (Digitel)"}, "2F7949F71076DB42480D3F5036B4A332":{n:"Name This Game (208 in 1) (Unknown) (PAL) (Hack)"}, "B392964E8B1C9C2BED12246F228011B2":{n:"Name This Game (Unknown) (PAL)"}, "0614ED51ACD027D531E7C85C4F435292":{n:"Narnia (Glenn Saunders) (PD)"}, "709910C2E83361BC4BF8CD0C20C34FBF":{n:"Netmaker (Rainbow Vision) (PAL)"}, "3F9CB1ABA8EC20E2C243AE642F9942BF":{n:"New Questions (1998) (John K. Harvey) (PD)"}, "1201C18CF00D2C236F42E4D7D8C86AA1":{n:"Nick Bensema Demo (Nick Bensema)"}, "392F00FD1A074A3C15BC96B0A57D52A1":{n:"Night Driver (1980) (Atari)",p:1,c:1}, "F48022230BB774A7F22184B48A3385AF":{n:"Night Driver (1980) (Atari) (4K)",p:1,c:1}, "FEEC54AAC911887940B47FE8C9F80B11":{n:"Night Driver (1980) (Atari) (PAL)",p:1,c:1}, "D9DA2AE7C7894A29B43B3C6B79F3B7A2":{n:"Night Driver (1980) (Atari) (PAL) (4K)",p:1,c:1}, "BD39598F067A1193AE81BD6182E756D1":{n:"Night Stalker (1989) (Telegames) (PAL)"}, "2783006EE6519F15CBC96ADAE031C9A9":{n:"Night Stalker (1989) (Telegames) (PAL) [a]"}, "EAD60451C28635B55CA8FEA198444E16":{n:"Nightmare (1983) (Sancho) (PAL)"}, "27F9E2E1B92AF9DC17C6155605C38E49":{n:"Nightmare (CCE)"}, "BDB4B584DDC90C9D2EC7E21632A236B6":{n:"Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack)"}, "DDA23757407C4E217F64962C87AD0C82":{n:"Nitemare at Sunshine Bowl-a-Rama (Atari Freak 1) (Hack) [a]"}, "B6D52A0CF53AD4216FEB04147301F87D":{n:"No Escape! (1982) (Imagic)"}, "DC81C4805BF23959FCF2C649700B82BF":{n:"No Escape! (1982) (Imagic) (PAL)"}, "D8DF256C0D89E494A9FB3E9ABB8E44AC":{n:"No Escape! (1982) (Imagic) (PAL) [a]"}, "9912D06EEA42200A198DD3E2BE18C601":{n:"No Escape! (1982) (Imagic) [a]"}, "637EFAC676FF063F2FBB0ABFF77C4FA5":{n:"Noize Maker Demo (PD)"}, "34F4B1D809AA705ACE6E46B13253FD3B":{n:"Nothern Alliance (Aaron Bergstrom) (Hack)"}, "E3C35EAC234537396A865D23BAFB1C84":{n:"Nuts (1983) (TechnoVision) (PAL)"}, "DE7A64108074098BA333CC0C70EEF18A":{n:"Nuts (Unknown)"}, "9ED0F2AA226C34D4F55F661442E8F22A":{n:"Nuts (Unknown) (PAL)"}, "133A4234512E8C4E9E8C5651469D4A09":{n:"Obelix (1983) (Atari)"}, "19E739C2764A5AB9ED08F9095AA2AF0B":{n:"Obelix (1983) (Atari) (PAL)"}, "669840B0411BFBAB5C05B786947D55D4":{n:"Obelix (1983) (Atari) (PAL) [a]"}, "A189F280521F4E5224D345EFB4E75506":{n:"Obelix (1983) (Thomas Jentzsch)"}, "4CABC895EA546022C2ECAA5129036634":{n:"Ocean City (Funvision)"}, "45CB0F41774B78DEF53331E4C3BF3362":{n:"Octopus (1983) (Carrere Video) (PAL)"}, "B6166F15720FDF192932F1F76DF5B65D":{n:"Off Your Rocker (1983) (Amiga) (Prototype)"}, "98F63949E656FF309CEFA672146DC1B8":{n:"Off the Wall (1989) (Atari)"}, "36EDEF446AB4C2395666EFC672B92ED0":{n:"Off the Wall (1989) (Atari) (PAL)"}, "0BF1E354304F46C0CAF8FC0F6F5E9525":{n:"Official Frogger (1983) (Arcadia) [a]"}, "E823B13751E4388F1F2A375D3560A8D7":{n:"Official Frogger (Preview) (1983) (Arcadia) [a]"}, "C73AE5BA5A0A3F3AC77F0A9E14770E73":{n:"Official Frogger, The (1983) (Arcadia)"}, "A74689A08746A667A299B0507E1E6DD9":{n:"Official Frogger, The (1983) (Arcadia) (PAL)"}, "F5D103A9AE36D1D4EE7EEF657B75D2B3":{n:"Official Frogger, The (Preview) (1983) (Arcadia)"}, "95FD6097DC27C20666F039CFE34F7C69":{n:"Oh No! (Version 1) (17-01-2003) (AD)"}, "5A734779D797CCEF25DC8ACFA47244C7":{n:"Oh No! (Version 2) (18-01-2003) (AD)"}, "FDD4995A50395DB14F518F63C2D63438":{n:"Oh No! (Version 3) (18-01-2003) (AD)"}, "DE07E9CB43AD8D06A35F6506E22C62E9":{n:"Oh No! (Version 4) (22-01-2003) (AD)"}, "C9C25FC536DE9A7CDC5B9A916C459110":{n:"Oink! (1982) (Activision)"}, "06B6C5031B8353F3A424A5B86B8FE409":{n:"Oink! (1982) (Activision) (PAL)"}, "3DA7CC7049D73D34920BB73817BD05A9":{n:"Oink! (1983) (Activision) (16K)"}, "2CF20F82ABCAE2DECFF88DB99331E071":{n:"Oink! (1983) (Activision) (8K)"}, "F8648D0C6AD1266434F6C485FF69EC40":{n:"Oink! (CCE)"}, "853C11C4D07050C22EF3E0721533E0C5":{n:"Oink! (Unknown) (PAL)"}, "8101EFAFCF0AF32FEDDA4579C941E6F4":{n:"Okie Dokie (4K) (PD)"}, "CE4BBE11D682C15A490AE15A4A8716CF":{n:"Okie Dokie (Older) (PD)"}, "CCA33AE30A58F39E3FC5D80F94DC0362":{n:"Okie Dokie (PD)"}, "9947F1EBABB56FD075A96C6D37351EFA":{n:"Omega Race (1983) (CBS Electronics)"}, "257BC3B72A6B5DB3FD0D47619125B387":{n:"Omega Race (1983) (CBS Electronics) [a]"}, "5B5D04887922B430DE0B7B2A21F9CD25":{n:"Omega Race (Genesis)"}, "A9784C24CDDB33BD0D14442B97784F3D":{n:"Omega Race DC (2003) (TJ) (Omega Race Hack)"}, "3B6DBA1A24BB2893BD3BD0593F92016B":{n:"Omega Race JS (TJ)"}, "61426CEE013306E7F7367534AB124747":{n:"One Blue Bar Demo (PD)"}, "B83DF1F32B4539C324BDF94851B4DB55":{n:"One On One by Angelino (Basketball Hack)"}, "8786F4609A66FBEA2CD9AA48CA7AA11C":{n:"Open Sesame (1983) (Goliath) (PAL)",c:1}, "28D5DF3ED036ED63D33A31D0D8B85C47":{n:"Open Sesame (1983) (Goliath) (PAL) [a]",c:1}, "90578A63441DE4520BE5324E8F015352":{n:"Open Sesame (4 Game in One Dark Green) (1983) (BitCorp) (PAL)",c:1}, "C880C659CDC0F84C4A66BC818F89618E":{n:"Open Sesame (Thomas Jentzsch)",c:1}, "52385334AC9E9B713E13FFA4CC5CB940":{n:"Open, Sesame! (1983) (CCE)",c:1}, "CC7138202CD8F6776212EBFC3A820ECC":{n:"Oscar's Trash Race (03-30-1983) (Atari) (Prototype)"}, "4B94FD272785D7EC6C95FB7279D0F522":{n:"Oscar's Trash Race (12-03-1982) (Atari) (Prototype)"}, "FA1B060FD8E0BCA0C2A097DCFFCE93D3":{n:"Oscar's Trash Race (1983) (Atari)"}, "47911752BF113A2496DBB66C70C9E70C":{n:"Oscar's Trash Race (1983) (Atari) (PAL)"}, "55949CB7884F9DB0F8DFCF8707C7E5CB":{n:"Othello (1981) (Atari)"}, "02CEE0B140D2F1A1EFCFB1D482A5C392":{n:"Othello (1981) (Atari) (4K)"}, "2C3B9C171E214E9E46BBAA12BDF8977E":{n:"Othello (1981) (Atari) (4K) [a]"}, "A0E2D310E3E98646268200C8F0F08F46":{n:"Othello (1981) (Atari) (PAL)"}, "95956108289A917F80667ECCD3CE98A9":{n:"Othello (1981) (Atari) (PAL) (4K)"}, "00E19EBF9D0817CCFB057E262BE1E5AF":{n:"Othello (1981) (Atari) (PAL) [no grid markers]"}, "113CD09C9771AC278544B7E90EFE7DF2":{n:"Othello (1981) (Atari) [no grid markers]"}, "7D9C96B215D1941E87B6FB412EB9204F":{n:"Othello (Unknown) (PAL) (4K)"}, "F97DEE1AA2629911F30F225CA31789D4":{n:"Out of Control (1983) (Avalon Hill)"}, "890C13590E0D8D5D6149737D930E4D95":{n:"Outlaw (1978) (Atari)"}, "F060826626AAC9E0D8CDA0282F4B7FC3":{n:"Outlaw (1978) (Atari) (4K)"}, "22675CACD9B71DEA21800CBF8597F000":{n:"Outlaw (1978) (Atari) (PAL)"}, "3EAE062A9B722BDA1255D474A87ECA5C":{n:"Outlaw (1978) (Atari) (PAL) (4K)"}, "2E3728F3086DC3E71047FFD6B2D9F015":{n:"Outlaw (32 in 1) (1988) (Atari) (PAL)"}, "F661F129644F338B13D9F4510D816C03":{n:"Outlaw (32 in 1) (1988) (Atari) (PAL) (4K)"}, "7F819454734DDF93F83FEFCFFCD3E212":{n:"Outlaw (Jone Yuan) (4K)"}, "1EC5BEF77B91E59313CBA205F15B06D7":{n:"Overhead Adventure Demo 1 (PD)"}, "4066D7D88EC4A2C656127A67FA52DCF1":{n:"Overhead Adventure Demo 2 (PD)"}, "3C7A96978F52B2B15426CDD50F2C4048":{n:"Overhead Adventure Demo 3 (PD)"}, "0CFDD2F3B243CAC21F38A0F09F54BEAD":{n:"Overhead Adventure Demo 4 (PD)"}, "D5AA7472E7F2CC17E893A1A36F8DADF0":{n:"Overhead Adventure Demo 5 (PD)"}, "F45644FF82B533A781A1EE50F2E95F3C":{n:"Overhead Adventure Demo 6 (PD)"}, "4689081B7363721858756FE781CC7713":{n:"Oystron (V2.6) (Piero Cavina) (PD)"}, "26F4F8B098609164EFFEF7809E0121E1":{n:"Oystron (V2.7) (Piero Cavina) (PD)"}, "E6508B878145187B87B9CDED097293E7":{n:"Oystron (V2.8) (Piero Cavina) (PD)"}, "70D14C66C319683B4C19ABBE0E3DB57C":{n:"Oystron (V2.82) (Piero Cavina) (PD)"}, "5360693F1EB90856176BD1C0A7B17432":{n:"Oystron (V2.85) (Piero Cavina) (PD)"}, "91F0A708EEB93C133E9672AD2C8E0429":{n:"Oystron (V2.9) (Piero Cavina) (PD)"}, "AA2C4B32656BDE9A75042A4D158583E1":{n:"Oystron X (Piero Cavina) (PD)"}, "C7E43AD79C5E5C029D9F5FFDE23E32CF":{n:"PAL-NTSC Detector (15-11-2002) (CT)"}, "106326C262DFD3E8EAEABD961D2A0519":{n:"PAL-NTSC Detector (15-11-2002) (CT)[a1]"}, "6AC3FD31A51730358708C7FDC62487F8":{n:"PC Invaders (Matthias Jaap) (Hack)"}, "9C7FA3CFCAAAFB4E6DAF1E2517D43D88":{n:"PIEROXM Demo (PD)"}, "D0498BACA989E792DB4B8270A02B9624":{n:"Pac Ghost Sprite Demo (PD)"}, "BD430C2193045C68D1A20A018A976248":{n:"Pac Ghost Sprite Demo 2 (PD)"}, "F9DA42F91A1C5CFA344D2FF440C6F8D4":{n:"Pac Invaders (ZUT)"}, "88D300A38BDD7CAB9EDAD271C18CD02B":{n:"Pac Kong (Funvision) (PAL)"}, "936EF1D6F8A57B9FF575DC195EE36B80":{n:"Pac Kong (Unknown)"}, "CA53FC8FD8B3C4A7DF89AC86B222EBA0":{n:"Pac Man (1983) (CCE)",l:"PAC-MAN",lc:"#f0f010"}, "651D2B6743A3A18B426BCE2C881AF212":{n:"Pac Man (1983) (CCE) [a]",l:"PAC-MAN",lc:"#f0f010"}, "B36040A2F9ECAFA73D835D804A572DBF":{n:"Pac Man (1983) (Digitel)",l:"PAC-MAN",lc:"#f0f010"}, "EBF9038E927E6A0DB3E0D170C59911E6":{n:"Pac-2600 (PD)"}, "D223BC6F13358642F02DDACFAF4A90C9":{n:"Pac-Kong (Rainbow Vision) (PAL)"}, "A4B99AA5ED85CFDB7D101923147DE035":{n:"Pac-Law (Jim Goebel) (Hack)"}, "3B8AACF5F5638492B926B5124DE19F18":{n:"Pac-Man (1981) (Atari) (8K)",l:"PAC-MAN",lc:"#f0f010"}, "72DB1194B1CC7D45B242F25EB1C148D3":{n:"Pac-Man (1981) (Atari) (Hack)",l:"PAC-MAN",lc:"#f0f010"}, "6E372F076FB9586AFF416144F5CFE1CB":{n:"Pac-Man (1982) (Atari)",l:"PAC-MAN",lc:"#f0f010"}, "FC2233FC116FAEF0D3C31541717CA2DB":{n:"Pac-Man (1982) (Atari) (PAL)",l:"PAC-MAN",lc:"#f0f010"}, "C2410D03820E0FF0A449FA6170F51211":{n:"Pac-Man (Unknown) (PAL) (Hack)"}, "6B6CA32228AE352B4267E4BD2CDDF10C":{n:"Pac-Man 4 (Pac-Man Hack)"}, "C569E57DCA93D3BEE115A49923057FD7":{n:"Pac-Space (Pac-Man Hack)"}, "D7B58303EC8D8C4DBCBF54D3B9734C7E":{n:"Paddle Demo (Joe Grand) (PD)",p:1}, "82BF0DFF20CEE6A1ED4BB834B00074E6":{n:"Panda (Quest) (Suntek) (PAL)"}, "0E713D4E272EA7322C5B27D645F56DD0":{n:"Panda Chase (1983) (Home Vision) (PAL)"}, "F8582BC6CA7046ADB8E18164E8CECDBC":{n:"Panda Chase (Unknown) (PAL)"}, "714E13C08508EE9A7785CEAC908AE831":{n:"Parachute (1983) (Home Vision) (PAL)"}, "245F07C8603077A0CAF5F83EE6CF8B43":{n:"Parachute (Thomas Jentzsch)"}, "012B8E6EF3B5FD5AABC94075C527709D":{n:"Party Mix (1983) (Arcadia)",p:1}, "7EF3CA08ABDE439C6CCCA84693839C57":{n:"Party Mix (1983) (Arcadia) (PAL)",p:1}, "4C0FB2544AE0F8B5F7AE8BCE7BD7F134":{n:"Party Mix (Preview) (1983) (Arcadia)",p:1}, "7D940D749E55B96B7B746519FA06F2DE":{n:"Party Mix (Preview) (1983) (Arcadia) (PAL)",p:1}, "36C31BB5DAEB103F488C66DE67AC5075":{n:"Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia)",p:1}, "FF86FC8FFA717BB095E8471638C1C31C":{n:"Party Mix - Bop a Buggy (1 of 3) (1983) (Arcadia) (PAL)",p:1}, "6ED5012793F5DDF4353A48C11EA9B8D3":{n:"Party Mix - Down on the Line (3 of 3) (1983) (Arcadia)",p:1}, "0E86470791B26292ABE1C64545C47985":{n:"Party Mix - Down on the Line (3 of 3) (1983) (Arcadia) (PAL)",p:1}, "AAEA37B65DB9E492798F0105A6915E96":{n:"Party Mix - Tug of War (2 of 3) (1983) (Arcadia)",p:1}, "08F4DC6F118F7C98E2406C180C08E78E":{n:"Party Mix - Tug of War (2 of 3) (1983) (Arcadia) (PAL)",p:1}, "E40A818DAC4DD851F3B4AAFBE2F1E0C1":{n:"Peek-A-Boo (1984) (Atari) (Prototype)"}, "17BBE288C3855C235950FEA91C9504E9":{n:"Pega Ladrao (Dismac)"}, "ACE319DC4F76548659876741A6690D57":{n:"Pele's Soccer (1981) (Atari)"}, "7A09299F473105AE1EF3AD6F9F2CD807":{n:"Pele's Soccer (1981) (Atari) (PAL)"}, "4BCC7F6BA501A26EE785B7EFBFB0FDC8":{n:"Pengo (1983) (Atari) (Prototype)"}, "04014D563B094E79AC8974366F616308":{n:"Pengo (1984) (Atari)"}, "87B6A17132FC32F576BC49EA18729506":{n:"Pengo (1984) (Atari) (PAL)"}, "212D0B200ED8B45D8795AD899734D7D7":{n:"Pepsi Invaders (1983) (Atari)"}, "6CE2110AC5DD89AB398D9452891752AB":{n:"Persian Gulf War (Funvision)"}, "09388BF390CD9A86DC0849697B96C7DC":{n:"Pete Rose Baseball (1988) (Absolute)"}, "CB4A7B507372C24F8B9390D22D54A918":{n:"Peter Penguin (1983) (ITT Family Games) (PAL)"}, "3685060707DF27D4091BA0EA2DC4B059":{n:"PezZerk - PezMan in Ghost Manor (Hack)"}, "E959B5A2C882CCAACB43C32790957C2D":{n:"Phantom II & Pirate (NTSC)"}, "069C17BEB1E8E0557ADB8539FDCF6CBA":{n:"Phantom II & Pirate (PAL60)"}, "6B1FC959E28BD71AED7B89014574BDC2":{n:"Phantom Tank (1982) (BitCorp) (PAL)"}, "B29359F7DE62FED6E6AD4C948F699DF8":{n:"Phantom Tank (1982) (Puzzy) (PAL)"}, "5A9D188245AFF829EFDE816FCADE0B16":{n:"Phantom Tank (1983) (CCE) (PAL)"}, "7454786AF7126CCC7A0C31FCF5AF40F1":{n:"Phantom Tank (Unknown) (PAL)"}, "4D38E1105C3A5F0B3119A805F261FCB5":{n:"Phantom UFO (4 Game in One Light Green) (1983) (BitCorp) (PAL)"}, "08BD4C1DCC843F6A0B563D9FD80B3B11":{n:"Phantompanzer II (1983) (Quelle) (PAL)"}, "E9034B41741DCEE64AB6605ABA9DE455":{n:"Phanton Tank (Digivision)"}, "3577E19714921912685BB0E32DDF943C":{n:"Pharaoh's Curse (1983) (TechnoVision) (PAL)",c:1}, "2AE700C9DBA843A68DFDCA40D7D86BD6":{n:"Pharaoh's Curse (Thomas Jentzsch)",c:1}, "62F74A2736841191135514422B20382D":{n:"Pharaoh's Curse (Unknown)",c:1}, "A69F5B1761A8A11C98E706EC7204937F":{n:"Pharaoh's Curse (Unknown) (PAL)",c:1}, "3AB5D138E26D88C8190E7CC629A89493":{n:"Phased Color Demo (PD)",c:1}, "7DCBFD2ACC013E817F011309C7504DAA":{n:"Phaser Patrol (1982) (Arcadia)",c:1}, "72305C997F2CEC414FE6F8C946172F83":{n:"Phaser Patrol (1982) (Arcadia) (PAL)",c:1}, "7867EE819B53D69CFCFE740F7DDCA574":{n:"Phaser Patrol (1982) (Arcadia) (Prototype)",c:1}, "A7A58E9291AEFA1064E933071F60D4EF":{n:"Phaser Patrol (1982) (Arcadia) (Prototype) [a]",c:1}, "A412C8577B2D57B09185AE51739AC54F":{n:"Phaser Patrol (1982) (Arcadia) [a]",c:1}, "CA54DE69F7CDF4D7996E86F347129892":{n:"Philly Flasher (1982) (PlayAround)",p:1}, "7E52A95074A66640FCFDE124FFFD491A":{n:"Phoenix (1982) (Atari)"}, "79FCDEE6D71F23F6CF3D01258236C3B9":{n:"Phoenix (1982) (Atari) (PAL)"}, "FD8B4EE0D57605B35E236E814F706FF1":{n:"Phoenix (1982) (Atari) (PAL) [a]"}, "A00EC89D22FCC0C1A85BB542DDCB1178":{n:"Phoenix (1983) (CCE)"}, "00E55B27FE2E96354CD21B8B698D1E31":{n:"Phoenix (Unknown)"}, "A8633050A686270FCF6C0CC4DCBAD630":{n:"Phoenix (Zirok)"}, "C4060A31D61BA857E756430A0A15ED2E":{n:"Pick 'n Pile (2003) (TJ)",c:1}, "DA79AAD11572C80A96E261E4AC6392D0":{n:"Pick 'n' Pile (1990) (Salu) (PAL)",c:1}, "1D4E0A034AD1275BC4D75165AE236105":{n:"Pick Up (1983) (20th Century Fox) (Prototype)"}, "17C0A63F9A680E7A61BEBA81692D9297":{n:"Picnic (1982) (U.S. Games)",p:1}, "24544EE5D76F579992D9522E9B238955":{n:"Picnic (1983) (Carrere Video) (PAL)",p:1}, "D3423D7600879174C038F53E5EBBF9D3":{n:"Piece o' Cake (1982) (U.S. Games)",p:1}, "8E4FA8C6AD8D8DCE0DB8C991C166CDAA":{n:"Pigs in Space (1983) (Atari)"}, "95E1D834C57CDD525DD0BD6048A57F7B":{n:"Pigs in Space (1983) (Atari) (PAL)"}, "CC3D942C6958BD16B1C602623F59E6E1":{n:"Pigs in Space (1983) (Atari) (PAL) [a]"}, "F04EE80011D95798006378643650AAA7":{n:"Pigs in Space (1983) (Atari) (Prototype)"}, "E3533684A7EF930A7FBD0C4DD8EC4847":{n:"Pimball (1983) (CCE)"}, "DBC7485AD5814D466DE780A3E7ED3B46":{n:"Pink Floyd (Kyle Pittman) (PD)"}, "69E79B1352B9EE1754BBE63B4A7062C3":{n:"Pink Floyd - The Wall (2003) (Barry Laws Jr.) (Hack)"}, "798CC114F1623C14085868CD3494FE8E":{n:"Pins Revenge (Atari Freak 1)"}, "F73D2D0EFF548E8FC66996F27ACF2B4B":{n:"Pitfall (1983) (CCE)",l:"PITFALL!",lc:"#ececec #272"}, "D20E61C86ED729780FECA162166912CA":{n:"Pitfall (1984) (Supergame)",l:"PITFALL!",lc:"#ececec #272"}, "2D405DA70AF82B20A6B3ECC3D1D2C4EC":{n:"Pitfall (Genus)",l:"PITFALL!",lc:"#ececec #272"}, "5A272012A62BECABCD52920348C7C60B":{n:"Pitfall (Star Game)",l:"PITFALL!",lc:"#ececec #272"}, "39A6A5A2E1F6297CCEAA48BB03AF02E9":{n:"Pitfall 2 Plus (Hack)"}, "7B79BEB378D1B4471DEF90CECCF413DE":{n:"Pitfall Cupcake (Hack)"}, "6D842C96D5A01967BE9680080DD5BE54":{n:"Pitfall II (1983) (Activision)"}, "E34C236630C945089FCDEF088C4B6E06":{n:"Pitfall II (1983) (Activision) (PAL)"}, "448C2A175AFC8DF174D6FF4CCE12C794":{n:"Pitfall II (1983) (Activision) [a2]"}, "490EED07D4691B27F473953FBEA6541A":{n:"Pitfall II (1983) (Activision) [a]"}, "268F46038E29301568FA9E443E16E960":{n:"Pitfall Unlimited (Atarius Maximus) (Hack)"}, "AAD91BE0BF78D33D29758876D999848A":{n:"Pitfall! (1981) (Activision) (Prototype)",l:"PITFALL!",lc:"#ececec #272"}, "3E90CF23106F2E08B2781E41299DE556":{n:"Pitfall! (1982) (Activision)",l:"PITFALL!",lc:"#ececec #272"}, "6FD7C7057EEAB273B29C7AAFC7429A96":{n:"Pitfall! (1982) (Activision) (16K)",l:"PITFALL!",lc:"#ececec #272"}, "98EC0FA4199B9C01F7B8FA3732E43372":{n:"Pitfall! (1982) (Activision) (8K)",l:"PITFALL!",lc:"#ececec #272"}, "791BC8ACEB6B0F4D9990D6062B30ADFA":{n:"Pitfall! (1982) (Activision) (PAL)",l:"PITFALL!",lc:"#ececec #272"}, "1782929E1C214B70FB6884F77C207A55":{n:"Pitfall! (1982) (Activision) (Prototype)",l:"PITFALL!",lc:"#ececec #272"}, "2B430C00DC79E495762AC59B2F9B4FCD":{n:"Pitfall! (1982) (Activision) (Prototype)",l:"PITFALL!",lc:"#ececec #272"}, "E42B937C30C617241CA9E01E4510C3F6":{n:"Pitfall! (No Walls Hack)",l:"PITFALL!",lc:"#ececec #272"}, "177504ABD4260C4265E1338955E9FA47":{n:"Pitfall! (Steroids Hack)"}, "55EF6AB2321CA0C3D369E63D59C059C8":{n:"Pitfall! (Unknown) (PAL)",l:"PITFALL!",lc:"#ececec #272"}, "5BBAB3F3E4B47E3E23F9820765DBB45C":{n:"Pitfall! (says 1985) [h1]",l:"PITFALL!",lc:"#ececec #272"}, "82EFE7984783E23A7C55266A5125C68E":{n:"Pizza Chef (1983) (CCE)"}, "D9FBF1113114FB3A3C97550A0689F10F":{n:"Pizza Chef (1983) (ZiMAG) (Prototype)"}, "2F77F015FC880B05F28E84156F989A0C":{n:"Plane Demo (Gonzalo) (PD)"}, "AE10527840A1AC24DE43730645ED508D":{n:"Planet Invaders (Charles Morgan) (Hack)"}, "BB745C893999B0EFC96EA9029E3C62CA":{n:"Planet Patrol (1982) (Play Video) (PAL)"}, "043F165F384FBEA3EA89393597951512":{n:"Planet Patrol (1982) (Spectravision)"}, "69FAC82CD2312DD9CE5D90E22E2F070A":{n:"Planet Patrol (1982) (Spectravision) (PAL)"}, "D6ACFF6AED0F04690FE4024D58FF4CE3":{n:"Planet Patrol (1982) (Spectravision) (PAL) [different spaceship]"}, "79004F84BDEEE78D142E445057883169":{n:"Planet Patrol (1983) (CCE)"}, "1C3F3133A3E5B023C77ECBA94FD65995":{n:"Planet Patrol (1983) (CCE) [a]"}, "AAFC79FFC32C4C9B2D73C8ADA7602CFE":{n:"Planet Patrol (Unknown) (PAL)"}, "9EFB4E1A15A6CDD286E4BCD7CD94B7B8":{n:"Planet of the Apes (1983) (20th Century Fox) (Prototype)"}, "DA4E3396AA2DB3BD667F83A1CB9E4A36":{n:"Plaque Attack (1983) (Activision)"}, "32244E55CE6EC6BFBD763F33384BDC2E":{n:"Plaque Attack (1983) (Activision) (16K)"}, "2ABA6A1B01A5859E96D6A66D2286772F":{n:"Plaque Attack (1983) (Activision) (8K)"}, "7CED6709F091E79A2AB9575D3516A4AC":{n:"Plaque Attack (1983) (Activision) (PAL)"}, "B64426E787F04FF23EE629182C168603":{n:"Plaque Attack (1983) (Dynacom)"}, "DE24F700FD28D5B8381DE13ABD091DB9":{n:"Plaque Attack (CCE)"}, "8B8789C6669A4CEE86C579A65332F852":{n:"Plaque Attack (Digivision)"}, "3ECCF9F363F5C5DE0C8B174A535DC83B":{n:"Plaque Attack (Unknown) (PAL)"}, "6A76D5F0ED721639474AA9BBDE69EBF0":{n:"Play Demo (PD)",c:1}, "5C3A6D27C026F59A96B7AF91E8B1BF26":{n:"PlayAround Demo (PlayAround) (1982)"}, "103E9D616328969F5D7B4E0A381B25D5":{n:"Playfield Illustration and Logo Demo (2001) (Jake Patterson) (PD)"}, "CBA56E939252B05DF7B7DE87307D12CA":{n:"Playfield Text Demo (2001) (Roger Williams)"}, "8BBFD951C89CC09C148BFABDEFA08BEC":{n:"Pleiades (1983) (UA Limited) (Prototype)",c:1}, "9AFDFE1CFF7F37F1C971FE3F0C900606":{n:"Plug Attack (Funvision)"}, "7C4A499D343FCA0CEF2D59DD16AF621A":{n:"Poker Card Demo (PD)"}, "D74A81FCD89C5CF0BD4C88EB207EBD62":{n:"Poker Squares (V0.00a) (2001) (B. Watson)"}, "12D7E0D6B187889F8D150BF7034D1DB2":{n:"Poker Squares (V0.0e) (2001) (B. Watson)"}, "E879B7093AC4CFAD74C88D636CA97D00":{n:"Poker Squares (V0.0f) (2001) (B. Watson)"}, "6E7ED74082F39AD4166C823765A59909":{n:"Poker Squares (V0.14) (2001) (B. Watson)"}, "78297DB7F416AF3052DD793B53FF014E":{n:"Poker Squares (V0.17) (2001) (B. Watson)"}, "54785FA29E28AAE6038929BA29D33D38":{n:"Poker Squares (V0.19) (2001) (B. Watson)"}, "675AE9C23FA1AAE376CEA86CAD96F9A5":{n:"Poker Squares (V0.25) (2001) (B. Watson)"}, "CCCFE9E9A11B1DAD04BEBA46EEFB7351":{n:"Poker Squares (V0.25) (PAL) (2001) (B. Watson)"}, "8C136E97C0A4AF66DA4A249561ED17DB":{n:"Poker Squares (V0.27) (2001) (B. Watson)"}, "08D60A58A691C7F690162850302DC0E1":{n:"Poker Squares (V0.27) (PAL) (2001) (B. Watson)"}, "EA832E2CB6AAE6F525F07452C381FA48":{n:"Polar to Cartesian and VV (2001) (Roger Williams)"}, "8953BC11352D794431D3303E31D3B892":{n:"Polaris (02-17-1983) (Tigervision) (Prototype) (4K)"}, "87BEA777A34278D29B3B6029833C5422":{n:"Polaris (1983) (Thomas Jentzsch)"}, "44F71E70B89DCC7CF39DFD622CFB9A27":{n:"Polaris (1983) (Tigervision)"}, "203049F4D8290BB4521CC4402415E737":{n:"Polaris (1983) (Tigervision) (PAL)"}, "9048CCB7E0802CD8FA5BFC2609F292D8":{n:"Polaris (1983) (Tigervision) (Prototype)"}, "7F0209CFCC3D181715463F4D6451CECF":{n:"Pole Position (05-15-1983) (Atari) (Prototype)"}, "A4FF39D513B993159911EFE01AC12EBA":{n:"Pole Position (1983) (Atari)"}, "B56264F738B2EB2C8F7CF5A2A75E5FDC":{n:"Pole Position (1983) (Atari) (PAL)"}, "25B52BF8DD215BCBD59C9ABDB55C44F8":{n:"Pole Position (1983) (Atari) (PAL) [a]"}, "5F39353F7C6925779B0169A87FF86F1E":{n:"Pole Position (1983) (Atari) [a]"}, "3225676F5C0C577AECCFAA7E6BEDD765":{n:"Pole Position (1983) (CCE)"}, "5DA8FD0B5ED33A360BFF37F8B5D0CD58":{n:"Pole Position (Tron)"}, "EE28424AF389A7F3672182009472500C":{n:"Polo (1978) (Atari) (Prototype)"}, "14B1E30982962C72F426E2E763EB4274":{n:"Polo (1978) (Atari) (Prototype) (4K)"}, "A83B070B485CF1FB4D5A48DA153FDF1A":{n:"Pompeii (1983) (Apollo) (Prototype)"}, "668DC528B7EA9345140F4FCFBECF7066":{n:"Pooyan (1983) (Gakken) (PAL)"}, "4799A40B6E889370B7EE55C17BA65141":{n:"Pooyan (1983) (Konami)"}, "F70E3F3BB2D19EC2AAEC8F78DC43744F":{n:"Pooyan (Jone Yuan) (Hack)"}, "89AFFF4A10807093C105740C73E9B544":{n:"Pooyan (Unknown) (PAL)"}, "C7F13EF38F61EE2367ADA94FDCC6D206":{n:"Popeye (1983) (Parker Bros)",c:1}, "E9CB18770A41A16DE63B124C1E8BD493":{n:"Popeye (1983) (Parker Bros) (PAL)",c:1}, "F93D7FEE92717E161E6763A88A293FFA":{n:"Porky's (1983) (20th Century Fox)"}, "4A5FDDF89801336637AC8E57A7C9A881":{n:"Power Play Arcade Video Game Album IV (1984) (Amiga) (Prototype)"}, "BBF8C7C9ED280151934AABE138E41BA7":{n:"Power Play Arcade Video Game Album V (1984) (Amiga) (Prototype)"}, "97D079315C09796FF6D95A06E4B70171":{n:"Pressure Cooker (1983) (Activision)"}, "525EA747D746F3E80E3027720E1FA7AC":{n:"Pressure Cooker (1983) (Activision) (PAL)"}, "D57913088E0C49AC3A716BF9837B284F":{n:"Pressure Cooker (1983) (Activision) (PAL) [a]"}, "027A59A575B78860AED780B2AE7D001D":{n:"Pressure Cooker (CCE)"}, "DE1A636D098349BE11BBC2D090F4E9CF":{n:"Pressure Gauge (Hozer Video Games)"}, "6A03C28D505BAB710BF20B954E14D521":{n:"Pressure Gauge 2 Beta (Hozer Video Games)"}, "EF3A4F64B6494BA770862768CAF04B86":{n:"Private Eye (1983) (Activision)"}, "1266B3FD632C981F3EF9BDBF9F86CE9A":{n:"Private Eye (1983) (Activision) (PAL)"}, "F9CEF637EA8E905A10E324E582DD39C2":{n:"Private Eye (CCE)"}, "22F6B40FC82110D68E50A1208AE0BB97":{n:"Purple Bar Demo (PD)"}, "9CA2DEB61318EBA4FB784D4BF7441D8B":{n:"Purple Bar Demo 2 (PD)"}, "6E19428387686A77D8C8D2F731CB09E0":{n:"Purple Cross Demo (PD)"}, "CFF1E9170BDBC29859B815203EDF18FA":{n:"Push (V0.01) (1998) (AD)",c:1}, "B7E459D5416EEB196AAA8E092DB14463":{n:"Push (V0.02) (1998) (AD)"}, "C482F8EEBD45E0B8D479D9B71DD72BB8":{n:"Push (V0.03) (1998) (AD)",c:1}, "BEFCE0DE2012B24FD6CB8B53C17C8271":{n:"Push (V0.03) (No Illegal Opcodes) (1998) (AD)"}, "0375F589F7DA06D2D2BE532E0D4D4B94":{n:"Push (V0.04) (2001) (AD)"}, "96F806FC62005205D851E758D050DFCA":{n:"Push (V0.05) (2001) (AD)"}, "9D2F05D0FE8B2DFCF770B02EDA066FC1":{n:"Push (V0.06) (2001) (AD)"}, "9F93734C68F6479EB022CAB40814142E":{n:"Push (V0.07) (2001) (AD)"}, "78963290052FD17C6C7998305AB3A6A0":{n:"Push (V0.08) (2001) (AD)"}, "679D30C7886B283CBE1DB4E7DBE5F2A6":{n:"Puzzle (Colin Hughes) (PD)"}, "3FF5165378213DAB531FFA4F1A41AE45":{n:"Pygmy (1983) (Quelle) (PAL)"}, "6FC0176CCF53D7BCE249AEB56D59D414":{n:"Pyramid War (Rainbow Vision) (PAL)"}, "37FD7FA52D358F66984948999F1213C5":{n:"Pyramid War (Rainbow Vision) (PAL) [a2]"}, "8B40A9CA1CFCD14822E2547EAA9DF5C1":{n:"Q-bert (1983) (Parker Bros) (PAL)"}, "1EDE4F365CE1386D58F121B15A775E24":{n:"Q-bert (1983) (Parker Bros) (PAL) [a]"}, "484B0076816A104875E00467D431C2D2":{n:"Q-bert (1987) (Atari)"}, "EB6D6E22A16F30687ADE526D7A6F05C5":{n:"Q-bert (1987) (Atari) (PAL)"}, "A91D0858A52DE3A2E6468437212D93E8":{n:"Q-bert (208 in 1) (Unknown) (PAL)"}, "517592E6E0C71731019C0CEBC2CE044F":{n:"Q-bert's Qubes (1984) (Parker Bros)"}, "B15026B43C6758609667468434766DD8":{n:"Qb (0.06) (Retroactive)",c:1}, "6803FA7C2C094B428B859A58DC1DD06A":{n:"Qb (0.11) (Retroactive)",c:1}, "5A5390F91437AF9951A5F8455B61CD43":{n:"Qb (0.11) (Retroactive) (PAL)",c:1}, "376944889DCFA96C73D3079F308E3D32":{n:"Qb (0.11) (Retroactive) (Stella)",c:1}, "292A0BB975B2587F9AC784C960E1B453":{n:"Qb (05-02-2001) (AD)",c:1}, "D0E9BEB2347595C6C7D158E9D83D2DA8":{n:"Qb (2.00) (Retroactive)",c:1}, "C866C995C0D2CA7D017FEF0FC0C2E268":{n:"Qb (2.00) (Retroactive) (PAL)",c:1}, "F33F1D0F7819C74148DACB48CBF1C597":{n:"Qb (2.00) (Retroactive) (Stella)",c:1}, "2E0AED5BB619EDCEFA3FAFB4FBE7C551":{n:"Qb (2.06) (Retroactive) (NTSC)",c:1}, "05EB4347F0EC8F4783983CA35FFD8D1B":{n:"Qb (2.06) (Retroactive) (PAL)",c:1}, "E800E4AEC7C6C54C9CF3DB0D1D030058":{n:"Qb (2.06) (Retroactive) (Stella)",c:1}, "3A51A6860848E36E6D06FFE01B71FB13":{n:"Qb (2.07) (Retroactive) (NTSC)",c:1}, "FAE0B86934A7C5A362281DFFEBDB43A0":{n:"Qb (2.07) (Retroactive) (PAL)",c:1}, "CEA9F72036DC6F7AF5EFF52459066290":{n:"Qb (2.07) (Retroactive) (Stella)",c:1}, "67BD3D4DC5AC6A42A99950B4245BDC81":{n:"Qb (2.11) (Retroactive)",c:1}, "283DEE88F295834C4C077D788F151125":{n:"Qb (2.11) (Retroactive) (PAL)",c:1}, "2808DC745FF4321DC5C8122ABEF6711F":{n:"Qb (2.11) (Retroactive) (Stella)",c:1}, "35163B56F4A692A232AE96AD3E23310F":{n:"Qb (2.12) (Retroactive)",c:1}, "B3017E397F74EFD53CAF8FAE0A38E3FE":{n:"Qb (2.12) (Retroactive) (PAL)",c:1}, "6E5D5BA193D2540AEC2E847AAFB2A5FB":{n:"Qb (2.14) (Retroactive) (NTSC)",c:1}, "4F634893D54E9CABE106E0EC0B7BDCDF":{n:"Qb (2.14) (Retroactive) (PAL)",c:1}, "52E1954DC01454C03A336B30C390FB8D":{n:"Qb (2.14) (Retroactive) (Stella)",c:1}, "AC53B83E1B57A601EEAE9D3CE1B4A458":{n:"Qb (2.15) (Retroactive) (NTSC)",c:1}, "9281ECCD7F6EF4B3EBDCFD2204C9763A":{n:"Qb (2.15) (Retroactive) (PAL)",c:1}, "34E37EAFFC0D34E05E40ED883F848B40":{n:"Qb (2.15) (Retroactive) (Stella)",c:1}, "2D69A5F23784F1C2230143292A073B53":{n:"Qb (Fixed background animation) (2001) (AD)",c:1}, "17512D0C38F448712F49F36F9D185C4E":{n:"Qb (Release Candidate #1) (Retroactive)",c:1}, "687C23224E26F81C56E431C24FAEA36D":{n:"Qb (Simple Background Animation) (2001) (AD)",c:1}, "3F01BD6D059396F495A4CDE7DE0AB180":{n:"Qb (Special Edition) (NTSC) (Retroactive)",c:1}, "F49A34F1FDD7DC147CBF96CE2CE71B76":{n:"Qb (Special Edition) (PAL) (Retroactive)",c:1}, "E01E00504E6D4B88FA743C0BBE8A96E5":{n:"Qb (Special Edition, some bugfixes) (Retroactive)",c:1}, "D787EC6785B0CCFBD844C7866DB9667D":{n:"Qb (V0.04) (2001) (Retroactive)",c:1}, "3C4A6F613CA8BA27CE9E43C6C92A3128":{n:"Qb (V0.04) (Non-Lax Version) (2001) (Retroactive)",c:1}, "CF0C593C563C84FDAF0F741ADB367445":{n:"Qb (V0.05) (2001) (Retroactive)",c:1}, "35FA32256982774A4F134C3347882DFF":{n:"Qb (V0.05) (Macintosh) (2001) (Retroactive)",c:1}, "8712CCEEC5644AACC2C21203D9EBE2EC":{n:"Qb (V0.10) (NTSC) (2001) (Retroactive)",c:1}, "4233EB824C2B4811ABEF9B6D00355AE9":{n:"Qb (V0.10) (PAL) (2001) (Retroactive)",c:1}, "D010E3DFE7366E47561C088079A59439":{n:"Qb (V0.10) (Stella) (2001) (Retroactive)",c:1}, "0906C6E0E4BDA9C10CFA4C5FC64D2F4B":{n:"Qb (V0.12) (NTSC) (2001) (Retroactive)",c:1}, "AE682886058CD6981C4B8E93E7B019CF":{n:"Qb (V0.12) (PAL) (2001) (Retroactive)",c:1}, "CDC1A5C61D7488EADC9ABA36166B253D":{n:"Qb (V0.12) (Stella) (2001) (Retroactive)",c:1}, "8B504B417C8626167A7E02F44229F0E7":{n:"Qb (V1.00) (NTSC) (2001) (Retroactive)",c:1}, "8FFFC8F15BB2E6D24E211884A5479AA5":{n:"Qb (V1.00) (PAL) (2001) (Retroactive)",c:1}, "7BC4FD254EC8C0A25A13F02FD3F762FF":{n:"Qb (V1.00) (Stella) (2001) (Retroactive)",c:1}, "8CCAA442D26B09139685F5B22BF189C4":{n:"Qb (V1.01) (NTSC) (2001) (Retroactive)",c:1}, "ABB740BEA0A6842831B4F53112FB8145":{n:"Qb (V1.01) (PAL) (2001) (Retroactive)",c:1}, "AE0D4F3396CB49DE0FABDFF03CB2756F":{n:"Qb (V2.02) (PAL) (2001) (Retroactive)",c:1}, "C504A71C411A601D1FC3173369CFDCA4":{n:"Qb (V2.02) (Stella) (2001) (Retroactive)",c:1}, "693137592A7F5CCC9BAAE2D1041B7A85":{n:"Qb (V2.02) (Stella) (2001) (Retroactive) [a1]",c:1}, "98CCD15345B1AEE6CAF51E05955F0261":{n:"Qb (V2.03) (NTSC) (2001) (Retroactive)",c:1}, "4C030667D07D1438F0E5C458A90978D8":{n:"Qb (V2.03) (PAL) (2001) (Retroactive)",c:1}, "CE64812EB83C95723B04FB56D816910B":{n:"Qb (V2.04) (NTSC) (2001) (Retroactive)",c:1}, "EB9712E423B57F0B07CCD315BB9ABF61":{n:"Qb (V2.04) (PAL) (2001) (Retroactive)",c:1}, "4DD6C7AB9EF77F2B4950D8FC7CD42EE1":{n:"Qb (V2.04) (Stella) (2001) (Retroactive)",c:1}, "659A20019DE4A23C748EC2292EA5F221":{n:"Qb (V2.05) (NTSC) (2001) (Retroactive)",c:1}, "C92CFA54B5D022637FDCBDC1EF640D82":{n:"Qb (V2.05) (PAL) (2001) (Retroactive)",c:1}, "DCBA0E33AA4AED67630A4B292386F405":{n:"Qb (V2.08) (Half Speed Version) (NTSC) (2001) (Retroactive)",c:1}, "57A66B6DB7EFC5DF17B0B0F2F2C2F078":{n:"Qb (V2.08) (NTSC) (2001) (Retroactive)",c:1}, "876A953DAAE0E946620CF05ED41989F4":{n:"Qb (V2.08) (PAL) (2001) (Retroactive)",c:1}, "318046AE3711C05FD16E479B298E5FCC":{n:"Qb (V2.08) (Stella) (2001) (Retroactive)",c:1}, "E2389C0BE5B5B84E0D3CA36EC7E67514":{n:"Qb (V2.09) (NTSC) (2001) (Retroactive)",c:1}, "008543AE43497AF015E9428A5E3E874E":{n:"Qb (V2.09) (PAL) (2001) (Retroactive)",c:1}, "67CE6CDF788D324935FD317D064ED842":{n:"Qb (V2.09) (Stella) (2001) (Retroactive)",c:1}, "94E4C9B924286038527F49CDC20FDA69":{n:"Qb (V2.12) (Stella) (2001) (Retroactive)",c:1}, "4FAE08027365D31C558E400B687ADF21":{n:"Qb (V2.17) (NTSC) (2001) (Retroactive)",c:1}, "8388D6FE59C38C0B3A6AB2C58420036A":{n:"Quadrun (12-06-1982) (Atari) (Prototype)"}, "024365007A87F213CBE8EF5F2E8E1333":{n:"Quadrun (1983) (Atari)"}, "392D34C0498075DD58DF0CE7CD491EA2":{n:"Quadrun (1983) (Atari) (Prototype)"}, "955C408265AD6994F61F9B66657BBAE9":{n:"Quadrun (Video Conversion) (Fabrizio Zavagli)"}, "152C253478B009C275E18CD731B48561":{n:"Quest (11-10-2002) (Chris Larkin)"}, "A0675883F9B09A3595DDD66A6F5D3498":{n:"Quest for Quintana Roo (1989) (Telegames)"}, "F736864442164B29235E8872013180CD":{n:"Quest for Quintana Roo (1989) (Telegames) (PAL)"}, "7EBA20C2291A982214CC7CBE8D0B47CD":{n:"Quick Step! (1983) (Imagic)"}, "E72EE2D6E501F07EC5E8A0EFBE520BEE":{n:"Quick Step! (1983) (Imagic) (PAL)"}, "84290E333FF7567C2380F179430083B8":{n:"Quick Step! (1983) (Imagic) (PAL) [a]"}, "7836794B79E8060C2B8326A2DB74EEF0":{n:"RIOT RAM Test (26-11-2002) (Dennis Debro)"}, "6CCD8CA17A0E4429B446CDCB66327BF1":{n:"RPG Engine (12-05-2003) (Paul Slocum) (PD)",c:1}, "9C6D65BD3B477AACE0376F705B354D68":{n:"RPG Kernal (18-04-2003) (Paul Slocum) (PD)",c:1}, "0F341D1F4E144E3163D9A5FC5A662B79":{n:"RUN Platform Demo (PD)",c:1}, "2E5B184DA8A27C4D362B5A81F0B4A68F":{n:"Rabbit Transit (08-29-1983) (Atari) (Prototype)"}, "FB4CA865ABC02D66E39651BD9ADE140A":{n:"Rabbit Transit (1983) (Arcadia)"}, "7481F0771BFF13885B2FF2570CF90D7B":{n:"Rabbit Transit (1983) (Arcadia) (PAL)"}, "A779B9FA02C62D00D7C31ED51268F18A":{n:"Rabbit Transit (1983) (Arcadia) [a]"}, "CD399BC422992A361BA932CC50F48B65":{n:"Rabbit Transit (Preview) (1983) (Arcadia)"}, "1A23540D91F87584A04F184304A00648":{n:"Race Demo (PD)"}, "AAB840DB22075AA0F6A6B83A597F8890":{n:"Racing Car (1983) (Home Vision) (PAL)"}, "4DF9D7352A56A458ABB7961BF10ABA4E":{n:"Racing Car (Unknown)"}, "CBCED209DD0575A27212D3EEE6AEE3BC":{n:"Racquetball (1981) (Apollo)",c:1}, "4F7B07EC2BEF5CCFFE06403A142F80DB":{n:"Racquetball (1981) (Apollo) (PAL)",c:1}, "A20D931A8FDDCD6F6116ED21FF5C4832":{n:"Racquetball (1981) (Apollo) [a]",c:1}, "F0D393DBF4164A688B2346770C9BBD12":{n:"Racquetball (Unknown)",c:1}, "97933C9F20873446E4C1F8A4DA21575F":{n:"Racquetball (Unknown) (PAL)",c:1}, "56300ED31FEF018BD96768CCC982F7B4":{n:"Rad Action Pak - Kung-Fu Master, Freeway, Frostbite (1990) (HES) (PAL)"}, "247FA1A29AD90E64069EE13D96FEA6D6":{n:"Radar (1983) (CCE)"}, "74F623833429D35341B7A84BC09793C0":{n:"Radar (Zellers)"}, "BAF4CE885AA281FD31711DA9B9795485":{n:"Radar Lock (1989) (Atari)"}, "04856E3006A4F5F7B4638DA71DAD3D88":{n:"Radar Lock (1989) (Atari) (PAL)"}, "200309C8FBA0F248C13751ED4FC69BAB":{n:"Radial Pong - Version 1 (Jeffry Johnston) (PD)"}, "0F14C03050B35D6B1D8850B07578722D":{n:"Radial Pong - Version 10 (Jeffry Johnston) (PD)"}, "43F33C6DFDEAF5138CE6E6968AD7C5CE":{n:"Radial Pong - Version 11 (Jeffry Johnston) (PD)"}, "32199271DC980EB31A2CC96E10A9E244":{n:"Radial Pong - Version 12 (Jeffry Johnston) (PD)"}, "6337927AD909AA739D6D0044699A916D":{n:"Radial Pong - Version 2 (Jeffry Johnston) (PD)"}, "F1E375D921858467166E53BCEC05803F":{n:"Radial Pong - Version 3 (Jeffry Johnston) (PD)"}, "481F9A742052801CC5F3DEFB41CB638E":{n:"Radial Pong - Version 4 (Jeffry Johnston) (PD)"}, "FD9B321CEE5FBB32C39BA3CA5D9EC7CF":{n:"Radial Pong - Version 5 (Jeffry Johnston) (PD)"}, "64B8E19C767191CCDC97ACC6904C397B":{n:"Radial Pong - Version 6 (Jeffry Johnston) (PD)"}, "2450DFA1DF70D12B60683185775EFED8":{n:"Radial Pong - Version 7 (Jeffry Johnston) (PD)"}, "9F9EE0F60C119C831E80694B6678CA1A":{n:"Radial Pong - Version 8 (Jeffry Johnston) (PD)"}, "05824FCBE615DBCA836D061A140A50E0":{n:"Radial Pong - Version 9 (Jeffry Johnston) (PD)"}, "92A1A605B7AD56D863A56373A866761B":{n:"Raft Rider (1982) (U.S. Games)"}, "438968A26B7CFE14A499F5BBBBF844DB":{n:"Raft Rider (208 in 1) (Unknown) (PAL)"}, "1E750000AF77CC76232F4D040F4AB060":{n:"Raft Rider (Jone Yuan)"}, "025668E36A788E8AF8AC4F1BE7E72043":{n:"Raiders of the Lost Ark (06-14-82) (Atari) (Prototype)"}, "F724D3DD2471ED4CF5F191DBB724B69F":{n:"Raiders of the Lost Ark (1982) (Atari)"}, "1CAFA9F3F9A2FCE4AF6E4B85A2BBD254":{n:"Raiders of the Lost Ark (1982) (Atari) (PAL)"}, "CB96B0CF90AB7777A2F6F05E8AD3F694":{n:"Rainbow Invaders"}, "8F98519A91DBBF4864F135A10050D9ED":{n:"Rainbow Invaders (non-playable demo) (PD)"}, "0B577E63B0C64F9779F315DCA8967587":{n:"Raketen-Angriff (Ariola) (PAL)"}, "7096A198531D3F16A99D518AC0D7519A":{n:"Ram It (1982) (Telesys)"}, "63E42D576800086488679490A833E097":{n:"Ram It (1982) (Telesys) (PAL)"}, "F2F2CB35FDEF063C966C1F5481050EA2":{n:"Ram It (Unknown) (PAL)"}, "9EEB40F04A27EFB1C68BA1D25E606607":{n:"Rambo II (2003) (Kyle Pittman) (Hack)"}, "2EDA6A49A49FCB2B674EA9E160B6A617":{n:"Rambo in Afghanistan (Kyle Pittman) (Hack)"}, "5E1B4629426F4992CF3B2905A696E1A7":{n:"Rampage! (1989) (Activision)"}, "A11099B6EC24E4B00B8795744FB12005":{n:"Rampage! (1989) (Activision) (PAL)"}, "9F8FAD4BADCD7BE61BBD2BCAEEF3C58F":{n:"Reactor (1982) (Parker Bros)",c:1}, "4904A2550759B9B4570E886374F9D092":{n:"Reactor (1982) (Parker Bros) (PAL)",c:1}, "C6DB733E0B108C2580A1D65211F06DBF":{n:"RealSports Baseball (07-09-1982) (Atari) (Prototype)"}, "EB634650C3912132092B7AEE540BBCE3":{n:"RealSports Baseball (1982) (Atari)",c:1}, "20D4457BA22517253FCB62967AF11B37":{n:"RealSports Baseball (1982) (Atari) (Prototype)"}, "8A183B6357987DB5170C5CF9F4A113E5":{n:"RealSports Basketball (1983) (Atari) (Prototype) (PAL)"}, "5524718A19107A04EC3265C93136A7B5":{n:"RealSports Basketball (Thomas Jentzsch)"}, "3177CC5C04C1A4080A927DFA4099482B":{n:"RealSports Boxing (1987) (Atari)"}, "4ABB4C87A4C5F5D0C14EAD2BB36251BE":{n:"RealSports Boxing (1987) (Atari) (PAL)"}, "7AD257833190BC60277C1CA475057051":{n:"RealSports Football (1982) (Atari)",c:1}, "277FA4B9A6BB7A8DCEA2C5F38A4C25F0":{n:"RealSports Football (1982) (Atari) (Prototype)",c:1}, "08F853E8E01E711919E734D85349220D":{n:"RealSports Soccer (1983) (Atari)"}, "B9336ED6D94A5CC81A16483B0A946A73":{n:"RealSports Soccer (1983) (Atari) (PAL)",c:1}, "6272F348A9A7F2D500A4006AA93E0D08":{n:"RealSports Soccer (1983) (Atari) (PAL) [a]",c:1}, "6706A00F9635508CFEDA20639156E66E":{n:"RealSports Soccer (1983) (Atari) (Prototype)"}, "F7856E324BC56F45B9C8E6FF062EC033":{n:"RealSports Soccer (1983) (Atari) [no opening tune]",c:1}, "C5DD8399257D8862F3952BE75C23E0EB":{n:"RealSports Tennis (1982) (Atari) (Prototype)"}, "DAC5C0FE74531F077C105B396874A9F1":{n:"RealSports Tennis (1983) (Atari)"}, "4E66C8E7C670532569C70D205F615DAD":{n:"RealSports Tennis (1983) (Atari) (PAL)"}, "13AA1F9AC4249947E4AF61319D9A08F2":{n:"RealSports Tennis (1983) (Atari) (PAL) [a1]"}, "C7EAB66576696E11E3C11FFFF92E13CC":{n:"RealSports Tennis (1983) (Atari) (PAL) [a2]"}, "435FD469F088468C4D66BE6B5204D887":{n:"RealSports Tennis (1983) (Atari) (PAL) [a]"}, "AED0B7BD64CC384F85FDEA33E28DAF3B":{n:"RealSports Volleyball (1982) (Atari)"}, "4CA0959F846D2BEADA18ECF29EFE137E":{n:"RealSports Volleyball (1982) (Atari) (PAL)"}, "A8D4A9500B18B0A067A1F272F869E094":{n:"Red And White Checkerboard Demo (PD)"}, "13DFB095E519A555A5B60B7D9D7169F9":{n:"Red Line Demo (PD)"}, "874C76726F68C166FCFAC48CE78EEF95":{n:"Red Pong Number 2 Demo (PD)",c:1}, "79B649FB812C50B4347D12E7DDBB8400":{n:"Red Pong Number 2 Demo 2 (PD)",c:1}, "DD1422FFD538E2E33B339EBEEF4F259D":{n:"Red Vs. Blue (1981) (Atari) (Prototype)"}, "EB9F8B84C193D9D93A58FCA112AA39ED":{n:"Register Twiddler Demo (PD)"}, "7450AE4E10BA8380C55B259D7C2B13E8":{n:"Register Twiddler Demo 2 (PD)"}, "8A9D874A38608964F33EC0C35CAB618D":{n:"Rescue Bira Bira (Chris Cracknell)",c:1}, "60A61DA9B2F43DD7E13A5093EC41A53D":{n:"Rescue Terra I (1982) (VentureVision)"}, "42249EC8043A9A0203DDE0B5BB46D8C4":{n:"Resgate Espacial (CCE)",c:1}, "5E1CD11A6D41FC15CF4792257400A31E":{n:"Return of Mario Bros (Philip R. Frey) (Hack)"}, "0B01909BA84512FDAF224D3C3FD0CF8D":{n:"Revenge of the Apes (Hack)"}, "96BCB3D97CE4FF7586326D183AC338A2":{n:"Revenge of the Apes (Hack) [h2]"}, "4F64D6D0694D9B7A1ED7B0CB0B83E759":{n:"Revenge of the Beefsteak Tomatoes (1982) (20th Century Fox)"}, "6468D744BE9984F2A39CA9285443A2B2":{n:"Reversi (32 in 1) (1988) (Atari) (PAL)"}, "A995B6CBDB1F0433ABC74050808590E6":{n:"Riddle of the Sphinx (1982) (Imagic)"}, "083E7CAE41A874B2F9B61736C37D2FFE":{n:"Riddle of the Sphinx (1982) (Imagic) (PAL)"}, "3D2652CBEA462A886A41791DD7C8D073":{n:"Ritorno dei frattelli di Mario (Mario Bros Hack)"}, "31512CDFADFD82BFB6F196E3B0FD83CD":{n:"River Patrol (1984) (Tigervision)"}, "393948436D1F4CC3192410BB918F9724":{n:"River Raid (1982) (Activision)",l:"RIVER RAID",lc:"#ececec #833"}, "291CC37604BC899E8E065C30153FC4B9":{n:"River Raid (1982) (Activision) (16K)",l:"RIVER RAID"}, "BCCB4E2CFAD5EFC93F6D55DC992118CE":{n:"River Raid (1982) (Activision) (8K)",l:"RIVER RAID"}, "927D422D6335018DA469A9A07CD80390":{n:"River Raid (1982) (Activision) (PAL)",l:"RIVER RAID"}, "33ED6DFAC4B9EA2F81F778CEDDBB4A75":{n:"River Raid (1982) (SpkSoft) [t1]",l:"RIVER RAID"}, "59F596285D174233C84597DEE6F34F1F":{n:"River Raid (1983) (CCE)",l:"RIVER RAID"}, "39D36366AE7E6DFD53393FB9EBAB02A0":{n:"River Raid (1983) (CCE) [a]",l:"RIVER RAID"}, "DA5096000DB5FDAA8D02DB57D9367998":{n:"River Raid (1983) (Digitel)",l:"RIVER RAID"}, "01B09872DCD9556427761F0ED64AA42A":{n:"River Raid (1984) (Galaga Games)",l:"RIVER RAID"}, "FADB89F9B23BEB4D43A7895C532757E2":{n:"River Raid (1984) (Galaga Games) (PAL)",l:"RIVER RAID"}, "8C8B15B3259E60757987ED13CDD74D41":{n:"River Raid (1984) (Supergame)",l:"RIVER RAID"}, "B1C14B5AC896400CC91C8E5DD67ACB59":{n:"River Raid (208 in 1) (Unknown) (PAL) (Hack)"}, "A539B9FD1BA57E46442B3E9351E6383B":{n:"River Raid (208 in 1) (Unknown) (PAL) (Hack) [a]"}, "8C941FA32C7718A10061D8C328909577":{n:"River Raid (Digivision)",l:"RIVER RAID"}, "A94528AE05DD051894E945D4D2349B3B":{n:"River Raid (Genus)",l:"RIVER RAID"}, "CD4423BD9F0763409BAE9111F888F7C2":{n:"River Raid (Jone Yuan)",l:"RIVER RAID"}, "C29D17EEF6B0784DB4586C12CB5FD454":{n:"River Raid (Jone Yuan) (Hack)"}, "39FE316952134B1277B6A81AF8E05776":{n:"River Raid (Robby)",l:"RIVER RAID"}, "EDF69B123E06EAF8663CC78D8AEBA06E":{n:"River Raid (SpkSoft 98) [h1]",l:"RIVER RAID"}, "DD92D6AD50976F881D86B52D38616118":{n:"River Raid (SpkSoft) [h1]",l:"RIVER RAID"}, "D5E5B3EC074FFF8976017EF121D26129":{n:"River Raid (Star Game)",l:"RIVER RAID"}, "1E89F722494608D6EA15A00D99F81337":{n:"River Raid (Unknown) (PAL)",l:"RIVER RAID"}, "90F502CBF4438A95F69F848CEF36EB64":{n:"River Raid II (1985) (Digitel)"}, "AB56F1B2542A05BEBC4FBCCFC4803A38":{n:"River Raid II (1988) (Activision)"}, "B049FC8AC50BE7C2F28418817979C637":{n:"River Raid II (1988) (Activision) (PAL)"}, "DEB39482E77F984D4CE73BE9FD8ADABD":{n:"River Raid II (1988) (Activision) [a]"}, "F2D4D6187903CAC2D5EA8ED90DAD120D":{n:"River Raid II (Digimax)"}, "D5F965C159E26A1FB49A22A47FBD1DD0":{n:"River Raid II (Supergame)"}, "FBB4F3DEBF48DC961B559384467F2057":{n:"River Raid III (1985) (Digitel)"}, "4E86866D9CDE738D1630E2E35D7288CE":{n:"River Raid III (Supergame)"}, "304512528A5530A9361E8A231ED9A6DE":{n:"River Raid Plus (Thomas Jentzsch) (Hack)"}, "C74BFD02C7F1877BBE712C1DA5C4C194":{n:"River Raid Tanks (Thomas Jentzsch) (Hack)"}, "322B29E84455AA41E7CC9AF463BFFA89":{n:"Road Runner (06-25-1984) (Atari) (Prototype)"}, "CE5CC62608BE2CD3ED8ABD844EFB8919":{n:"Road Runner (1989) (Atari)"}, "C3A9550F6345F4C25B372C42DC865703":{n:"Road Runner (1989) (Atari) (PAL)"}, "7D3CDDE63B16FA637C4484E716839C94":{n:"Road Runner (CCE)"}, "0F8043715D66A4BBED394EF801D99862":{n:"Robin Hood (1983) (Quelle) (PAL)"}, "72A46E0C21F825518B7261C267AB886E":{n:"Robin Hood (1983) (Xonox)"}, "DD7598B8BCB81590428900F71B720EFB":{n:"Robin Hood (1983) (Xonox) (PAL)"}, "DB76F7A0819659D9E585F2CDDE9175C7":{n:"Robin Hood (1983) (Xonox) (PAL) [a]"}, "3E1682DDAEC486D8B6B90B527AAA0FC4":{n:"Robot City (V0.12) (TJ)"}, "F954381F9E0F2009D1AC40DEDD777B1A":{n:"Robot City (V0.18) (01-09-2002) (TJ)"}, "97CD63C483FE3C68B7CE939AB8F7A318":{n:"Robot City (V0.21) (15-09-2002) (TJ)"}, "D82675CE67CAF16AFE5ED6B6FAC8AA37":{n:"Robot City (V0.23) (13-11-2002) (TJ)"}, "82337E5FE0F418CA9484CA851DFC226A":{n:"Robot City (V1.0) (Alpha) (TJ)"}, "4251B4557EA6953E88AFB22A3A868724":{n:"Robot City (V1.1) (TJ)"}, "913D5D959B5021F879033C89797BAB5E":{n:"Robot Player Graphic (1996) (J.V. Matthews) (PD)"}, "4F618C2429138E0280969193ED6C107E":{n:"Robot Tank (1983) (Activision)"}, "F687EC4B69611A7F78BD69B8A567937A":{n:"Robot Tank (1983) (Activision) (PAL)"}, "FBB0151EA2108E33B2DBAAE14A1831DD":{n:"Robot Tank TV (Thomas Jentzsch) (Hack)"}, "568371FBAE6F5E5B936AF80031CD8888":{n:"Robotfindskitten2600 (26-04-2003) (Jeremy Penner)"}, "39790A2E9030751D7DB414E13F1B6960":{n:"Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a1]"}, "D100B11BE34A1E5B7832B1B53F711497":{n:"Robotfindskitten2600 (26-04-2003) (Jeremy Penner) [a2]"}, "0173675D40A8D975763EE493377CA87D":{n:"Roc 'n Rope (1984) (CBS Electronics) (PAL)"}, "65BD29E8AB1B847309775B0DE6B2E4FE":{n:"Roc 'n Rope (1984) (Coleco)"}, "D97FD5E6E1DAACD909559A71F189F14B":{n:"Rocky & Bullwinkle (04-20-1983) (M Network) (Prototype)"}, "A89A3E0547D6887279C34ABA4B17A560":{n:"Rocky & Bullwinkle (1983) (Mattel) (Prototype)"}, "DB80D8EF9087AF4764236F7B5649FA12":{n:"Rocky & Bullwinkle (1983) (Mattel) (Prototype) (4K)"}, "2F16663B01591539624D0EF52934A17D":{n:"Rocky and Bullwinkle"}, "3F96EB711928A6FAC667C04ECD41F59F":{n:"Rodeo Champ (4 Game in One Dark Green) (1983) (BitCorp) (PAL)"}, "67931B0D37DC99AF250DD06F1C095E8D":{n:"Room of Doom (1982) (CommaVid)",c:1}, "685E9668DC270B6DEEB9CFBFD4D633C3":{n:"Room of Doom (1982) (CommaVid) (PAL)",c:1}, "A936D80083E99D48752AD15C2B5F7C96":{n:"Room of Doom (208 in 1) (Unknown) (PAL)",c:1}, "CBB0EE17C1308148823CC6DA85BFF25C":{n:"Rotating Colors Demo 1 (Junkosoft) (PD)"}, "C1B038CE5CB6D85E956C5509B0E0D0D8":{n:"Rotating Colors Demo 2 (Junkosoft) (PD)"}, "1F2AE0C70A04C980C838C2CDC412CF45":{n:"Rubik's Cube (1984) (Atari)"}, "40B1832177C63EBF81E6C5B61AAFFD3A":{n:"Rubik's Cube 3-D (1982) (Atari) (Prototype)"}, "B6821AC51C4C1DCB283F01BE2F047DC1":{n:"Rubik's Cube 3D Demo (25-11-2002) (TJ)"}, "B731D35E4AC6B3B47EBA5DD0991F452F":{n:"Rubik's Cube 3D Demo (Final) (08-01-2003) (TJ)"}, "6058E40CE79D7434C7F7477B29ABD4A5":{n:"Rubik's Cube Demo (23-12-2002) (CT)"}, "3A35D7F1DC2A33565C8DCA52BAA86BC4":{n:"Rubik's Cube Demo 2 (23-12-2002) (CT)"}, "73B4E8F8B04515D91937510E680214BC":{n:"Rubik's Cube Demo 3 (24-12-2002) (CT)"}, "6847CE70819B74FEBCFD03E99610243B":{n:"Ruby Runner 4A50"}, "E18ABE87035379C56B435BFE8175077B":{n:"Rumble 2600 (Grimlock) (Hack)"}, "B9B4612358A0B2C1B4D66BB146767306":{n:"Rush Hour (1983) (Commavid) (Prototype)"}, "F3CD0F886201D1376F3ABAB2DF53B1B9":{n:"Rush Hour (1983) (Commavid) (Prototype)"}, "AAD61898633F470CE528E3D7EF3D0ADB":{n:"Rush Hour (1983) (Commavid) (Prototype) [a1]"}, "EBF2DFF78A08733251BF3838F02F7938":{n:"Rush Hour (1983) (Commavid) (Prototype) [a2]"}, "3391F7C4C656793F92299F4187E139F7":{n:"Rush Hour (1983) (Commavid) (Prototype) [a4]"}, "8749A0D088DF25218C149DC325ABC7CA":{n:"Rush Hour (1983) (Commavid) (Prototype) [a5]"}, "C529E63013698064149B9E0468AFD941":{n:"S.I.PLIX 2 (Hack)",p:1}, "298387B0637173D2002770A649B4FBCA":{n:"S.I.PLIX 2 (Hack) [a]",p:1}, "17BA72433DD41383065D4AA6DEDB3D91":{n:"SCSIcide (09-06-2001) (Joe Grand)"}, "523F5CBB992F121E2D100F0F9965E33F":{n:"SCSIcide (1.30) (CGE 2001 Release) (Joe Grand)",p:1}, "843435EB360ED72085F7AB9374F9749A":{n:"SCSIcide (1.31) (Joe Grand)",p:1}, "9EFA877A98DD5A075E058214DA428ABB":{n:"SCSIcide (1.32) (Hozer Video Games)",p:1}, "FECE458A8023A809A5006867FECA40E8":{n:"SCSIcide (24-02-2001) (Joe Grand) (PD)"}, "742DE93B8D849220F266B627FBABBA82":{n:"SCSIcide (25-02-2001) (Chris Wilkson) (PD)"}, "FF87D58125AE517EB7B09A0475A1CCDC":{n:"SCSIcide (Score Hack 1) (24-02-2001) (Joe Grand) (PD)"}, "E9C5D04643855949A23FF29349AF74EA":{n:"SCSIcide (Score Hack 2) (24-02-2001) (Joe Grand) (PD)"}, "62921652F6634EB1A0940ED5489C7E18":{n:"SCSIcide (V1.09) (2001) (Joe Grand)",p:1}, "EAE0C06EE61C63B81CD016096FC901B0":{n:"SCSIcide (v1.0) (2001) (Joe Grand)"}, "7991E1797E5E9F311FD957E62D889DFF":{n:"SCSIcide (v1.1) (2001) (Joe Grand)",p:1}, "6538E454B0498AD2BEFE1EF0F87815C0":{n:"SCSIcide (v1.2) (2001) (Joe Grand)",p:1}, "B1A6C96E9093352106BC335E96CAA154":{n:"SCSIcide Pre-release 1 (Joe Grand)"}, "07A3AF1E18B63765B6807876366F5E8A":{n:"SCSIcide Pre-release 2 (Joe Grand)"}, "D483F65468D9A265661917BAE1A54F3E":{n:"SCSIcide Pre-release 3 (Joe Grand)"}, "34340C8EECD1E557314789CC6477E650":{n:"SCSIcide Pre-release 4 (Joe Grand)"}, "F34DD3B8156AAF113CB621B2E51D90B8":{n:"SCSIcide Pre-release 5 (Joe Grand)"}, "A0028F057D496F22B549FD8DEECC6F78":{n:"SCSIcide Pre-release 6 (Joe Grand)"}, "0AC0D491763153FAC75F5337CE32A9D6":{n:"SPAM Image Demo (PD)"}, "504688D49A41BF03D8A955512609F3F2":{n:"SWOOPS! (TJ)",p:1}, "278F14887D601B5E5B620F1870BC09F6":{n:"SWOOPS! (v0.96) (TJ)",p:1}, "5D8F1AB95362ACDF3426D572A6301BF2":{n:"SWOOPS! (v0.96) (TJ) (PAL)",p:1}, "88D8A1ACCAB58CF1ABB043613CF185E9":{n:"Sabotage (Ultravison)"}, "64FAB9D15DF937915B1C392FC119B83B":{n:"Saboteur (05-20-1983) (Atari) (Prototype)"}, "350E0F7B562EC5E457B3F5AF013648DB":{n:"Saboteur (06-09-1983) (Atari) (Prototype)"}, "4E01D9072C500331E65BB87C24020D3F":{n:"Saboteur (06-15-1983) (Atari) (Prototype)"}, "1EC57BBD27BDBD08B60C391C4895C1CF":{n:"Saboteur (09-02-1983) (Atari) (Prototype)"}, "A4ECB54F877CD94515527B11E698608C":{n:"Saboteur (12-20-1983) (Atari) (Prototype)"}, "E723AD8F406CB258B89681EF4CEF0EFF":{n:"Sadoom (TJ) (PAL) (Hack)",p:1}, "81073D0377A2BADEF8D5E74FC44FC323":{n:"Sadoom (TJ) (PAL60) (Hack)",p:1}, "7AB0917107B6EC768A5EBAADF28C497A":{n:"Santa's Helper (Hack)",p:1}, "7BB286CB659D146AF3966D699B51F509":{n:"Save Mary! (04-03-1989) (Atari) (Prototype)"}, "4884B1297500BD1243659E43C7E7579E":{n:"Save Mary! (10-24-1991) (Atari) (Prototype) (PAL)"}, "4D502D6FB5B992EE0591569144128F99":{n:"Save Mary! (11-21-1989) (Atari) (Prototype)"}, "01297D9B450455DD716DB9658EFB2FAE":{n:"Save Our Ship (1983) (TechnoVision) (PAL)"}, "49571B26F46620A85F93448359324C28":{n:"Save Our Ship (Unknown)"}, "ED1A784875538C7871D035B7A98C2433":{n:"Save Our Ship (Unknown) (Hack)"}, "E377C3AF4F54A51B85EFE37D4B7029E6":{n:"Save the Whales (1983) (20th Century Fox) (Prototype)"}, "2516F4F4B811EDE4ECF6FBEB5D54A299":{n:"Schiessbude (1983) (Quelle) (PAL)"}, "F6F1B27EFC247A0E8D473DDB4269FF9E":{n:"Schnapp die Apfeldiebe (1983) (Quelle) (PAL)"}, "E040DF95A055B18EBDB094E904CB71B2":{n:"Score Demo (B. Watson)"}, "EE67DC0B01746372D2B983D88F48E24F":{n:"Scroller Demo (02-01-2003) (CT)"}, "0F2E09C71CC216F79D22A804152BA24B":{n:"Scroller Demo (Bob Colbert) (PD)",c:1}, "0D07D2C1BE1A5EAAEA235A533BCDA781":{n:"Scrolling Playfield 1 (Junkosoft) (PD)"}, "F6C13E816E58C8C62F82B2C8B91A2D67":{n:"Scrolling Playfield 2 (Junkosoft) (PD)"}, "A6737C81542A99EE71CB5F5FF14703D9":{n:"Scrolling Playfield 3 (Junkosoft) (PD)"}, "0D786A41695E5FC8CFFD05A6DBB3F659":{n:"Scrolling Playfield With Score (10-02-2003) (Aaron Bergstrom)"}, "19E761E53E5EC8E9F2FCEEA62715CA06":{n:"Scuba Diver (1983) (Panda)"}, "1BC2427AC9B032A52FE527C7B26CE22C":{n:"Sea Battle (1983) (M Network)"}, "624E0A77F9EC67D628211AAF24D8AEA6":{n:"Sea Hawk (1983) (Panda)"}, "3FD53BFEEE39064C945A769F17815A7F":{n:"Sea Hawk (CCE)"}, "8FA47E5242776E841DF7E708B12EB998":{n:"Sea Hawk (Genesis)"}, "07F42847A79E4F5AE55CC03304B18C25":{n:"Sea Hawk (Zellers)"}, "5DCCF215FDB9BBF5D4A6D0139E5E8BCB":{n:"Sea Hunt (1987) (Froggo)"}, "D8ACAA980CDA94B65066568DD04D9EB0":{n:"Sea Hunt (CCE)"}, "68489E60268A5E6E052BAD9C62681635":{n:"Sea Monster (1982) (BitCorp) (PAL)"}, "DF6A46714960A3E39B57B3C3983801B5":{n:"Sea Monster (1982) (Puzzy) (PAL)"}, "A4B9423877A0B86CA35B52CA3C994AC5":{n:"Sea Monster (1983) (CCE)"}, "2124CF92978C46684B6C39CCC2E33713":{n:"Sea Monster (Unknown) (PAL)"}, "74D072E8A34560C36CACBC57B2462360":{n:"Seahawk (1982) (Sancho) (PAL)"}, "A8C48B4E0BF35FE97CC84FDD2C507F78":{n:"Seamonster (1982) (Puzzy)"}, "240BFBAC5163AF4DF5AE713985386F92":{n:"Seaquest (1983) (Activision)"}, "EBCBC8A181A738E13DF6216E5C329230":{n:"Seaquest (1983) (Activision) (16K)"}, "026180BF641FF17D8577C33FACF0EDEA":{n:"Seaquest (1983) (Activision) (8K)"}, "FD0E5148162E8EC6719445D559F018A9":{n:"Seaquest (1983) (Activision) (PAL)"}, "0B24658714F8DFF110A693A2052CC207":{n:"Seaquest (1983) (CCE)"}, "79C27F90591E3FDC7D2ED020ECBEDEB3":{n:"Seaquest (1983) (CCE) [a]"}, "BC33C685E6FFCED83ABE7A43F30DF7F9":{n:"Seaquest (1983) (Dynacom)"}, "94D90F63678E086F6B6D5E1BC6C4C8C2":{n:"Seaquest (Digivision)"}, "10AF8728F975AA35A99D0965DE8F714C":{n:"Seaquest (Dinatronic)"}, "5B6F5BCBBDE42FC77D0BDB3146693565":{n:"Seaquest (Unknown) (PAL)"}, "40EB4E263581B3DFEC6DD8920B68E00F":{n:"Seawolf 3 (03-23-1981) (Sears) (Prototype) (PAL)"}, "605FD59BFEF88901C8C4794193A4CBAD":{n:"Secret Agent (1983) (Data Age) (Prototype)",p:1}, "FC24A94D4371C69BC58F5245ADA43C44":{n:"Secret Quest (1989) (Atari)"}, "2D2C5F0761E609E3C5228766F446F7F8":{n:"Secret Quest (1989) (Atari) (PAL)"}, "F3DFAE774F3BD005A026E29894DB40D3":{n:"See Saw (Double-Game Package) (1983) (Quelle) (PAL)"}, "8DA51E0C4B6B46F7619425119C7D018E":{n:"Sentinel (1990) (Atari)"}, "55ACE3C775F42EB46F08BB1DCA9114E7":{n:"Shadow Keep (04-03-2003) (Andrew Towers)"}, "D7DD56677E4EC1E6627419478A4A9668":{n:"Shadow Keep (Fixed) (04-03-2003) (Andrew Towers)"}, "54F7EFA6428F14B9F610AD0CA757E26C":{n:"Shark Attack (1982) (Apollo)"}, "5069FECBE4706371F17737B0357CFA68":{n:"Shark Attack (1982) (Apollo) (PAL)"}, "90B1799DDDB8BF748EE286D22E609480":{n:"Ship Demo (PD)"}, "1DB3BC4601F22CF43BE7CE015D74F59A":{n:"Ship Demo (V 10) (PD)"}, "85E48D68C8D802E3BA9D494A47D6E016":{n:"Ship Demo (V 15) (PD)"}, "A0563DD6D8215C38C488FBBD61435626":{n:"Ship Demo (V 1501) (PD)"}, "1B1DAAA9AA5CDED3D633BFCBEB06479C":{n:"Ship Demo (V 1502) (PD)"}, "B5A1A189601A785BDB2F02A424080412":{n:"Shootin' Gallery (1982) (Imagic)"}, "557E893616648C37A27AAB5A47ACBF10":{n:"Shooting Arcade (01-16-1990) (Atari) (Prototype) (PAL)"}, "15C11AB6E4502B2010B18366133FC322":{n:"Shooting Arcade (09-19-1989) (Atari) (Prototype)"}, "25B6DC012CDBA63704EA9535C6987BEB":{n:"Shuttle Orbiter (1983) (Avalon Hill)"}, "E3C0451D29DAD724231BC5818EC4BAE0":{n:"Single-Scanline Positioning Demo 1 (2001) (Roger Williams)"}, "4C205F166157154DF2F1EF60D87E552F":{n:"Single-Scanline Positioning Demo 2 (2001) (Roger Williams)"}, "DE8443FF47283E7B274A7838CB071FB6":{n:"Sinistar (01-04-1984) (Atari) (Prototype)"}, "3E88CCA5B860D0BD8947479E74C44284":{n:"Sinistar (01-23-1984) (Atari) (Prototype)"}, "1E85F8BCCB4B866D4DAA9FCF89306474":{n:"Sinistar (02-13-1984) (Atari) (Prototype)"}, "EA38FCFC06AD87A0AED1A3D1588744E4":{n:"Sinistar (1984) (Atari) (Prototype)"}, "4C8970F6C294A0A54C9C45E5E8445F93":{n:"Sir Lancelot (1983) (Xonox)"}, "DD0CBE5351551A538414FB9E37FC56E8":{n:"Sir Lancelot (1983) (Xonox) (PAL)"}, "7EAD257E8B5A44CAC538F5F54C7A0023":{n:"Sir Lancelot (1983) (Xonox) [a1]"}, "8490E1014C2BAA0D3A3A08854E5D68B3":{n:"Sir Lancelot (1983) (Xonox) [a2]"}, "F847FB8DBA6C6D66D13724DBE5D95C4D":{n:"Skate Boardin' (1987) (Absolute)"}, "ABE40542E4FF2D1C51AA2BB033F09984":{n:"Skate Boardin' (1987) (Absolute) (PAL)"}, "7F9FBE3E00A21EA06E6AE5E0E5DB2143":{n:"Skate Boardin' (2002) (Skyworks)"}, "39C78D682516D79130B379FA9DEB8D1C":{n:"Skeet Shoot (1981) (Apollo)"}, "5F2B4C155949F01C06507FB32369D42A":{n:"Skeet Shoot (1981) (Apollo) (4K)"}, "0832FB2EE654BF9382BC57D2B16D2FFC":{n:"Skeet Shoot (1981) (Apollo) (PAL)"}, "4189ADFC1B30C121248876E3A1A3AC7E":{n:"Skeleton (Complete) (06-09-2002) (Eric Ball)"}, "40E12C008037A323A1290C8FA4D2FE7F":{n:"Skeleton (NTSC) (06-09-2002) (Eric Ball)"}, "647162CCEB550FD49820E2206D9EE7E8":{n:"Skeleton (NTSC) (2002) (Eric Ball)"}, "8E42674972D6805068FC653E014370FD":{n:"Skeleton (PAL) (15-10-2002) (Eric Ball)"}, "C033DC1D7B6FDE41B9CADCE9638909BB":{n:"Skeleton (V1.1) (06-09-2002) (Eric Ball)"}, "28A4CD87FB9DE4EE91693A38611CB53C":{n:"Skeleton (V1.1) (NTSC) (24-10-2002) (Eric Ball)"}, "8E887D1BA5F3A71AE8A0EA16A4AF9FC9":{n:"Skeleton (V1.1) (PAL) (24-10-2002) (Eric Ball)"}, "F20BD756F3990E06C492F53CD0168E68":{n:"Skeleton+ (03-05-2003) (Eric Ball) (NTSC)"}, "22B22C4CE240303012E8A9596AE8D189":{n:"Skeleton+ (03-05-2003) (Eric Ball) (PAL)"}, "CFEF1A2D1F6A5EE7A5E1F43F3056F112":{n:"Skeleton+ (05-05-2003) (Eric Ball) (NTSC)"}, "75B22FDF632D76E246433DB1EBCCD3C4":{n:"Skeleton+ (05-05-2003) (Eric Ball) (PAL)"}, "F98D869F287D2CE4F8FB36E0686929D9":{n:"Skeleton+ (17-04-2003) (Eric Ball) (NTSC)"}, "43F8459D39FB4EDDF9186D62722FF795":{n:"Skeleton+ (17-04-2003) (Eric Ball) (PAL)"}, "EAFE8B40313A65792E88FF9F2FE2655C":{n:"Skeleton+ (NTSC)"}, "63C7395D412A3CD095CCDD9B5711F387":{n:"Skeleton+ (PAL)"}, "8654D7F0FB351960016E06646F639B02":{n:"Ski Hunt (1983) (Home Vision) (PAL)"}, "F10E3F45FB01416C87E5835AB270B53A":{n:"Ski Run (Ariola) (PAL)"}, "5305F69FBF772FAC4760CDCF87F1AB1F":{n:"Ski Run (Jone Yuan)"}, "B76FBADC8FFB1F83E2CA08B6FB4D6C9F":{n:"Skiing (1980) (Activision)"}, "0D90A0EE73D55539B7DEF24C88CAA651":{n:"Skiing (1980) (Activision) (16K)"}, "60BBD425CB7214DDB9F9A31948E91ECB":{n:"Skiing (1980) (Activision) (4K)"}, "7623A639A6FFFDB246775FE2EABC8D01":{n:"Skiing (1980) (Activision) (8K)"}, "EEC61CC4250DF70939D48FE02D7122AC":{n:"Skiing (1980) (Activision) (PAL)"}, "E1F88DA6DA8A7D521CA1DCBF2BC6978B":{n:"Skiing (1980) (Activision) (PAL) (4K)"}, "0E4B2B6E014A93EF8BE896823DA0D4EC":{n:"Skiing (208 in 1) (Unknown) (PAL)"}, "367411B78119299234772C08DF10E134":{n:"Skiing (32 in 1) (1988) (Atari) (PAL)"}, "40B59249E05135BCA33861E383735E9E":{n:"Skiing (32 in 1) (1988) (Atari) (PAL) (4K)"}, "40D9F5709877ECF3DD1184F9791DD35E":{n:"Skiing (Dactari - Milmar)"}, "7ED61A18CEBDECA0A93BE1F5461731E5":{n:"Skiing (Dactari) (4K)"}, "C118854D670289A8B5D5156AA74B0C49":{n:"Skiing (Jone Yuan)"}, "13584411DA0A8D431991035423FDC0DC":{n:"Skiing (Jone Yuan) (4K)"}, "340F546D59E72FB358C49AC2CA8482BB":{n:"Skindiver (1983) (Sancho) (PAL)"}, "C31A17942D162B80962CB1F7571CD1D5":{n:"Sky Alien (1983) (Home Vision) (PAL)"}, "BC97D544F1D4834CC72BCC92A37B8C1B":{n:"Sky Demo (PD)"}, "46C021A3E9E2FD00919CA3DD1A6B76D8":{n:"Sky Diver (1979) (Atari)"}, "3D8A2D6493123A53ADE45E3E2C5CAFA0":{n:"Sky Diver (1979) (Atari) (4K)"}, "756CA07A65A4FBBEDEB5F0DDFC04D0BE":{n:"Sky Diver (1979) (Atari) (PAL)"}, "5EF303B9F0AA8CF20720C560E5F9BAA1":{n:"Sky Diver (1979) (Atari) (PAL) (4K)"}, "3F75A5DA3E40D486B21DFC1C8517ADC0":{n:"Sky Diver (32 in 1) (1988) (Atari) (PAL)"}, "F1FE06EBE2900EAC4CDD17799389A102":{n:"Sky Diver (32 in 1) (1988) (Atari) (PAL) (4K)"}, "B23EBF427713DD0198B7EF47DBD07EF4":{n:"Sky Diver (Jone Yuan) (4K) (Hack)"}, "5A81AD4E184050851E63C8E16E3DAC77":{n:"Sky Diver (Jone Yuan) (Hack)"}, "37252757A79DC5B174E3C03D6EA0BDCB":{n:"Sky Diver (Unknown) (PAL) (4K) (Hack)"}, "8190B403D67BF9792FE22FA5D22F3556":{n:"Sky Diver (Unknown) (PAL) (Hack)"}, "2A0BA55E56E7A596146FA729ACF0E109":{n:"Sky Jinks (1982) (Activision)"}, "05AFF8F626EF870432AE3B3D9D5AA301":{n:"Sky Jinks (1982) (Activision) (16K)"}, "8BD8F65377023BDB7C5FCF46DDDA5D31":{n:"Sky Jinks (1982) (Activision) (4K)"}, "A4790224BD5AFABD53CBE93E46A7F241":{n:"Sky Jinks (1982) (Activision) (8K)"}, "50A410A5DED0FC9AA6576BE45A04F215":{n:"Sky Jinks (1982) (Activision) (PAL)"}, "502168660BFD9C1D2649D415DC89C69D":{n:"Sky Jinks (1982) (Activision) (PAL) (4K)"}, "93DC15D15E77A7B23162467F95A5F22D":{n:"Sky Jinks (CCE)"}, "8764462D7D19A33B0717AF22B99FC88F":{n:"Sky Jinks (CCE) (4K)"}, "E1B90F1E01B1A316D7BBF141525CC00E":{n:"Sky Jinks (Unknown) (PAL) (4K) (Hack)"}, "F992A39B46AA48188FAB12AD3809AE4A":{n:"Sky Jinks (Unknown) (PAL) (Hack)"}, "4C9307DE724C36FD487AF6C99CA078F2":{n:"Sky Patrol (1982) (Imagic) (Prototype)"}, "3B91C347D8E6427EDBE942A7A405290D":{n:"Sky Skipper (1983) (Parker Bros)"}, "514F911ECFF2BE5EEFF2F39C49A9725C":{n:"Sky Skipper (1983) (Parker Bros) (PAL)"}, "1AA7344B563C597EECFBFCF8E7093C27":{n:"Slot Invaders (David Marli) (Hack)"}, "F90B5DA189F24D7E1A2117D8C8ABC952":{n:"Slot Machine (1979) (Atari)"}, "81254EBCE88FA46C4FF5A2F4D2BAD538":{n:"Slot Machine (1979) (Atari) (4K)"}, "705FE719179E65B0AF328644F3A04900":{n:"Slot Machine (1979) (Atari) (4K) [a]"}, "FC6052438F339AEA373BBC999433388A":{n:"Slot Machine (1979) (Atari) (PAL)"}, "75EA128BA96AC6DB8EDF54B071027C4E":{n:"Slot Machine (32 in 1) (1988) (Atari) (PAL)"}, "1E272D09C0E55F5EF14FCB76A735F6D7":{n:"Slot Machine (32 in 1) (1988) (Atari) (PAL) (4K)"}, "DBDD21E1EE3D72119E8CD14D943C585B":{n:"Slot Machine (Unknown) (PAL) (4K)"}, "AED82052F7589DF05A3F417BB4E45F0C":{n:"Slot Racers (1978) (Atari)"}, "5F708CA39627697E859D1C53F8D8D7D2":{n:"Slot Racers (1978) (Atari) (4K)"}, "A7ED7DC5CBC901388AFA59030FB11D26":{n:"Slot Racers (1978) (Atari) (PAL)"}, "7A64A8B727C8215D945E37D565CA95A5":{n:"Slot Racers (1978) (Atari) (PAL) (4K)"}, "D1D704A7146E95709B57B6D4CAC3F788":{n:"Slot Racers (32 in 1) (1988) (Atari) (PAL)"}, "F6D512BEF1BF253DC935D0E13C3D1462":{n:"Slot Racers (Unknown) (PAL) (4K)"}, "92D1F6AC179EBE5963868D6BC1BDDA8D":{n:"Smash Hit Pak - Frogger, Boxing, Seaquest, Skiing, Stampede (HES) (PAL)"}, "73C545DB2AFD5783D37C46004E4024C2":{n:"Smurf (1982) (CBS Electronics) (PAL)"}, "24AFF972D58990F9B88A6D787C796F1E":{n:"Smurf (1982) (CBS Electronics) (PAL) [a]"}, "3D1E83AFDB4265FA2FB84819C9CFD39C":{n:"Smurf - Rescue in Gargamel's Castle (1982) (Coleco)"}, "A204CD4FB1944C86E800120706512A64":{n:"Smurfs Save the Day (1983) (Coleco)"}, "898B5467551D32AF48A604802407B6E8":{n:"Snail Against Squirrel (1983) (BitCorp) (PAL)"}, "AC26D7D37248D1D8EAC5ECCACDBEF8DB":{n:"Snail Against Squirrel (Unknown) (PAL)"}, "9C6FAA4FF7F2AE549BBCB14F582B70E4":{n:"Sneak 'n Peek (1982) (U.S. Games)"}, "F21813AA050437F0DBC8479864ACEC6D":{n:"Sneak 'n Peek (Unknown) (PAL)"}, "C54B4207CE1D4BF72FADBB1A805D4A39":{n:"Sniper (Feb 30) (2001) (Prototype)"}, "01293BD90A4579ABB7AED2F7D440681F":{n:"Snoopy (1983) (Century) (PAL)"}, "45A095645696A217E416E4BD2BAEA723":{n:"Snoopy (Digivision)"}, "0F39FC03D579D0D93A6B729A3746843E":{n:"Snoopy and the Red Baron (05-27-1983) (Atari) (Prototype)"}, "57939B326DF86B74CA6404F64F89FCE9":{n:"Snoopy and the Red Baron (1983) (Atari)"}, "F844F4C6F3BAAAF5322657442D6F29EB":{n:"Snoopy and the Red Baron (1983) (Atari) (PAL)"}, "BDA1463E02AE3A6E1107FFE1B572EFD2":{n:"Snoopy and the Red Baron (1983) (Atari) (PAL) [a]"}, "C5D2834BF98E90245E545573EB7E6BBC":{n:"Snoopy and the Red Baron (CCE)"}, "D2DEDDB77C8B823E4BE9C57CB3C69ADC":{n:"Snoopy and the Red Baron (Canal 3)"}, "75028162BFC4CC8E74B04E320F9E6A3F":{n:"Snow White and the Seven Dwarfs (02-09-1983) (Atari) (Prototype)"}, "75EE371CCFC4F43E7D9B8F24E1266B55":{n:"Snow White and the Seven Dwarfs (11-09-1982) (Atari) (Prototype)"}, "3F6DBF448F25E2BD06DEA44248EB122D":{n:"Soccer (1989) (Telegames)"}, "604E09724555807C28108049EFE34A13":{n:"Sokoban (01-01-2003) (Adam Wozniak)"}, "B4DAEDB43511521DB9036D503B3C1B69":{n:"Sokoban (01-01-2003) (Adam Wozniak) [a1]"}, "947317A89AF38A49C4864D6BDD6A91FB":{n:"Solar Fox (1983) (CBS Electronics)"}, "E03B0B091BEA5BC9D3F14EE0221E714D":{n:"Solar Fox (1983) (CBS Electronics) (PAL)"}, "DF753CB87D3AF4D03F694AB848638108":{n:"Solar Fox (1983) (CBS Electronics) (PAL) [a]"}, "97842FE847E8EB71263D6F92F7E122BD":{n:"Solar Storm (1983) (Imagic)",p:1}, "E6DE4EF9AB62E2196962AA6B0DEDAC59":{n:"Solar Storm (1983) (Imagic) (PAL)",p:1}, "E72EB8D4410152BDCB69E7FBA327B420":{n:"Solaris (1986) (Atari)"}, "BC4CF38A4BEE45752DC466C98ED7AD09":{n:"Solaris (1986) (Atari) (PAL)"}, "0ADB21206DE92E8AEC5EF295805EBB90":{n:"Solaris (Genesis)"}, "F19ABA18F86E415812480AD2BE221425":{n:"Solaris Trainer (2002) (Chris Larkin) (Hack)"}, "2DFEC1615C49501FEFC02165C81955E6":{n:"Song (05-11-2002) (Paul Slocum)",c:1}, "CAD982C9B45BC5EFF34E4EA982D5F1CA":{n:"Song (17-02-2003) (Paul Slocum)",c:1}, "D2C4F8A4A98A905A9DEEF3BA7380ED64":{n:"Sorcerer (1983) (Mythicon)"}, "5F7AE9A7F8D79A3B37E8FC841F65643A":{n:"Sorcerer's Apprentice (1983) (Atari)"}, "2E82A1628EF6C735C0AB8FA92927E9B0":{n:"Sorcerer's Apprentice (1983) (Atari) (PAL)"}, "27C4C2AF4B46394BB98638AF8E0F6E9D":{n:"Sorcerer's Apprentice (1983) (Atari) (Prototype)"}, "101AB60F4000A5D13792EF0ABAD5F74B":{n:"Sorcerer's Apprentice (1983) (Atari) [a]"}, "F78C125B5DA483C41E51522947D6C4CE":{n:"Sound Paddle V1 (Dennis Caswell & Jim Nitchals) (PD)",p:1}, "EEE7695AE3EEA7818321DF0B790B31F3":{n:"Sound Paddle V2 (Dennis Caswell & Jim Nitchals) (PD)",p:1}, "32F4E47A71601AB06CFB59E1C6A0B846":{n:"Sound X (1994) (Ed Federmeyer)"}, "7DBC8FA2E488E3F6B87FBE0F76C5B89F":{n:"Sound X (1996) (Ed Federmeyer)"}, "310BA30E25EA8957E58180B663503C0C":{n:"Sound X6 (1994) (Ed Federmeyer)"}, "24B9ADAC1B4F85B0BAC9BF9B9E180906":{n:"Space 2002 (Angelino) (Hack)"}, "17BADBB3F54D1FC01EE68726882F26A6":{n:"Space Attack (1982) (M Network)"}, "ABB741C83F665D73C86D90A7D9292A9B":{n:"Space Attack (1989) (Telegames) (PAL)"}, "F047DF70D3D08E331122CD2DE61D6AF8":{n:"Space Battle (NTSC)"}, "CC12581E079CD18330A89902625B8347":{n:"Space Battle (PAL)"}, "559317712F989F097EA464517F1A8318":{n:"Space Canyon (1983) (Panda)"}, "DF6A28A89600AFFE36D94394EF597214":{n:"Space Cavern (1981) (Apollo)"}, "D9548AD44E67EDEC202D1B8B325E5ADF":{n:"Space Cavern (1981) (Apollo) (PAL)"}, "7AC4F4FB425DB38288FA07FB8FF4B21D":{n:"Space Eagle (1983) (Goliath) (PAL)"}, "0D27C7F5DB349B592F70F68DAF5E8F3B":{n:"Space Instigators (21-10-2002) (CT)"}, "B2A6F31636B699AEDA900F07152BAB6E":{n:"Space Instigators (Public Release 2) (06-01-2003) (CT)"}, "18BEBBBD41C234F82B1717B1905E6027":{n:"Space Instigators (Public Release) (02-01-2003) (CT)"}, "CDA38714267978B9A8B0B24BEE3529AE":{n:"Space Instigators (V1.6) (17-10-2002) (CT)"}, "98E6E34AF45A0664597972C3BB31180F":{n:"Space Instigators (V1.7) (17-10-2002) (CT)"}, "52BAE1726D2D7A531C9CA81E25377FC3":{n:"Space Instigators (V1.8 Fixed) (20-10-2002) (CT)"}, "CFEE10BD7119F10B136921CED2EE8972":{n:"Space Instigators (V1.8) (19-10-2002) (CT)"}, "E927ECF80F3784D745ABD8368D78F2F3":{n:"Space Instigators (V1.8) (19-10-2002) (CT) [a1]"}, "DD10B5EE37FDBF909423F2998A1F3179":{n:"Space Instigators (V1.9) (21-10-2002) (CT)"}, "E10BF1AF6BF3B4A253C5BEF6577FE923":{n:"Space Invaders (1978) (Atari) [h1]"}, "07F91E33E76F53BB9D2731FD5D8A35A5":{n:"Space Invaders (1978) (Atari) [t1]"}, "72FFBEF6504B75E69EE1045AF9075F66":{n:"Space Invaders (1980) (Atari)"}, "F1B7EDFF81CEEF5AF7AE1FA76C8590FC":{n:"Space Invaders (1980) (Atari) (PAL)"}, "8747BA79CD39FA83A529BB26010DB21B":{n:"Space Invaders (1980) (Atari) (PAL) [different speed and colors]"}, "7CC77F6745E1F2B20DF4A4327D350545":{n:"Space Invaders (1980) (Atari) (PAL) [fixed]"}, "61DBE94F110F30CA4EC524AE5CE2D026":{n:"Space Invaders (1983) (CCE)"}, "C126656DF6BADFA519CC63E681FB3596":{n:"Space Invaders (2002) (Ron Corcoran) (Hack)"}, "2EF36341D1BF42E02C7EA2F71E024982":{n:"Space Invaders (Explosion Hack)"}, "270229C6D5578446E6A588492E4E5910":{n:"Space Invaders 2 (Hack)"}, "0963AA9F7F6CF5A36FF700001583624E":{n:"Space Invaders 2 (Hack) [o1]"}, "2CFB188C1091CC7EC2A7E60064D2A758":{n:"Space Invaders Hack Demo (2003) (SnailSoft)"}, "6F2AAFFAAF53D23A28BF6677B86AC0E3":{n:"Space Jockey (1982) (U.S. Games)"}, "D1A9478B99D6A55E13A9FD4262DA7CD4":{n:"Space Jockey (1982) (U.S. Games) (4K)"}, "457E7D4FCD56EBC47F5925DBEA3EE427":{n:"Space Jockey (1983) (Carrere Video) (PAL)"}, "EE9CAEE4EB958284FB10C277B14537F1":{n:"Space Jockey (1983) (Carrere Video) (PAL) (4K)"}, "E1D79E4E7C150F3861256C541EC715A1":{n:"Space Jockey (208 in 1) (Unknown) (PAL)"}, "822A950F27FF0122870558A89A49CAD3":{n:"Space Jockey (Unknown) (PAL)"}, "C689148AD9275667924AB334107B517E":{n:"Space Raid (Jone Yuan)"}, "690A6049DB78B9400C13521646708E9C":{n:"Space Raid (King Tripod) (PAL)"}, "345769D085113D57937198262AF52298":{n:"Space Raid (Rainbow Vision) (PAL)"}, "1A624E236526C4C8F31175E9C89B2A22":{n:"Space Raid (Rainbow Vision) (PAL) [a]"}, "1BEF389E3DD2D4CA4F2F60D42C932509":{n:"Space Robot (1983) (Dimax - Sinmax) (PAL)",c:1}, "3DFB7C1803F937FADC652A3E95FF7DC6":{n:"Space Robot (Dimax - Sinmax)",c:1}, "82E7AAB602C378CFFDD8186A099E807E":{n:"Space Robot (Unknown)"}, "C4D888BCF532E7C9C5FDEAFBB145266A":{n:"Space Robot (Unknown) (PAL)",c:1}, "5894C9C0C1E7E29F3AB86C6D3F673361":{n:"Space Shuttle (1983) (Activision)"}, "4F6702C3BA6E0EE2E2868D054B00C064":{n:"Space Shuttle (1983) (Activision) (PAL)"}, "898143773824663EFE88D0A3A0BB1BA4":{n:"Space Shuttle (1983) (Activision) [FE]"}, "FF5A9E340D96DF6F5A5B6EB038E923BD":{n:"Space Shuttle (1983) (Activision) [t1]"}, "A8D0A4A77CD71AC601BD71DF5A060E4C":{n:"Space Shuttle (1983) (Activision) [t2] (Fuel)"}, "D97E3D0B4575CE0B9A6132E19CFEAC6E":{n:"Space Treat (061002) (PD)"}, "2683D29A282DD059535AC3BB250F540D":{n:"Space Treat (12-01-2003) (Fabrizio Zavagli)"}, "DED26E1CB17F875A9C17515C900F9933":{n:"Space Treat (29-12-2002) (Fabrizio Zavagli)"}, "3367EEBA3269AA04720ABE6169767502":{n:"Space Treat (30-12-2002) (Fabrizio Zavagli)"}, "75B557BE7F08DB84EC5B242207B9F241":{n:"Space Treat (30-12-2002) (Fabrizio Zavagli) [a1]"}, "E74022CFE31EC8908844718DFBDEDF7A":{n:"Space Treat (30-12-2002) (Fabrizio Zavagli) [a2]"}, "D49AFF83F77A1B9041AD7185DF3C2277":{n:"Space Treat (60% complete) (PD)"}, "6C9A32AD83BCFDE3774536E52BE1CCE7":{n:"Space Treat (NTSC) (13-08-2002) (Fabrizio Zavagli)"}, "B0C47E426C7F799AEE2C40422DF8F56A":{n:"Space Treat (PAL) (Fabrizio Zavagli)"}, "DFAFA3FA58F5CC3F0342CCA475DF6095":{n:"Space Treat (V1.1 Beta) (24-12-2002) (Fabrizio Zavagli)"}, "562ACB1B7FF182ABA133BDA8E21AD7C1":{n:"Space Treat Deluxe (08-03-2003) (Fabrizio Zavagli)"}, "DF2745D585238780101DF812D00B49F4":{n:"Space Tunnel (1982) (BitCorp)"}, "C5387FC1AA71F11D2FA82459E189A5F0":{n:"Space Tunnel (1982) (BitCorp) (PAL)"}, "8917F7C1AC5EB05B82331CF01C495AF2":{n:"Space Tunnel (1982) (BitCorp) (PAL) [a]"}, "BE3F0E827E2F748819DAC2A22D6AC823":{n:"Space Tunnel (1982) (Puzzy)"}, "D73AD614F1C2357997C88F37E75B18FE":{n:"Space Tunnel (1982) (Puzzy) (PAL)"}, "7FCD5FB59E88FC7B8473C641F44226C3":{n:"Space Tunnel (1983) (CCE)"}, "A7EF44CCB5B9000CAF02DF3E6DA71A92":{n:"Space War (1978) (Atari)"}, "7E9DA5CB84D5BC869854938FE3E85FFA":{n:"Space War (1978) (Atari) (4K)"}, "F9677B2EC8728A703EB710274474613D":{n:"Space War (1978) (Atari) (PAL)"}, "0519F395D5F7D76BE813B834AA51C0BE":{n:"Space War (1978) (Atari) (PAL) (4K)"}, "77887E4192A6B0A781530E6CF9BE7199":{n:"Space War (1978) (Atari) [b1]"}, "E505BD8E59E31AAED20718D47B15C61B":{n:"Space War (1982) (Funvision) (PAL)"}, "63D6247F35902BA32AA49E7660B0ECAA":{n:"Space War (208 in 1) (Unknown) (PAL)"}, "B702641D698C60BCDC922DBD8C9DD49C":{n:"Space War (32 in 1) (1988) (Atari) (PAL)"}, "8F60551DB6D1535EF0030F155018C738":{n:"Space War (Unknown) (PAL) (4K)"}, "45040679D72B101189C298A864A5B5BA":{n:"SpaceMaster X-7 (1983) (20th Century Fox)"}, "E14FEDDEB82F5160ED5CF9CA4078E58D":{n:"SpaceMaster X-7 (208 in 1) (Unknown) (PAL)"}, "EC5C861B487A5075876AB01155E74C6C":{n:"Spacechase (1981) (Apollo)"}, "89EABA47A59CBFD26E74AAD32F553CD7":{n:"Spacechase (1981) (Apollo) (PAL)"}, "FAFFD84F3A8ECEEE2FA5EA5B0A3E6678":{n:"Spectracube Invasion (Suntek) (PAL)"}, "F3F92AAD3A335F0A1EAD24A0214FF446":{n:"Spectrum Color Demo (PD)"}, "327FE8CF94F3A45C35A840A453DF1235":{n:"Spice Girls Rule Demo (PD)"}, "A8A703E073183A89C94D4D99B9661B7F":{n:"Spice Invaders (Franklin Cruz) (Hack)"}, "24D018C4A6DE7E5BD19A36F2B879B335":{n:"Spider Fighter (1982) (Activision)"}, "8786F229B974C393222874F73A9F3206":{n:"Spider Fighter (1982) (Activision) (PAL)"}, "BA3A17EFD26DB8B4F09C0CF7AFDF84D1":{n:"Spider Fighter (1983) (Activision) (16K)"}, "D25018349C544320BF3FD5092EE072BC":{n:"Spider Fighter (1983) (Activision) (8K)"}, "0FC161704C46E16F7483F92B06C1558D":{n:"Spider Fighter (1983) (CCE)"}, "C41E7735F6701DD50E84EE71D3ED1D8F":{n:"Spider Fighter (1983) (Dynacom)"}, "92E72F7CC569584C44C9530D645AE04E":{n:"Spider Fighter (Canal 3)"}, "B40DEA357D41C5408546E4E4D5F27779":{n:"Spider Fighter (Digivision)"}, "7778AC65D775A079F537E97CBDAD541C":{n:"Spider Fighter (Unknown) (PAL)"}, "F14D5E96EC3380AEF57A4B70132C6677":{n:"Spider Kong (1983) (Goliath) (PAL) [a]"}, "672012D40336B403EDEA4A98CE70C76D":{n:"Spider Kong (208 in 1) (Unknown) (PAL)"}, "AE465044DFBA287D344BA468820995D7":{n:"Spider Kong (Unknown) (PAL)"}, "21299C8C3AC1D54F8289D88702A738FD":{n:"Spider Maze (1982) (K-Tel Vision)"}, "37B98344C8E0746C486CAF5AAEEC892A":{n:"Spider Maze (1982) (K-Tel Vision) (PAL)"}, "D39E29B03AF3C28641084DD1528AAE05":{n:"Spider Monster (1982) (Funvision) (PAL)"}, "199EB0B8DCE1408F3F7D46411B715CA9":{n:"Spider-Man (1982) (Parker Bros)"}, "E77EC259E1387BC308B0534647A89198":{n:"Spider-Man (1982) (Parker Bros) (PAL)"}, "8454ED9787C9D8211748CCDDB673E920":{n:"Spiderdroid (1987) (Froggo)"}, "F7AF41A87533524D9A478575B0D873D0":{n:"Spiderman (1983) (Quelle) (PAL)"}, "A4E885726AF9D97B12BB5A36792EAB63":{n:"Spike's Peak (1983) (Xonox)"}, "B37F0FE822B92CA8F5E330BF62D56EA9":{n:"Spike's Peak (1983) (Xonox) (PAL)"}, "9BB136B62521C67AC893213E01DD338F":{n:"Spike's Peak (1983) (Xonox) (PAL) [a]"}, "542C6DD5F7280179B51917A4CBA4FAFF":{n:"Spinning Fireball (1983) (ZiMAG) (Prototype)"}, "D3171407C3A8BB401A3A62EB578F48FB":{n:"Spinning Fireball (1983) (ZiMAG) (Prototype) [a]",c:1}, "98555B95CB38E0E0B22B482B2B60A5B6":{n:"Spinning Fireball (Unknown) (PAL)",c:1}, "CEF2287D5FD80216B2200FB2EF1ADFA8":{n:"Spitfire Attack (1983) (Milton Bradley)"}, "FFEBB0070689B9D322687EDD9C0A2BAE":{n:"Spitfire Attack (1983) (Milton Bradley) [h1]"}, "FB91DA78455D9B1606913FBF8C859772":{n:"Split Screen (Ballblazer) Demo (PD)"}, "A4D026A5C200EF98518EBB77719FE8DC":{n:"SpongeBob SquarePants (2003) (Kyle Pittman) (Hack)"}, "2C3B2843295C9D6B16996971180A3FE9":{n:"Sports Action Pak - Enduro, Ice Hockey, Fishing Derby, Dragster (1988) (HES) (PAL)"}, "4CD796B5911ED3F1062E805A3DF33D98":{n:"Springer (1982) (Tigervision)"}, "133456269A03E3FDAE6CDDD65754C50D":{n:"Springer (1982) (Tigervision) (PAL)"}, "5A8AFE5422ABBFB0A342FB15AFD7415F":{n:"Sprint Master (1988) (Atari)"}, "B2D5D200F0AF8485413FAD957828582A":{n:"Sprint Master (1988) (Atari) (PAL)"}, "6B75F8FA4FD011A6698C58315F83D2AC":{n:"Sprintmaster DC (TJ)"}, "D597D35C6022C590D6E75E865738558A":{n:"Sprite Color Demo (PD)"}, "F1B2EA568B3E156E3F2849DAC83591F6":{n:"Sprite Demo (1997) (Bob Colbert) (PD)"}, "E15B5525CF8F77297B322838DF8D999C":{n:"Sprite Demo 0 (PD)"}, "D5C6B81212AD86FD9542A1FEDAF57CAE":{n:"Sprite Demo 1 (PD)"}, "FE0BC4BB92C1C4DE7D5706AAA8D8C10D":{n:"Sprite Demo 2 (PD)"}, "DBABB80E92FF18D8EECF615C0539151E":{n:"Sprite Demo 3 (PD)"}, "61728C6CFB052E62A9ED088C5BF407BA":{n:"Sprite Demo 4 (PD)"}, "AD7E97C19BD25D5AA3999430845C755B":{n:"Sprite Demo 5 (PD)"}, "ACAA27D214039D89D7031609AAFA55C3":{n:"Sprite Demo 6 (PD)"}, "2D6DA0EB85EABC93270E5BB8A466CA51":{n:"Sprite Demo 7 (PD)"}, "DFE034297200DFF672DF9533ED1449A9":{n:"Sprite Movement Demo 1 (2001) (Roger Williams)"}, "D4C590CCFB611A73B3331359700C01A3":{n:"Sprite Movement Demo 2 (2001) (Roger Williams)"}, "37AB3AFFC7987995784B59FCD3FCBD31":{n:"Sprite Test (29-11-2002) (Eric Ball)"}, "3105967F7222CC36A5AC6E5F6E89A0B4":{n:"Spy Hunter (1984) (Sega)"}, "6A8C6940D3BE6FD01274363C4D4B298E":{n:"Spy Hunter (Genesis)"}, "2A360BC85BF22DE438651CF92FFDA1DE":{n:"Spy Vs. Spy (4 Game in One) (1983) (BitCorp) (PAL)"}, "BA257438F8A78862A9E014D831143690":{n:"Squeeze Box (1982) (U.S. Games)"}, "68878250E106EB6C7754BC2519D780A0":{n:"Squirrel (1983) (CCE)"}, "34C808AD6577DBFA46169B73171585A3":{n:"Squoosh (1983) (Apollo) (Prototype)"}, "22ABBDCB094D014388D529352ABE9B4B":{n:"Squoosh (1983) (Apollo) (Prototype) [a]"}, "21A96301BB0DF27FDE2E7EEFA49E0397":{n:"Sssnake (1982) (Data Age)"}, "B3203E383B435F7E43F9492893C7469F":{n:"Sssnake (1983) (Gameworld) (PAL)"}, "21D7334E406C2407E69DBDDD7CEC3583":{n:"Stampede (1981) (Activision)"}, "9057694DCE8449521E6164D263702185":{n:"Stampede (1981) (Activision) (16K)"}, "E66E5AF5DEA661D58420088368E4EF0D":{n:"Stampede (1981) (Activision) (4K)"}, "53F147B9746FDC997C62F3DD67888EE5":{n:"Stampede (1981) (Activision) (8K)"}, "75511BB694662301C9E71DF645F4B5A7":{n:"Stampede (1981) (Activision) (PAL)"}, "F52F40299FD238C6FFD9E6107050DC76":{n:"Stampede (1981) (Activision) (PAL) (4K)"}, "C9196E28367E46F8A55E04C27743148F":{n:"Stampede (32 in 1) (1988) (Atari) (PAL)"}, "F20675C8B98518367B9F5B8EE6F7C8EA":{n:"Stampede (32 in 1) (1988) (Atari) (PAL) (4K)"}, "F77F5FC3893DA5D00198E4CD96544AAD":{n:"Stampede (Canal 3)"}, "866E5150C995C4AE5172E5207BA948C7":{n:"Stampede (Canal 3) (16K)"}, "43ADF60EBDD6B5A0FAE21594ECF17154":{n:"Stampede (Jone Yuan)"}, "D170317AE4C7D997A989C7D6567C2840":{n:"Stampede (Jone Yuan) (4K) (Hack)"}, "1EA1ABCD2D3D3D628F59A99A9D41B13B":{n:"Stampede (Jone Yuan) (Hack)"}, "869ABE0426E6E9FCB6D75A3C2D6E05D1":{n:"Stampede (Unknown) (PAL)"}, "0945081A6BD00345FF3D58EB7A07330A":{n:"Stampede (Unknown) (PAL) (4K)"}, "A8916734FF8C64EC3342F4C73FD5B57D":{n:"Stand Alone Test Cart (1982) (Atari) [a]"}, "D9C9CECE2E769C7985494B1403A25721":{n:"Star Castle 2600 (SolidCorp)",c:1}, "54BAFC299423F5A50B8BC3A797914706":{n:"Star Castle 2600 (SolidCorp) (PAL)",c:1}, "CE8467AE2A3A5BC88CA72A2CE44CE28C":{n:"Star Castle 2600 (SolidCorp) (PAL) [015]",c:1}, "DD0DE0F61AF2A2A4878E377B880A3933":{n:"Star Castle 2600 (SolidCorp) [013]",c:1}, "C0589BB73858924389077FA3C2E9441A":{n:"Star Castle 2600 (SolidCorp) [014]",c:1}, "39B94D41BD3B01C12B4054C1A8733783":{n:"Star Castle 2600 (SolidCorp) [016]",c:1}, "2AEEDCC6EB1602EFB77161B0CEF832AB":{n:"Star Castle 2600 (SolidCorp) [025]",c:1}, "1EF04E7E508296A8D9EB61CC7DAE2E5D":{n:"Star Castle 2600 (SolidCorp) [069]",c:1}, "6E4521989A60A0DDF4FF1FC6E6E5FC3D":{n:"Star Fire (01-05-2002) (MP)"}, "A443D8557D712845C8CD3699363A42E6":{n:"Star Fire (07-01-2003) (MP)"}, "1E1817D9CBCC3BA75043B7DB4E6C228F":{n:"Star Fire (07-10-2002) (MP)"}, "DBA2692A216CB6C262C78F8B111A813E":{n:"Star Fire (08-10-2002) (MP)"}, "47BB1C677FE7BA5F376372AE7358E790":{n:"Star Fire (10-10-2002) (MP)"}, "43E6C5159C3A093FCA88656628C6EF34":{n:"Star Fire (17-02-2003) (MP)"}, "6F75D72E4CF996100CCDD163D57BDAC2":{n:"Star Fire (200203) (MP)"}, "18760F1F9CA5E18610115CF7B815B824":{n:"Star Fire (23-10-2002) (MP)"}, "539B7038ACEC0CCEDEAE40F238998579":{n:"Star Fire (25-10-2002) (MP)"}, "16FBB36A6124567405A235821E8F69EE":{n:"Star Fire (28-11-2002) (MP)"}, "C473B222B7C5308D0773326416094272":{n:"Star Fire (28-11-2002) (MP) [a1]"}, "BC6432CBED32C695658514C4EB41D905":{n:"Star Fire (MP) (2002) (PD)"}, "BF5E2079586CB307BF5EB2413E2E61AF":{n:"Star Fire - 1LK Intro (13-11-2002) (TJ)"}, "0890A5B089191F45D0F08DD1E3235687":{n:"Star Fire - 4K Version (25-10-2002) (MP)"}, "D2C305A443DFC49E8430964D7C1BD1B7":{n:"Star Fire - Advice on radar needed (16-10-2002) (MP)"}, "09D19274C20768F842E8FAE84B766ABE":{n:"Star Fire - Animated Patricles (06-10-2002) (MP)"}, "BF9DDC5DD9056633D4AC0DAC8B871DFE":{n:"Star Fire - Cockpit View (10-10-2002) (MP)"}, "EC26FDC87B1D35F1D60EA89CDA4F4DD4":{n:"Star Fire - Crash Scene (04-11-2002) (MP)"}, "BFCABC6995EF42D0B6C06786993DC4D6":{n:"Star Fire - Creating a Universe (09-09-2002) (MP)"}, "86F5E55CA9A9BDE7338A157570828E79":{n:"Star Fire - Creating a Universe (09-09-2002) (MP) [a1]"}, "11CF751BC8173DB105EABD119C5844BA":{n:"Star Fire - Crosshair (12-02-2002) (MP)"}, "06953ED762220DBA63D63930D4AD0CC3":{n:"Star Fire - Eckhard WIP (MP)"}, "40D7CCD460C9B1198238AF6CEEA1737D":{n:"Star Fire - Enemy Mine (2002) (MP)"}, "D79DF06894E3C1585A47C2807332B319":{n:"Star Fire - Explosions! (10-10-2002) (MP)"}, "5E2928F089490017E88E9F9E5A881A25":{n:"Star Fire - Faster Skipping 1 (24-10-2002) (MP)"}, "44560E324FFB30741A483218BA5B4342":{n:"Star Fire - Faster Skipping 2 (24-10-2002) (MP)"}, "562BF02F5031D51C6B53B03972A56B22":{n:"Star Fire - Framework Done (30-10-2002) (MP)"}, "DC6AA0BB21A6E66E80E75BA5EDC5C0DD":{n:"Star Fire - Kernel Done (MP)"}, "9E6FA031ECE07919C816FBA5DC8DE43E":{n:"Star Fire - Meteor Dance (13-11-2002) (MP)"}, "BB9F06B288B5275BC0D38B6731B2526A":{n:"Star Fire - Meteor Dance 2 (18-11-2002) (MP)"}, "551EF75593EC18D078E8F5CC0229E1C4":{n:"Star Fire - New Paulstar WIP (MP)"}, "74CA9BDC91EE387A5BD929B73AEC5C2C":{n:"Star Fire - New Shields (03-04-2003) (MP)"}, "A23FFC86804240CE77134A1C91926685":{n:"Star Fire - Paulstar WIP (MP)"}, "C6CEDB25B7D390B580EA8EDB614B168B":{n:"Star Fire - Radar Completed (22-10-2002) (MP)"}, "5F69453A69F21DC49697A80D2E933491":{n:"Star Fire - Reduced Flickering (06-10-2002) (MP)"}, "2E2885E68FA1045871CE1382B68F6EFC":{n:"Star Fire - Return of the Crosshair (MP)"}, "DA64F33D0521D5C9958E5D2D4434FF95":{n:"Star Fire - Return of the Starfield (MP)"}, "92EDE72ED8F61D255BC58D2F166DC6B6":{n:"Star Fire - Shootable (26-09-2002) (MP)"}, "ED9999911B406DC5F75C850DCC17BDF4":{n:"Star Fire - Shootable (Friendlier Collision Detection) (26-09-2002) (MP)"}, "92C5ABB7A8BB1C3FC66C92BA353A3D21":{n:"Star Fire - Sorting Fixed (MP)"}, "103D4C890C2108CB536372C98D093E5F":{n:"Star Fire - Star Background (MP)"}, "7F73AC39E5E3E13E40FD8AD885561A0F":{n:"Star Fire - Warping Star (13-04-2003) (MP)"}, "FBD6102E17A5C02C6E1911381B7203F9":{n:"Star Fire - Warping!! (10-04-2003) (MP)"}, "BB07F917611CDE42B7D83746EE27147D":{n:"Star Fire - Warping!! (13-04-2003) (MP)"}, "F526D0C519F5001ADB1FC7948BFBB3CE":{n:"Star Fox (1983) (Mythicon)"}, "C541A5F6FC23B40A211196DD78233780":{n:"Star Raiders (1981) (Atari) (Prototype)"}, "CBD981A23C592FB9AB979223BB368CD5":{n:"Star Raiders (1982) (Atari)"}, "C1A83F44137EA914B495FC6AC036C493":{n:"Star Raiders (1982) (Atari) (PAL)"}, "E363E467F605537F3777AD33E74E113A":{n:"Star Ship (1977) (Atari)"}, "7B938C7DDF18E8362949B62C7EAA660A":{n:"Star Ship (1977) (Atari) (4K)"}, "79E5338DBFA6B64008BB0D72A3179D3C":{n:"Star Strike (1983) (M Network)"}, "405F8591B6941CFF56C9B392C2D5E4E5":{n:"Star Strike (1989) (Telegames) (PAL)"}, "AB8D318DA4ADDD39C65B7F9C408DF2A6":{n:"Star Trek (Genesis)",c:1}, "03C3F7BA4585E349DD12BFA7B34B7729":{n:"Star Trek - Strategic Operations Simulator (1983) (Sega)",c:1}, "30F0B49661CFCFD4EC63395FAB837DC3":{n:"Star Trek - Strategic Operations Simulator (1983) (Sega) (PAL)",c:1}, "813985A940AA739CC28DF19E0EDD4722":{n:"Star Voyager (1982) (Imagic)"}, "0ACEB7C3BD13FE048B77A1928ED4267D":{n:"Star Voyager (1982) (Imagic) (PAL)"}, "D912312349D90E9D41A9DB0D5CD3DB70":{n:"Star Voyager (1983) (CCE)"}, "2E7E9C6DCFCCEAFFC6FA73F0D08A402A":{n:"Star Voyager (1983) (CCE) [a]"}, "9D33D31FB1DE58C5460D8A67B57B36DA":{n:"Star Voyager (Genesis)"}, "5336F86F6B982CC925532F2E80AA1E17":{n:"Star Wars - Death Star Battle (1983) (Parker Bros)",c:1}, "CB9B2E9806A7FBAB3D819CFE15F0F05A":{n:"Star Wars - Death Star Battle (1983) (Parker Bros) (PAL)"}, "D44D90E7C389165F5034B5844077777F":{n:"Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype)"}, "2E2ACEF8513EDCCA991E7E5149412E11":{n:"Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (16K)"}, "6DFAD2DD2C7C16AC0FA257B6CE0BE2F0":{n:"Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL)"}, "9D7F04618BB4043F531D087E3AAA7AC8":{n:"Star Wars - Ewok Adventure (1983) (Parker Bros) (Prototype) (PAL) (16K)"}, "C246E05B52F68AB2E9AEE40F278CD158":{n:"Star Wars - Ewok Adventure (Thomas Jentzsch) (Prototype)"}, "C9F6E521A49A2D15DAC56B6DDB3FB4C7":{n:"Star Wars - Jedi Arena (1983) (Parker Bros)",p:1}, "05B45BA09C05BEFA75AC70476829EDA0":{n:"Star Wars - Jedi Arena (1983) (Parker Bros) (PAL)",p:1}, "F4B8A47A95B61895E671C3EC86FFD461":{n:"Star Wars - The Arcade Game (01-03-1984) (Parker Bros) (Prototype)",c:1}, "6651E2791D38EDC02C5A5FD7B47A1627":{n:"Star Wars - The Arcade Game (04-05-1984) (Parker Bros) (Prototype) (8K)",c:1}, "E8A3473BF786CF796D1336D2D03A0008":{n:"Star Wars - The Arcade Game (12-05-1983) (Parker Bros) (Prototype)",c:1}, "1E1290EA102E12D7AC52820961457E2B":{n:"Star Wars - The Arcade Game (12-15-1983) (Parker Bros) (Prototype)",c:1}, "AE2F1F69BB38355395C1C75C81ACC644":{n:"Star Wars - The Arcade Game (12-23-1983) (Parker Bros) (Prototype)",c:1}, "6339D28C9A7F92054E70029EB0375837":{n:"Star Wars - The Arcade Game (1984) (Parker Bros)",c:1}, "6CF054CD23A02E09298D2C6F787EB21D":{n:"Star Wars - The Arcade Game (1984) (Parker Bros) (PAL)",c:1}, "FFC0FF4305DD46B4B459885BD1818E2E":{n:"Star Wars - The Battle of Alderaan (Star Strike Hack)"}, "3C8E57A246742FA5D59E517134C0B4E6":{n:"Star Wars - The Empire Strikes Back (1982) (Parker Bros)"}, "BE060A704803446C02E6F039AB12EB91":{n:"Star Wars - The Empire Strikes Back (1982) (Parker Bros) (PAL)"}, "D69559F9C9DC6EF528D841BF9D91B275":{n:"StarMaster (1982) (Activision)"}, "73C839AFF6A055643044D2CE16B3AAF7":{n:"StarMaster (1982) (Activision) (PAL)"}, "348615FFA30FAB3CEC1441B5A76E9460":{n:"StarMaster (1982) (Activision) (PAL) [fixed]"}, "D62D7D1A974C31C5803F96A8C1552510":{n:"StarMaster (Unknown) (PAL)"}, "1542662F665D2FFAA77B4B897DD2E2AF":{n:"Starfield (V1.0) (2002) (MP)"}, "91D1C82CEAF8AF2ADD3973A3C34BC0CB":{n:"Starfield Demo 1 (20-12-2002) (CT)"}, "68FEB6D6FF63E80DF1302D8547979AEC":{n:"Starfield Demo 2 (20-12-2002) (CT)"}, "0C48E820301251FBB6BCDC89BD3555D9":{n:"Stargate (1984) (Atari)"}, "493DE059B32F84AB29CDE6213964AEEE":{n:"Stargate (1984) (Atari) (PAL)"}, "A3C1C70024D7AABB41381ADBFB6D3B25":{n:"Stargunner (1982) (Telesys)"}, "E5BACF526036D3C8C99DB5B030CF00E7":{n:"Starmaster (Genesis)"}, "C5BAB953AC13DBB2CBA03CD0684FB125":{n:"Stay Frosty (SpiceWare)",c:1}, "1FA86282403FA35D103AB88A9D603C31":{n:"Stay Frosty (SpiceWare) (PAL60)",c:1}, "1619BC27632F9148D8480CD813AA74C3":{n:"Steeple Chase (Thomas Jentzsch)",c:1}, "F75872946E82AD74D48EAE5BC28F5F0E":{n:"Steeplechase (04-15-1980) (Sears) (Prototype)",p:1}, "656DC247DB2871766DFFD978C71DA80C":{n:"Steeplechase (1980) (Sears)",p:1}, "A174CECE06B3ABC0AEC3516913CDF9CC":{n:"Steeplechase (1980) (Sears) (4K)",p:1}, "F1EEECCC4BBA6999345A2575AE96508E":{n:"Steeplechase (1983) (Video Gems) (PAL)",c:1}, "3CDD91E1C28D28E856C0063D602DA166":{n:"Stell-A-Sketch (03-11-1997) (Bob Colbert) (PD)",c:1}, "47AEF18509051BAB493589CB2619170B":{n:"Stell-A-Sketch (Bob Colbert) (PD)",c:1}, "18ED63E3CE5BC3DD2D8BD188B807F1A2":{n:"Stell-A-Sketch (Bob Colbert) (PD) [a1]",c:1}, "0B8D3002D8F744A753BA434A4D39249A":{n:"Stellar Track (1980) (Sears)",c:1}, "23FAD5A125BCD4463701C8AD8A0043A9":{n:"Stone Age (1983) (CCE)"}, "B17B9CC4103844DCDA54F77F44ACC93A":{n:"Stopp die Gangster (1983) (Quelle) (PAL)"}, "F240BA9F8092D2E8A4C7D82C554BF509":{n:"Strahlen der Teufelsvoegel (1983) (Quelle) (PAL)"}, "807A8FF6216B00D52ABA2DFEA5D8D860":{n:"Strat-O-Gems Deluxe (2005) (J. Payson)"}, "EF76EA05655A0B62CB1018C92B9B4B7D":{n:"Strategy X (1983) (Gakken) (PAL)"}, "9333172E3C4992ECF548D3AC1F2553EB":{n:"Strategy X (1983) (Konami)"}, "E10D2C785AADB42C06390FAE0D92F282":{n:"Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros)"}, "516FFD008057A1D78D007C851E6EFF37":{n:"Strawberry Shortcake - Musical Match-Ups (1983) (Parker Bros) (PAL)"}, "8A6C84F481ACF42ABCB78BA5064AD755":{n:"Street Racer (128-in-1 Junior Console) (PAL) (4K)",p:1}, "396F7BC90AB4FA4975F8C74ABE4E81F0":{n:"Street Racer (1977) (Atari)",p:1}, "6FF4156D10B357F61F09820D03C0F852":{n:"Street Racer (1977) (Atari) (4K)",p:1}, "E12E32DEE68201B6765FCD0ED54D6646":{n:"Street Racer (1977) (Atari) (PAL)",p:1}, "7B3CF0256E1FA0FDC538CAF3D5D86337":{n:"Stronghold (1983) (CommaVid)"}, "C3BBC673ACF2701B5275E85D9372FACF":{n:"Stunt Cycle (07-21-1980) (Atari) (Prototype)"}, "D7759FA91902EDD93F1568A37DC70CDB":{n:"Stunt Cycle (1980) (Atari) (Prototype) (4K)"}, "ED0AB909CF7B30AFF6FC28C3A4660B8E":{n:"Stunt Man (1983) (Panda)"}, "5AF9CD346266A1F2515E1FBC86F5186A":{n:"Sub-Scan (1982) (Sega)"}, "B095009004DF341386D22B2A3FAE3C81":{n:"Sub-Scan (Unknown) (PAL)"}, "F3F5F72BFDD67F3D0E45D097E11B8091":{n:"Submarine Commander (1982) (Sears)"}, "93C52141D3C4E1B5574D072F1AFDE6CD":{n:"Subterranea (1983) (Imagic)"}, "38DE7B68379770B9BD3F7BF000136EB0":{n:"Subterranea (1983) (Imagic) (PAL)"}, "D8E4C8E2D210270CD1E0F6D1B4582B91":{n:"Subterranea (1983) (Imagic) (PAL) [a]"}, "4AB4AF3ADCDAE8CDACC3D06084FC8D6A":{n:"Sucky Zepplin (Nick Bensema) (PD)"}, "CFF578E5C60DE8CAECBEE7F2C9BBB57B":{n:"Suicide Adventure (George Veeder) (Hack)"}, "E4C666CA0C36928B95B13D33474DBB44":{n:"Suicide Mission (1982) (Arcadia)",c:1}, "EB92193F06B645DF0B2A15D077CE435F":{n:"Suicide Mission (1982) (Arcadia) (PAL)",c:1}, "CD98BE8A48EBF610C9609A688B9C57F2":{n:"Suicide Mission (1982) (Arcadia) (Prototype)",c:1}, "753375D183C713CFA0AA7298D1F3067B":{n:"Suicide Mission (1982) (Arcadia) [a]",c:1}, "463DD4770506E6C0EF993A40C52C47BE":{n:"Suicide Mission (Preview) (1982) (Arcadia)",c:1}, "B4F05E544834D0238A0C263491775EDF":{n:"Suicide Mission (Preview) (1982) (Arcadia) (PAL)",c:1}, "45027DDE2BE5BDD0CAB522B80632717D":{n:"Summer Games (1987) (Epyx)"}, "12BCA8305D5AB8EA51FE1CFD95D7AB0E":{n:"Summer Games (1987) (Epyx) (PAL)"}, "4F2D47792A06DA224BA996C489A87939":{n:"Super Action Pak - Pitfall, Barnstorming, Grand Prix, Laser Blast (1988) (HES) (PAL)"}, "7ADBCF78399B19596671EDBFFC3D34AA":{n:"Super Baseball (1988) (Atari)"}, "0751F342EE4CF28F2C9A6E8467C901BE":{n:"Super Baseball (1988) (Atari) (PAL)"}, "FAED2EF6B44894F8C83F2B50891C35C6":{n:"Super Baseball (CCE)"}, "1C85C0FC480BBD69DC301591B6ECB422":{n:"Super Box (CCE)"}, "8885D0CE11C5B40C3A8A8D9ED28CEFEF":{n:"Super Breakout (1982 - 1981) (Atari)",p:1}, "EE4C186123D31A279ED7A84D3578DF23":{n:"Super Breakout (1982 - 1981) (Atari) (PAL)",p:1}, "0AD9A358E361256B94F3FB4F2FA5A3B1":{n:"Super Breakout (1982 - 1981) (Atari) [a]",p:1}, "9D37A1BE4A6E898026414B8FEE2FC826":{n:"Super Challenge Baseball (1982) (M Network)"}, "DAB844DEED4C752632B5E786B0F47999":{n:"Super Challenge Baseball (208 in 1) (Unknown) (PAL)"}, "1D6ED6FE9DFBDE32708E8353548CBB80":{n:"Super Challenge Baseball (Jone Yuan)"}, "E275CBE7D4E11E62C3BFCFB38FCA3D49":{n:"Super Challenge Football (1982) (M Network)"}, "FEBA8686FD0376015258D1152923958A":{n:"Super Circus (Unknown) (PAL)"}, "C29F8DB680990CB45EF7FEF6AB57A2C2":{n:"Super Cobra (1982) (Parker Bros)"}, "D326DB524D93FA2897AB69C42D6FB698":{n:"Super Cobra (1982) (Parker Bros) (PAL)"}, "5F7DE62A408B9DE3A1168898298FD31D":{n:"Super Cobra (Genesis)"}, "C7900A7FE95A47EEF3B325072AD2C232":{n:"Super Congo Bongo (2003) (Larry Petit) (Hack)"}, "638CC82EA96F67674595BA9AE05DA6C6":{n:"Super Ferrari (Rainbow Vision) (PAL)"}, "09ABFE9A312CE7C9F661582FDF12EAB6":{n:"Super Football (1988) (Atari)"}, "262CCB882FF617D9B4B51F24AEE02CBE":{n:"Super Football (1988) (Atari) (PAL)"}, "2447E17A4E18E6B609DE498FE4AB52BA":{n:"Super Futebol (CCE)",c:1}, "2F0A8BB4E18839F9B1DCAA2F5D02FD1D":{n:"Super Futebol (CCE) [a]",c:1}, "C08D0CEE43077D3055FEBB00E5745C1D":{n:"Super Hit Pak - River Raid, Sky Jinks, Grand Prix, Fishing Derby, Checkers (HES) (PAL)"}, "08D1B6D75206EDB999252CAF542A2C7F":{n:"Super Home Run (2003) (Larry Petit) (Hack)"}, "645BF7F9146F0E4811FF9C7898F5CD93":{n:"Super Kung-Fu (1983) (Xonox) (PAL)"}, "3B2C32FCD331664D037952BCAA62DF94":{n:"Super Kung-Fu (1983) (Xonox) (PAL) [a]"}, "0E7E73421606873B544E858C59DC283E":{n:"Super Soccer (Digivision)",c:1}, "3E7D10D0A911AFC4B492D06C99863E65":{n:"Super Tenis (VGS)"}, "53B66F11F67C3B53B2995E0E02017BD7":{n:"Super Tennis (1983) (CCE)"}, "517923E655755086A3B72C0B17B430E6":{n:"Super Tennis (Tron)"}, "CBC373FBCB1653B4C56BFABBA33EA50D":{n:"Super Voleyball (CCE)"}, "BDECC81F740200780DB04A107C3A1EBA":{n:"Super-Cowboy beim Rodeo (1983) (Quelle) (PAL)"}, "CC2973680C150886CCE1ED8693C3ACA2":{n:"Super-Cowboy beim Rodeo (1983) (Quelle) (PAL) (4K)"}, "2B27EB194E13F3B38D23C879CC1E3ABF":{n:"Super-Ferrari (1983) (Quelle) (PAL)"}, "85502D69FE46B7F54EF2598225678B47":{n:"Super-Ferrari (Jone Yuan)"}, "724613EFFAF7743CBCD695FAB469C2A8":{n:"Super-Ferrari (Unknown)"}, "4565C1A7ABCE773E53C75B35414ADEFD":{n:"Supercharger BIOS (1982) (Arcadia)"}, "A9531C763077464307086EC9A1FD057D":{n:"Superman (1979) (Atari)"}, "3619786F6A32EFC1E4A262D5ACA8A070":{n:"Superman (1979) (Atari) (8K)"}, "DBB10B904242FCFB8428F372E00C01AF":{n:"Superman (1979) (Atari) (PAL)"}, "FD10915633AEA4F9CD8B518A25D62B55":{n:"Superman (1979) (Atari) (PAL) [a]"}, "5DE8803A59C36725888346FDC6E7429D":{n:"Superman (1979) (Atari) [fixed]"}, "149B543C917C180A1B02D33C12415206":{n:"Superman (1983) (CCE)"}, "CCB807EB79B0ED0F5FDC460445EF703A":{n:"Superman (Stunt_Cycle_Rules!) (Hack)"}, "6FAC680FC9A72E0E54255567C72AFE34":{n:"Superman (Unknown) (PAL)"}, "169D4C7BD3A4D09E184A3B993823D048":{n:"Superman (Unknown) (PAL) [a]"}, "AEC9B885D0E8B24E871925630884095C":{n:"Surf's Up (1983) (Amiga) (Prototype)"}, "A2170318A8EF4B50A1B1D38567C220D6":{n:"Surf's Up (1983) (Amiga) (Prototype) [a]"}, "C20F15282A1AA8724D70C117E5C9709E":{n:"Surfer's Paradise (1983) (Video Gems) (PAL)"}, "59B70658F9DD0E2075770B07BE1A35CF":{n:"Surfer's Paradise (Thomas Jentzsch)"}, "4D7517AE69F95CFBC053BE01312B7DBA":{n:"Surround (1977) (Atari)"}, "31D08CB465965F80D3541A57EC82C625":{n:"Surround (1977) (Atari) (4K)"}, "52A0003EFB3B1C49FCDE4DBC2C685D8F":{n:"Surround (1977) (Atari) (4K) [a]"}, "C370C3268AD95B3266D6E36FF23D1F0C":{n:"Surround (1977) (Atari) (PAL)"}, "A60598AD7EE9C5CCAD42D5B0DF1570A1":{n:"Surround (32 in 1) (1988) (Atari) (PAL)"}, "5C86E938E0845B9D61F458539E9A552B":{n:"Surround (32 in 1) (1988) (Atari) (PAL) (4K)"}, "D89FEDDED0436FDEDA7C3C37E2FB7CF1":{n:"Surround (Unknown) (PAL) (4K)"}, "4C462B2B6FB0A19A1437EB2C3DC20783":{n:"Survival Island (1 of 3) (1983) (Arcadia)"}, "B6E40BCE550672E5495A8CDDE7075B8B":{n:"Survival Island (1 of 3) (1983) (Arcadia) (PAL)"}, "045035F995272EB2DEB8820111745A07":{n:"Survival Island (1983) (Arcadia)"}, "84DB818CD4111542A15C2A795369A256":{n:"Survival Island (1983) (Arcadia) (PAL)"}, "691D67910B08B63DE8631901D1887C1F":{n:"Survival Island (1983) (Arcadia) [a]"}, "B31DC989F594764EACFA7931CEAD0050":{n:"Survival Island (2 of 3) (1983) (Arcadia)"}, "277C7281AC945B8331E2E6FCAD560C11":{n:"Survival Island (2 of 3) (1983) (Arcadia) (PAL)"}, "4A9009620038F7F30AAEB2A00AE58FDE":{n:"Survival Island (3 of 3) (1983) (Arcadia)"}, "76C685D1A60C0107AA54A772113A2972":{n:"Survival Island (3 of 3) (1983) (Arcadia) (PAL)"}, "59E53894B3899EE164C91CFA7842DA66":{n:"Survival Run (1983) (Data Age) (Prototype)"}, "85E564DAE5687E431955056FBDA10978":{n:"Survival Run (1983) (Milton Bradley)",c:1}, "C7600D72247C5DFA1EC1A88D23E6C85E":{n:"Sweat! - The Decathlon Game (1 of 3) (1983) (Arcadia) (Prototype)",p:1}, "E51C23389E43AB328CCFB05BE7D451DA":{n:"Sweat! - The Decathlon Game (1983) (Arcadia) (Prototype)",p:1}, "5EC73AC7D2AC95AC9530C6D33E713D14":{n:"Sweat! - The Decathlon Game (2 of 3) (1983) (Arcadia) (Prototype)",p:1}, "1E060A8025512AD2127E3DA11E212CCC":{n:"Sweat! - The Decathlon Game (3 of 3) (1983) (Arcadia) (Prototype)",p:1}, "528400FAD9A77FD5AD7FC5FDC2B7D69D":{n:"Sword of Saros (1983) (Arcadia)"}, "8B7CA29A55432F886CEE3D452FB00481":{n:"Sword of Saros (1983) (Arcadia) (PAL)"}, "545048CCB045F9EFC6CF2B125CD0DFA8":{n:"Sword of Saros (1983) (Arcadia) [a]"}, "5AEA9974B975A6A844E6DF10D2B861C4":{n:"SwordQuest - EarthWorld (1982) (Atari)"}, "A875F0A919129B4F1B5103DDD200D2FE":{n:"SwordQuest - EarthWorld (1982) (Atari) (PAL)"}, "05EBD183EA854C0A1B56C218246FBBAE":{n:"SwordQuest - EarthWorld (1982) (Atari) [a]"}, "F9D51A4E5F8B48F68770C89FFD495ED1":{n:"SwordQuest - FireWorld (1982) (Atari)"}, "BF976CF80BCF52C5F164C1D45F2B316B":{n:"SwordQuest - FireWorld (1982) (Atari) (PAL)"}, "3882224ADBD0CA7C748B2A1C9B87263E":{n:"SwordQuest - FireWorld (1982) (Atari) (PAL) [a]"}, "BC5389839857612CFABEB810BA7EFFDC":{n:"SwordQuest - WaterWorld (1983) (Atari)"}, "87662815BC4F3C3C86071DC994E3F30E":{n:"Swordfight (1983) (Intellivision)"}, "D0B9F705AA5F61F47A748A66009AE2D2":{n:"Synthcart (14-01-2002) (Paul Slocum)",c:1}, "2C2AEA31B01C6126C1A43E10CACBFD58":{n:"Synthcart (2002) (Paul Slocum)",c:1}, "8B556C3D9CA8E5E6E665BD759B93FFAE":{n:"Synthcart (2002) (Paul Slocum) (PAL) [!]",c:1}, "896EC58F26E930E02F5E4F046602C3A1":{n:"Synthcart (Beta) (2002) (Paul Slocum)",c:1}, "8933976F2029C0D8492EBD8F4EB21492":{n:"Synthcart Plus (09-02-2003) (Paul Slocum)"}, "294762000E853B4319F9991C1CED5DFC":{n:"T.F. Space Invaders (Hack)"}, "BECD908F9D7BB361982C3DC02D6475C6":{n:"THX-1138 (Kyle Pittman) (Hack)"}, "6FFC95108E5ADD6F9B8ABCAF330BE835":{n:"TP Bug (Charles Morgan) (Hack)"}, "FB27AFE896E7C928089307B32E5642EE":{n:"TRON - Deadly Discs (1982) (M Network)"}, "9E5007131695621D06902AB3C960622A":{n:"Tac Scan (1983) (Sega) [h1]",p:1,c:1}, "D45EBF130ED9070EA8EBD56176E48A38":{n:"Tac-Scan (1982) (Sega)",p:1,c:1}, "06E5DC181A8EDA1C31CC7C581C68B6EF":{n:"Tac-Scan (Unknown) (PAL)",c:1}, "C77D3B47F2293E69419B92522C6F6647":{n:"Tank Brigade (1983) (Panda)"}, "AD8072675109D13FDD31A2E0403D5CFF":{n:"Tank City (Funvision)"}, "FA6FE97A10EFB9E74C0B5A816E6E1958":{n:"Tanks But No Tanks (1983) (ZiMAG)"}, "082FDC8BD47FEF01482CE5883C4FFDB8":{n:"Tanks DX (Charles Morgan) (Hack)"}, "1A613CE60FC834D4970E1E674B9196B3":{n:"Tanks War (1983) (Home Vision) (PAL)"}, "DE3D0E37729D85AFCB25A8D052A6E236":{n:"Tapeworm (1982) (Spectravision)",c:1}, "8ED73106E2F42F91447FB90B6F0EA4A4":{n:"Tapeworm (1982) (Spectravision) (PAL)",c:1}, "33CAC5E767A534C95D292B04F439DC37":{n:"Tapeworm (Jone Yuan)"}, "C0D2434348DE72FA6EDCC6D8E40F28D7":{n:"Tapper (1984) (Sega)"}, "2D6741CDA3000230F6BBDD5E31941C01":{n:"Targ (1983) (CBS Electronics) (Prototype)"}, "3D6FC7A19BE76D808AA233415CB583FC":{n:"Target Practice (1983) (CCE)"}, "7DD9C5284422F729066AB22A284C8283":{n:"Target Practice (1983) (CCE) [a]"}, "0C35806FF0019A270A7ACAE68DE89D28":{n:"Task Force (1987) (Froggo)"}, "A1EAD9C181D67859AA93C44E40F1709C":{n:"Tax Avoiders (1982) (American Videogame)"}, "360BA640F6810EC902B01A09CC8AB556":{n:"Taz (06-15-1983) (Atari) (Prototype) (PAL)"}, "B31F178AA0D569CCCAC7959F84E0A724":{n:"Taz (07-13-1983) (Atari) (Prototype)"}, "9A01115206F32EB0B539C7E5A47CCAFA":{n:"Taz (07-15-1983) (Atari) (Prototype)"}, "7574480AE2AB0D282C887E9015FDB54C":{n:"Taz (1983) (Atari)"}, "0D09CFF0D28033C02C3290EDFC3A5CEA":{n:"Taz (1983) (Atari) (Prototype)"}, "76809EB1EE0DB8A318308A5CDDA0F4E2":{n:"Taz (1983) (Atari) (Prototype) [a]"}, "4702D8D9B48A332724AF198AEAC9E469":{n:"Taz (1983) (Atari) [a]"}, "AB60EA7B707C58D356CAD858EB18DB43":{n:"Tazer (John K. Harvey)"}, "8C2FA33048F055F38358D51EEFE417DB":{n:"Teddy Apple (1983) (Home Vision) (PAL)",c:1}, "3D7AAD37C55692814211C8B590A0334C":{n:"Telepathy (1983) (Atari) (Prototype)"}, "AE97CF8ED21F4154B4360A3CF6C95C5E":{n:"Teleterm 2600 (John K. Harvey) (PD)"}, "203B1EFC6101D4B9D83BB6CC1C71F67F":{n:"Teller-Jonglieren! (1983) (Quelle) (PAL)",c:1}, "C830F6AE7EE58BCC2A6712FB33E92D55":{n:"Tempest (01-05-1984) (Atari) (Prototype)"}, "42CDD6A9E42A3639E190722B8EA3FC51":{n:"Tennis (1981) (Activision)"}, "961112B74A920A5242E233480326C356":{n:"Tennis (1981) (Activision) (16K)"}, "ACA09FFEA77174B148B96B205109DB4D":{n:"Tennis (1981) (Activision) (4K)"}, "74EBACA101CC428CF219F15DDA84B6F8":{n:"Tennis (1981) (Activision) (8K)"}, "A5C96B046D5F8B7C96DAAA12F925BEF8":{n:"Tennis (1981) (Activision) (PAL)"}, "CA7F166A94EED1A349DEC6D6A358BCAD":{n:"Tennis (1981) (Activision) (PAL) (4K)"}, "73EFA9F3CBE197F26E0FB87132829232":{n:"Tennis (1983) (CCE) (4K)"}, "04B488D4EEF622D022A0021375E7E339":{n:"Tennis (1983) (Home Vision) (PAL) (4K)"}, "A3F8AEBB38182749CB8DA85CFBC63D7C":{n:"Tennis (208 in 1) (Unknown) (PAL) (Hack)"}, "16E04823887C547DC24BC70DFF693DF4":{n:"Tennis (32 in 1) (1988) (Atari) (PAL)"}, "30685B9B6EBD9BA71536DD7632A1E3B6":{n:"Tennis (Dactari)"}, "736388D73198552D77D423962000006F":{n:"Tennis (Dactari) (4K)"}, "1F5A2927A0B2FAF87540B01D9D7D7FD1":{n:"Tennis (Pet Boat) (PAL)"}, "61E0F5E1CC207E98704D0758C68DF317":{n:"Tennis (Star Game)"}, "A3873D7C544AF459F40D58DFCFB78887":{n:"Tennis (Unknown)"}, "6697F177847C70505824422E76AAD586":{n:"Tennis (Unknown) (PAL) (4K)"}, "E3ED4BA3361756970F076E46E9CAD1D2":{n:"Tennis (Unknown) (PAL) (4K) [a]"}, "20AE62FB69C6CC6E8098CCA8CD080487":{n:"Tennis (Zirok)"}, "67631EA5CFE44066A1E76DDCB6BCB512":{n:"Termool (Unknown) (PAL)"}, "05C60458EC69E7FE8B1BE973852D84F1":{n:"Test (1996) (J.V. Matthews) (PD)"}, "F0631C6675033428238408885D7E4FDE":{n:"Test Cart (2002) (Paul Slocum)",c:1}, "B0E1EE07FBC73493EAC5651A52F90F00":{n:"Tetris 2600 (Colin Hughes)",c:1}, "CAE8F83C06831EC7BB6A3C07E98E9342":{n:"Tetris 2600 (Colin Hughes) [o1]",c:1}, "5EEB81292992E057B290A5CD196F155D":{n:"Texas Chainsaw Massacre, The (1983) (Wizard Video)"}, "3316EE2F887E9CB9B54DD23C5B98C3E2":{n:"Texas Golf (miniature Gold Hack)"}, "4476C39736090DABAC09F6CAF835FC49":{n:"Text Screen (25-01-2003) (AD)"}, "3B64A00CE147C3C29F7F8F8E531D08D8":{n:"This Planet Sucks (16K) (Greg Troutman)"}, "5FB71CC60E293FE10A5023F11C734E55":{n:"This Planet Sucks (Fix) (27-12-2002) (Greg Troutman)"}, "A98B649912B6CA19EAF5C2D2FAF38562":{n:"This Planet Sucks (Greg Troutman) (PAL) [!]"}, "DFE6AA7443BB813CEFA35A4CF4887422":{n:"This Planet Sucks (Greg Troutman) [a1]"}, "0ACAF71E60B89F6B6EAB63DB6AB84510":{n:"This Planet Sucks (Greg Troutman) [a2]"}, "225522777DC7155627808BDE0C1D0EF0":{n:"This Planet Sucks Demo 1 (Greg Troutman) (PD)"}, "8530CAAAF40ACBDCD118C282B5F8A37A":{n:"This Planet Sucks Demo 2 (Greg Troutman) (PD)"}, "7F790939F7EAA8C47A246C4283981F84":{n:"This Planet Sucks Demo 3 (Greg Troutman) (PD)"}, "E56DA674188BA2F02C7A0A343A01236F":{n:"This Planet Sucks Demo 4 (Greg Troutman) (PD)"}, "65C6406F5AF934590097C8C032EBB482":{n:"Three Hugger (Pave Demo) (20-12-2002) (Billy Eno)"}, "E63A87C231EE9A506F9599AA4EF7DFB9":{n:"Threshold (1982) (Tigervision)"}, "67684A1D18C85FFA5D82DAB48FD1CB51":{n:"Threshold (1982) (Tigervision) (PAL)"}, "346555779A2D51B48833463B5433472F":{n:"Thrust (V0.1) (2000) (TJ)"}, "1442D1B35A6478FBA22AE7DD1FCB5634":{n:"Thrust (V0.2) (2000) (TJ)"}, "BA3B0EEBCCC7B791107DE5B4ABB671B4":{n:"Thrust (V0.9) (2000) (TJ)"}, "041B5E56BBC650DB574BD8DB3FAE2696":{n:"Thrust (V1.0) (2000) (TJ)"}, "98FA3AD778A668A79449350DE4B3B95B":{n:"Thrust (V1.1) (2000) (TJ)"}, "FC668A2251DD79CBD903D4FA0E558F96":{n:"Thrust (V1.1) (2000) (TJ) [a1]"}, "E1E09E2F280E8E142121A377D0DC1B46":{n:"Thrust (V1.21) (2000) (TJ)"}, "DE7BCA4E569AD9D3FD08FF1395E53D2D":{n:"Thrust (V1.22) (2000) (TJ)"}, "CF507910D6E74568A68AC949537BCCF9":{n:"Thunderground (1983) (Sega)",c:1}, "1428029E762797069AD795CE7C6A1A93":{n:"Thunderground (Unknown) (PAL)",c:1}, "C032C2BD7017FDFBBA9A105EC50F800E":{n:"Thwocker (04-09-1984) (Activision) (Prototype)"}, "79D6F61DA3C64688AC8E075667F8A39F":{n:"Tie-Fighters (MP)"}, "7576DD46C2F8D8AB159D97E3A3F2052F":{n:"Time Machine (1983) (Goliath) (PAL)"}, "FC2104DD2DADF9A6176C1C1C8F87CED9":{n:"Time Pilot (1983) (Coleco)"}, "4E99EBD65A967CABF350DB54405D577C":{n:"Time Pilot (1983) (Coleco) [b1]"}, "5DB9E5BF663CAD6BF159BC395F6EAD53":{n:"Time Race (1983) (Goliath) (PAL)"}, "71F09F128E76EB14E244BE8F44848759":{n:"Time Race (Funvision) (PAL)"}, "00EAEE22034AFF602F899B684C107D77":{n:"Time Race (Rainbow Vision) (PAL)"}, "EFB47D70B2965CE689E2C5757616B286":{n:"Time Test Demo (Eckhard Stolberg) (PAL) (PD)"}, "D6D1DDD21E9D17EA5F325FA09305069C":{n:"Time Warp (1982) (Funvision) (PAL)"}, "BC3057A35319AAE3A5CD87A203736ABE":{n:"Time Warp (1983) (CCE)"}, "619DE46281EB2E0ADBB98255732483B4":{n:"Time Warp (Unknown)"}, "6D9AFD70E9369C2A6BFF96C4964413B7":{n:"Time Warp (Unknown) (PAL)"}, "B879E13FD99382E09BCAF1D87AD84ADD":{n:"Time Warp (Zellers)"}, "FB09EE4CCD47AE74A3C314F0D8A40344":{n:"Titans (SnailSoft)"}, "12123B534BDEE79ED7563B9AD74F1CBD":{n:"Title Match Pro Wrestling (1987) (Absolute)"}, "153F40E335E5CB90F5CE02E54934AB62":{n:"Title Match Pro Wrestling (1987) (Absolute) (PAL)"}, "DA6465A34D2E44D26AA9A2A0CD1BCE4D":{n:"Title Match Pro Wrestling (1987) (Absolute) [a]"}, "784176346E9422733D55C427230E5BAD":{n:"Title Match Pro Wrestling (1989) (Activision)"}, "3B9480BB6FB1E358C9C0A64E86945AEE":{n:"Title Match Pro Wrestling (2002) (Skyworks)"}, "DE61A0B171E909A5A4CFCF81D146DBCB":{n:"Tom Boy (Rainbow Vision) (PAL)"}, "ECE908D77AB944F7BAC84322B9973549":{n:"Tom Boy (Unknown) (PAL60)"}, "D85F1E35C5445AC898746719A3D93F09":{n:"Tom's Eierjagd (1983) (Quelle) (PAL)"}, "C05F367FA4767CEB27ABADF0066DF7F4":{n:"TomInv (31-07-2001) (TJ)"}, "32DCD1B535F564EE38143A70A8146EFE":{n:"Tomarc the Barbarian (1983) (Xonox)"}, "8BC0D2052B4F259E7A50A7C771B45241":{n:"Tomarc the Barbarian (1983) (Xonox) [a]"}, "BE2870A0120FD28D25284E9CCDCBDC99":{n:"Tomb Raider 2600 [REV 01] (Montezuma's Revenge Hack)"}, "E0221C95AA657F5764EEEB64C8429258":{n:"Tomb Raider 2600 [REV 02] (Montezuma's Revenge Hack)"}, "5B574FAA56836DA0866BA32AE32547F2":{n:"Tomb Raider 2600 [REV 03] (Montezuma's Revenge Hack)"}, "3AC6C50A8E62D4CE71595134CBD8035E":{n:"Tomcat (1988) (Absolute)"}, "155FA7F479DCBA3B10B1494E236D6010":{n:"Tomcat (2002) (Skyworks) (PAL)"}, "FA2BE8125C3C60AB83E1C0FE56922FCB":{n:"Tooth Protectors (1983) (DSD-Camelot)",c:1}, "E0B24C3F40A46CDA52E29835AB7AD660":{n:"Top Gun (1983) (Quelle) (PAL)"}, "01ABCC1D2D3CBA87A3AA0EB97A9D7B9C":{n:"Topy (Jone Yuan)"}, "0AA208060D7C140F20571E3341F5A3F8":{n:"Towering Inferno (1982) (U.S. Games)",c:1}, "15FE28D0C8893BE9223E8CB2D032E557":{n:"Towering Inferno (208 in 1) (Unknown) (PAL)",c:1}, "F39E4BC99845EDD8621B0F3C7B8C4FD9":{n:"Toyshop Trouble (AtariAge)",p:1}, "6AE4DC6D7351DACD1012749CA82F9A56":{n:"Track and Field (1984) (Atari)"}, "66706459E62514D0C39C3797CBF73FF1":{n:"Treasure Below (1983) (Video Gems) (PAL)"}, "81414174F1816D5C1E583AF427AC89FC":{n:"Treasure Below (Thomas Jentzsch)"}, "B86A12E53AB107B6CAEDD4E0272AA034":{n:"Treasure Hunting (Funvision)"}, "1BB91BAE919DDBD655FA25C54EA6F532":{n:"Treasure Island (Suntek) (PAL)"}, "D6A44277C3EB4F9D039185E0ECF7BFA6":{n:"Trick (1997) (Eckhard Stolberg)"}, "0CC8224FF1EDFE458E8629E9E5FE3F5B":{n:"Trick 12 (2001) (TJ)"}, "24DF052902AA9DE21C2B2525EB84A255":{n:"Trick Shot (1982) (Imagic)",c:1}, "097936B07E0E0117B9026AE6835EB168":{n:"Trick Shot (1982) (Imagic) (PAL)",c:1}, "DCA90EA1084A2FDBE300D7178CA1A138":{n:"Trick Shot (1982) (Imagic) (PAL) [a]",c:1}, "8F613EA7C32A587D6741790E32872DDD":{n:"Troll Demo (PD)"}, "E7A758BB0B43D0F7004E92B9ABF4BC83":{n:"Troll's Adventure (Hack)"}, "DF3E6A9B6927CF59B7AFB626F6FD7EEA":{n:"Tuby Bird (208 in 1) (Unknown) (PAL)"}, "E957EB4612D6BD5940D3492DFA749668":{n:"Tunnel Demo (27-03-2003) (CT)"}, "A14D8A388083C60283E00592B18D4C6C":{n:"Tunnel Demo (28-03-2003) (AD)"}, "18D26111CEF66DFF0C8AF8CF0E117843":{n:"Tunnel Demo (Cycling Colours 2) (29-03-2003) (AD)"}, "265A85F66544EAF95FDA06C3D9E48ABF":{n:"Tunnel Demo (Cycling Colours) (29-03-2003) (AD)"}, "AE047E9468BDA961D8E9E9D8FF52980F":{n:"Tunnel Demo (Red Spiral) (30-03-2003) (AD)"}, "D8B2C81CEA5AF04F795EB3DC6573D72B":{n:"Tunnel Demo 2 (27-03-2003) (CT)"}, "B2737034F974535F5C0C6431AB8CAF73":{n:"Tunnel Runner (1983) (CBS Electronics)"}, "7648E72A5B5899076688DF18A1DDCF72":{n:"Tunnel Runner (1983) (CBS Electronics) (Prototype)"}, "EFEFC02BBC5258815457F7A5B8D8750A":{n:"Tunnel Runner (1983) (CBS Electronics) [a]"}, "D9AB6B67A17DA51E5AD13717E93FA2E2":{n:"Turbo (Coleco) Prototype Fake v0.1 (TJ)"}, "DD4F4E0FBD81762533E39E6F5B55BB3A":{n:"Turbo WIP (TJ)"}, "7A5463545DFB2DCFDAFA6074B2F2C15E":{n:"Turmoil (1982) (20th Century Fox)"}, "46258BD92B1F66F4CB47864D7654F542":{n:"Turmoil (Zellers)"}, "085322BAE40D904F53BDCC56DF0593FC":{n:"Tutankham (1983) (Parker Bros)"}, "66C2380C71709EFA7B166621E5BB4558":{n:"Tutankham (1983) (Parker Bros) (PAL)"}, "6FC27A9233FC69D28D3F190B4FF80F03":{n:"UFO #6 (Charles Morgan) (Hack)"}, "6BB09BC915A7411FE160D0B2E4D66047":{n:"UFO (32 in 1) (1988) (Atari) (PAL)"}, "B290C2B139344FCFF5B312C71B9AC3B2":{n:"UFO (32 in 1) (1988) (Atari) (PAL) (4K)"}, "CA50CC4B21B0155255E066FCD6396331":{n:"UFO Patrol (Suntek) (PAL)",c:1}, "1278F74CA1DFAA9122DF3ECA3C5BCAAD":{n:"Ungeheuer der Tiefe (Quelle) (PAL)"}, "81A010ABDBA1A640F7ADF7F84E13D307":{n:"Universal Chaos (1989) (Telegames)",c:1}, "E020F612255E266A8A6A9795A4DF0C0F":{n:"Universal Chaos (1989) (Telegames) (PAL)"}, "5F950A2D1EB331A1276819520705DF94":{n:"Unknown 20th Century Fox Game (1983) (20th Century Fox) (Prototype)",c:1}, "841B7BC1CAD05F5408302308777D49DC":{n:"Unknown Activision Game #1 (10-22-1982) (Activision) (Prototype)"}, "EE681F566AAD6C07C61BBBFC66D74A27":{n:"Unknown Activision Game #1 (10-29-1982) (Activision) (Prototype)"}, "8055B9C2622136FD91EDFEA6DF642DAF":{n:"Unknown Activision Game #1 (1983) (Activision) (Prototype) (PAL)"}, "700A786471C8A91EC09E2F8E47F14A04":{n:"Unknown Activision Game #2 (1983) (Activision) (Prototype)"}, "06B0194CE992584C365278E0D7323279":{n:"Unknown Activision Game #2 (Prototype) (PAL)"}, "73E66E82AC22B305EB4D9578E866236E":{n:"Unknown Datatech Game (Jone Yuan)"}, "C3205E3707F646E1A106E09C5C49C1BF":{n:"Unknown Title (bin00003 (200206)) (PD)"}, "3C3A2BB776DEC245C7D6678B5A56AC10":{n:"Unknown Title (bin00003) (PD)"}, "B00088418FC891F3FAA3D4DDDE6ACE94":{n:"Unknown Title (bin00007 (200102)) (PD)"}, "143918368F4F4DFFF90999188C0197C9":{n:"Unknown Title (bin00016 (200110)) (PD)"}, "4DCC7E7C2EC0738E26C817B9383091AF":{n:"Unknown Title (bin00026 (200110)) (PD)"}, "C150C76CBDE2C9B5A97EB5399D46C64F":{n:"Unknown Title (xxx00000 (200203)) (PD)"}, "A499D720E7EE35C62424DE882A3351B6":{n:"Up 'n Down (1984) (Sega)"}, "C6556E082AAC04260596B4045BC122DE":{n:"Vanguard (1982) (Atari)"}, "3CAA902AC0CE4509308990645876426A":{n:"Vanguard (1982) (Atari) (PAL)"}, "9D0BEFA555F003069A21D2F6847AD962":{n:"Vanguard (1982) (Atari) (PAL) [a]"}, "88D7B6B3967DE0DB24CDAE1C7F7181BD":{n:"Vanguard (1982) (Atari) (Prototype)"}, "7EF74879D7CB9FA0EF161B91AD55B3BB":{n:"Vanguard (CCE)"}, "F9660EBED66FEE8BDFDF07B4FAA22941":{n:"Vanguard (VGS)"}, "787EBC2609A31EB5C57C4A18837D1AEE":{n:"Vault Assault (19xx) (Prescott)"}, "D08FCCFBEBAA531C4A4FA7359393A0A9":{n:"Venetian Blinds Demo (1982) (Activision)"}, "FB884FFD89013331A6F01AE3F6ABD214":{n:"Venetian Blinds Demo (1982) (Activision) (PAL)"}, "39DA69FF9833F8C143F03B6E0E7A996B":{n:"Ventrra Invaders 2002 (Charles Morgan) (Hack)"}, "345758747B893E4C9BDDE8877DE47788":{n:"Venture (1982) (CBS Electronics) (PAL)",c:1}, "3E899EBA0CA8CD2972DA1AE5479B4F0D":{n:"Venture (1982) (Coleco)",c:1}, "82DE957D155FC041FC6AFB8315A28550":{n:"Venture (1982) (Coleco) (Prototype)"}, "C63A98CA404AA5EE9FCFF1DE488C3F43":{n:"Venture (1987) (Atari)",c:1}, "7CA7A471D70305C673FEDD08174A81E8":{n:"Venture II (2001) (Tim Snider)",c:1}, "6CD1DC960E3E8D5C5E0FBE67AB49087A":{n:"Vertical Playfield Demo 1 (PD)"}, "EA6D40DB5498D6386571A76DF448AA4C":{n:"Vertical Playfield Demo 2 (PD)"}, "CE6C4270F605AD3CE5E82678B0FC71F8":{n:"Vertical Rainbow Demo (PD)"}, "BDC381BAF7C252C63739C5E9ED087A5C":{n:"Vertical Ship Demo 1 (PD)"}, "6A091B8FFEACD0939850DA2094B51564":{n:"Vertically Scrolling Playfield (02-02-2003) (Aaron Bergstrom)"}, "0956285E24A18EFA10C68A33846CA84D":{n:"Viagem Espacial (Dismac)"}, "539D26B6E9DF0DA8E7465F0F5AD863B7":{n:"Video Checkers (1980) (Atari)"}, "193F060553BA0A2A2676F91D9EC0C555":{n:"Video Checkers (1980) (Atari) (PAL)"}, "F0B7DB930CA0E548C41A97160B9F6275":{n:"Video Chess (1979) (Atari)"}, "3EF9573536730DCD6D9C20B6822DBDC4":{n:"Video Chess (1979) (Atari) (PAL)"}, "A58B11148C18D85E4C2AEF4FF46ADE67":{n:"Video Chess (Unknown) (PAL)"}, "ED1492D4CAFD7EBF064F0C933249F5B0":{n:"Video Cube (CCE)"}, "4191B671BCD8237FC8E297B4947F2990":{n:"Video Jogger (1983) (Exus)"}, "497F3D2970C43E5224BE99F75E97CBBB":{n:"Video Life (1981) (CommaVid)",c:1}, "3EC12372CA3E870B11CA70EDC7EC26A4":{n:"Video Life (1981) (CommaVid) (4K)",c:1}, "4209E9DCDF05614E290167A1C033CFD2":{n:"Video Life (1981) (CommaVid) [higher sounds]",c:1}, "14D365BBFAAC3D20C6119591F57ACCA4":{n:"Video Life (Unknown) (4K) (Hack)",c:1}, "60E0EA3CBE0913D39803477945E9E5EC":{n:"Video Olympics (1977) (Atari)",p:1}, "C00B65D1BAE0AEF6A1B5652C9C2156A1":{n:"Video Olympics (1977) (Atari) (4K)",p:1}, "77D0A577636E1C9212AECCDE9D0BAA4B":{n:"Video Olympics (1977) (Atari) (PAL)",p:1}, "FE3B461D4C8B179FE68BC77760294C25":{n:"Video Olympics (1977) (Atari) (PAL) (4K)",p:1}, "107CC025334211E6D29DA0B6BE46AEC7":{n:"Video Pinball (1981) (Atari)"}, "6E59DD52F88C00D5060EAC56C1A0B0D3":{n:"Video Pinball (1981) (Atari) (PAL)"}, "A2424C1A0C783D7585D701B1C71B5FDC":{n:"Video Pinball (Unknown) (PAL)"}, "EE659AE50E9DF886AC4F8D7AD10D046A":{n:"Video Reflex (1983) (Exus)"}, "16F494F20AF5DC803BC35939EF924020":{n:"Video Simon (Mark De Smet)"}, "93ACD5020AE8EB5673601E2EDECBC158":{n:"Video Time Machine (Chris Cracknell)"}, "3B80B8F52A0939E16B5059F93A3FC19A":{n:"Virtual Pet (V007) (after Demo 2) (CRACKERS) (PD)"}, "4F0071946E80CA68EDFDCCBAC86DCCE0":{n:"Virtual Pet Demo 1 (CRACKERS) (PD)"}, "1F349DD41C3F93C4214E5E308DCCB056":{n:"Virtual Pet Demo 2 (CRACKERS) (PD)"}, "E17699A54C90F3A56AE4820F779F72C4":{n:"Vogel Flieh (1983) (Quelle) (PAL)"}, "6C128BC950FCBDBCAF0D99935DA70156":{n:"Volleyball (1983) (Digitel)"}, "4D8396DEEABB40B5E8578276EB5A8B6D":{n:"Volleyball (1983) (Quelle) (PAL)"}, "5FAFFE1C4C57430978DEC5CED32B9F4A":{n:"Volleyball (Dactari - Milmar)"}, "42B3AB3CF661929BDC77B621A8C37574":{n:"Volleyball (Robby)"}, "8108162BC88B5A14ADC3E031CF4175AD":{n:"Vom Himmel durch die Hoelle (1983) (Quelle) (PAL)"}, "1F21666B8F78B65051B7A609F1D48608":{n:"Vulture Attack (1982) (K-Tel Vision)"}, "B00A8BC9D7FE7080980A514005CBAD13":{n:"Vulture Attack (1982) (K-Tel Vision) (PAL)"}, "6041F400B45511AA3A69FAB4B8FC8F41":{n:"Wabbit (1982) (Apollo)"}, "38CF93EACFB2FA9A2C5E39059FF35A74":{n:"WacMan (2003) (Greg Zumwalt) (Hack)"}, "1C5796D277D9E4DF3F6648F7012884C4":{n:"Wachroboter jagt Jupy (Quelle) (PAL)"}, "7FF53F6922708119E7BF478D7D618C86":{n:"Walker (Suntek) (PAL)"}, "D175258B2973B917A05B46DF4E1CF15D":{n:"Walker (Suntek) (PAL) [a]"}, "D3456B4CF1BD1A7B8FB907AF1A80EE15":{n:"Wall Ball (1983) (Avalon Hill)",c:1}, "C16FBFDBFDF5590CC8179E4B0F5F5AEB":{n:"Wall Break (Unknown)"}, "EAE6A5510055341D3ABEB45667BB3E9B":{n:"Wall Defender (HES) (PAL)"}, "03FF9E8A7AF437F16447FE88CEA3226C":{n:"Wall-Defender (1983) (Bomb)"}, "372BDDF113D088BC572F94E98D8249F5":{n:"Wall-Defender (1983) (Bomb) (PAL)"}, "6522717CFD75D1DBA252CBDE76992090":{n:"War 2000 (1983) (Home Vision) (PAL)"}, "9436B7AD131B5A1F7753CE4309BA3DEE":{n:"War of The Worlds (Kyle Pittman) (Hack)"}, "CBE5A166550A8129A5E6D374901DFFAD":{n:"Warlords (1981) (Atari)",p:1}, "0C80751F6F7A3B370CC9E9F39AD533A7":{n:"Warlords (1981) (Atari) (PAL)",p:1}, "679E910B27406C6A2072F9569AE35FC8":{n:"Warplock (1982) (Data Age)",p:1,c:1}, "D1C3520B57C348BC21D543699BC88E7E":{n:"Warplock (1983) (Gameworld) (PAL)",p:1,c:1}, "D88691C995008B9AB61A44BB686B32E4":{n:"Warring Worms (07-02-2002) (Billy Eno)"}, "FA3DE71841C0841DB6A741884A6B6B2F":{n:"Warring Worms (17-02-2002) (Billy Eno)"}, "2351D26D0BFDEE3095BEC9C05CBCF7B0":{n:"Warring Worms (19-01-2002) (Billy Eno)"}, "7E7C4C59D55494E66EEF5E04EC1C6157":{n:"Warring Worms (2002) (Baroque Gaming)"}, "A2F296EA2D6D4B59979BAC5DFBF4EDF0":{n:"Warring Worms (28-01-2002) (Billy Eno)"}, "7A64B5A6E90619C6AACF244CDD7502F8":{n:"Warring Worms (Beta 1) (2002) (Baroque Gaming)"}, "2F66EBF037321ED0442AC4B89CE22633":{n:"Warring Worms (Beta 2) (2002) (Baroque Gaming)"}, "D17A8C440D6BE79FAE393A4B46661164":{n:"Warring Worms (Beta 3) (2002) (Billy Eno)"}, "4A2FE6F0F6317F006FD6D4B34515448B":{n:"Warring Worms (Midwest Classic Edition) (08-06-2002) (Billy Eno)"}, "E171558C51BB3BAC97BFA79FA2C1A19C":{n:"Warring Worms (Tim Strauss Edition) (20-12-2002) (Billy Eno)"}, "0D7E630A14856F4D52C9666040961D4D":{n:"Wavy Line Test (PD)"}, "5C73693A89B06E5A09F1721A13176F95":{n:"Wavy Line Test 2 (PD)"}, "BCE4C291D0007F16997FAA5C4DB0A6B8":{n:"Weltraumtunnel (1983) (Quelle) (PAL)"}, "D47387658ED450DB77C3F189B969CC00":{n:"Westward Ho (1982) (PlayAround) (PAL)"}, "4C39A2C97917D3D71739B3E21F60BBA5":{n:"Whale (Sub Scan Hack)"}, "AB10F2974DEE73DAB4579F0CAB35FCA6":{n:"Wilma Wanderer (1983) (ITT Family Games) (PAL)"}, "4E02880BEEB8DBD4DA724A3F33F0971F":{n:"Wing War (1983) (Imagic) (PAL)"}, "9D2938EB2B17BB73E9A79BBC06053506":{n:"Wing War (1983) (Imagic) (PAL) [a]"}, "0CDD9CC692E8B04BA8EB31FC31D72E5E":{n:"Wing War (Thomas Jentzsch)"}, "8E48EA6EA53709B98E6F4BD8AA018908":{n:"Wings (06-03-1983) (CBS Electronics) (Prototype)",c:1}, "827A22B9DFFEE24E93ED0DF09FF8414A":{n:"Wings (10-10-1983) (CBS Electronics) (Prototype) (PAL)",c:1}, "83FAFD7BD12E3335166C6314B3BDE528":{n:"Winter Games (1987) (Epyx)"}, "8C36ED2352801031516695D1EEEFE617":{n:"Winter Games (1987) (Epyx) (PAL)"}, "6C1553CA90B413BF762DFC65F2B881C7":{n:"Winterjagd (1983) (Quelle) (PAL)"}, "7B24BFE1B61864E758ADA1FE9ADAA098":{n:"Wizard (1980) (Atari) (Prototype)"}, "3B86A27132FB74D9B35D4783605A1BCB":{n:"Wizard (1980) (Atari) (Prototype) (4K)"}, "1F40EEFC7447336AE6CD8FFA5EB325BE":{n:"Wizard (1980) (Atari) (Prototype) (4K) [a]"}, "C43BD363E1F128E73BA5F0380B6FD7E3":{n:"Wizard (1980) (Atari) (Prototype) [a]"}, "7E8AA18BC9502EB57DAAF5E7C1E94DA7":{n:"Wizard of Wor (1982) (CBS Electronics)",c:1}, "663EF22EB399504D5204C543B8A86BCD":{n:"Wizard of Wor (1982) (CBS Electronics) (PAL)",c:1}, "EC3BEB6D8B5689E867BAFB5D5F507491":{n:"Word Zapper (1982) (U.S. Games)"}, "3A53963F053B22599DB6AC9686F7722F":{n:"Word Zapper (208 in 1) (Unknown) (PAL)"}, "E1143B72A30D4D3FEE385EEC38B4AA4D":{n:"Word Zapper (Unknown)"}, "37527966823EE9243D34C7DA8302774F":{n:"Word Zapper (Unknown) (PAL)"}, "2FACD460A6828E0E476D3AC4B8C5F4F7":{n:"Words-Attack (1983) (Sancho) (PAL)",c:1}, "130C5742CD6CBE4877704D733D5B08CA":{n:"World End (1983) (Home Vision) (PAL)"}, "E62E60A3E6CB5563F72982FCD83DE25A":{n:"World End (Jone Yuan)"}, "87F020DAA98D0132E98E43DB7D8FEA7E":{n:"Worm War I (1982) (20th Century Fox)"}, "007D18DEDC1F0565F09C42AA61A6F585":{n:"Worm War I (1983) (CCE)"}, "FB531FEBF8E155328EC0CD39EF77A122":{n:"Worm War I (208 in 1) (Unknown) (PAL)",c:1}, "52B448757081FD9FABF859F4E2F91F6B":{n:"Worm War I (Unknown) (PAL)"}, "5C0520C00163915A4336E481CA4E7EF4":{n:"Wuestenschlacht (1983) (Quelle) (PAL)"}, "332F01FD18E99C6584F61AA45EE7791E":{n:"X'Mission (Unknown) (PAL)",c:1}, "0D35618B6D76DDD46D2626E9E3E40DB5":{n:"X-Doom V.26 (PD)"}, "F613AAD84D2163D6B197B220BFEC1B7E":{n:"X-Doom V.27 (PD)"}, "5961D259115E99C30B64FE7058256BCF":{n:"X-Man (1983) (Universal)"}, "5E201D6BFC520424A28F129EE5E56835":{n:"X-Man (1983) (Universal) (PAL)"}, "F38358CD8F5ECFEDFFD5ACA1AA939F18":{n:"X-Man (1983) (Universal) [a]"}, "9E2C7299C69B602443D327C7DAD51CBF":{n:"Xaxyrax Road (Charles Morgan) (Hack)"}, "972486110933623039A3581DB308FDA6":{n:"Xeno Plus (Hack)"}, "EAF744185D5E8DEF899950BA7C6E7BB5":{n:"Xenophobe (1990) (Atari)"}, "F02BA8B5292BF3017D10553C9B7B2861":{n:"Xenophobe (1990) (Atari) (PAL)"}, "5494B9EE403D9757F0FD1F749E80214A":{n:"Xenophobe Arcade (2003) (Larry Petit) (Hack)"}, "284CA61B2407BDBA3938048B0A559015":{n:"Xevious (05-25-1983) (Atari) (Prototype)",c:1}, "C6688781F4AB844852F4E3352772289B":{n:"Xevious (08-02-1983) (Atari) (Prototype)",c:1}, "24385BA7F5109FBE76AADC0A375DE573":{n:"Xevious (CCE)",c:1}, "D090836F0A4EA8DB9AC7ABB7D6ADF61E":{n:"Yahtzee (Hozer Video Games)",c:1}, "096649575E451508006B17E0353259A5":{n:"Yar Vs. Yar (2002) (Justin J. Scott) (Hack)",c:1}, "159E5CD6CCB968015F49AED5ADBC91EB":{n:"Yar's Defeat (2002) (Justin J. Scott) (Hack)",c:1}, "C5930D0E8CDAE3E037349BFA08E871BE":{n:"Yars' Revenge (1982) (Atari)",c:1}, "E91D2ECF8803AE52B55BBF105AF04D4B":{n:"Yars' Revenge (1982) (Atari) (PAL)",c:1}, "75EA60884C05BA496473C23A58EDF12F":{n:"Yars' Revenge (1982) (Atari) (PAL) [a]",c:1}, "5F681403B1051A0822344F467B05A94D":{n:"Yars' Revenge (1982) (Atari) [a]",c:1}, "2F7772879A1ED04F660AA9D77A86A4BD":{n:"Yars' Revenge (Genesis)",c:1}, "522C9CF684ECD72DB2F85053E6F6F720":{n:"Year 1999, The (Rainbow Vision) (PAL)"}, "2179DFD7EDEE76EFAFE698C1BC763735":{n:"Yellow Submarine (Cody Pittman) (PD)"}, "3856B9425CC0185ED770376A62AF0282":{n:"Yellow Submarine (Kyle Pittman) (Hack)"}, "C1E6E4E7EF5F146388A090F1C469A2FA":{n:"Z-Tack (1983) (Bomb)"}, "D6DC9B4508DA407E2437BFA4DE53D1B2":{n:"Z-Tack (1983) (Bomb) (PAL)"}, "25BB080457351BE724AAC8A02021AA92":{n:"Zaxxon (1982) (CBS Electronics) (PAL)"}, "EEA0DA9B987D661264CCE69A7C13C3BD":{n:"Zaxxon (1982) (Coleco)"}, "1367E41858BE525710EB04D0DAB53505":{n:"Zelda (2003) (Kyle Pittman) (Hack)"}, "C5A76BAFC4676EDB76E0126FB9F0FB2D":{n:"Zero Patrol (Charles Morgan) (Hack)"}, "692202772D8B38CCF85A90C8003A1324":{n:"Zi - The Flie Buster (2002) (Fernando Mora) (PD)"}, "FB833ED50C865A9A505A125FC9D79A7E":{n:"Zoo Fun (1983) (Home Vision) (PAL)"}, "0FCFF6FE3B0769AD5D0CF82814D2A6D9":{n:"Zoo Fun (Suntek) (PAL)"}, "A336BEAC1F0A835614200ECD9C41FD70":{n:"Zoo Keeper Sounds (1984) (Atari) (Prototype)"}, "527B2893F202E0B4930E18E739C81EF4":{n:"Star Castle Arcade 124cu",l:"Star Castle Arcade",c:1}, "2CEE5D587E6A2240233C93A5035D5748":{n:"Star Castle Arcade 124",l:"Star Castle Arcade",c:1}, "DCBDD2C1E201637C30369CE657E1B5CC":{n:"Star Castle Arcade 133cu",l:"Star Castle Arcade",c:1}, "B503531C719AECEF6E97C4961F97F5E8":{n:"Star Castle Arcade 133",l:"Star Castle Arcade",c:1}, "33AB116244C57F6726D0D64BA9F5B6A4":{n:"Star Castle Arcade 140cu",l:"Star Castle Arcade",c:1}, "15A6D61D04D50B5C4DC77964AF812469":{n:"Star Castle Arcade 140",l:"Star Castle Arcade",c:1} }; ================================================ FILE: src/main/atari/cartridge/CartridgeFormats.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.CartridgeFormats = { "4K": { name: "4K", desc: "4K Atari", priority: 101, tryFormat: function (rom) { if (rom.content.length >= 8 && rom.content.length <= 4096 && 4096 % rom.content.length === 0) return this; }, createCartridgeFromRom: function (rom) { return new jt.Cartridge4K(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge4K.recreateFromSaveState(state, cart); } }, "CV": { name: "CV", desc: "2K Commavid +RAM", priority: 102, tryFormat: function (rom) { if (rom.content.length === 2048 || rom.content.length === 4096) return this; // Also accepts 4K ROMs }, createCartridgeFromRom: function (rom) { return new jt.Cartridge2K_CV(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge2K_CV.recreateFromSaveState(state, cart); } }, "E0": { name: "E0", desc: "8K Parker Bros.", priority: 102, tryFormat: function (rom) { if (rom.content.length === 8192) return this; }, createCartridgeFromRom: function (rom) { return new jt.Cartridge8K_E0(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_E0.recreateFromSaveState(state, cart); } }, "F0": { name: "F0", desc: "64K Dynacom Megaboy", priority: 101, tryFormat: function (rom) { if (rom.content.length === 65536) return this; }, createCartridgeFromRom: function (rom) { return new jt.Cartridge64K_F0(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge64K_F0.recreateFromSaveState(state, cart); } }, "FE": { name: "FE", desc: "8K Robotank/Decathlon", priority: 103, tryFormat: function (rom) { if (rom.content.length === 8192) return this; }, createCartridgeFromRom: function (rom) { return new jt.Cartridge8K_FE(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_FE.recreateFromSaveState(state, cart); } }, "E7": { name: "E7", desc: "16K M-Network", priority: 102, tryFormat: function (rom) { if (rom.content.length === 16384) return this; }, createCartridgeFromRom: function (rom) { return new jt.Cartridge16K_E7(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge16K_E7.recreateFromSaveState(state, cart); } }, "F8": { name: "F8", desc: "8K Atari (+RAM)", priority: 101, tryFormat: function(rom) { if (rom.content.length === 8192) return this; }, createCartridgeFromRom: function(rom) { return new jt.CartridgeBankedByMaskedRange(rom, this, 0x0ff8, null, 128); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(state, cart); } }, "F6": { name: "F6", desc: "16K Atari (+RAM)", priority: 101, tryFormat: function(rom) { if (rom.content.length === 16384) return this; }, createCartridgeFromRom: function(rom) { return new jt.CartridgeBankedByMaskedRange(rom, this, 0x0ff6, null, 128); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(state, cart); } }, "F4": { name: "F4", desc: "32K Atari (+RAM)", priority: 101, tryFormat: function(rom) { if (rom.content.length === 32768) return this; }, createCartridgeFromRom: function(rom) { return new jt.CartridgeBankedByMaskedRange(rom, this, 0x0ff4, null, 128); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(state, cart); } }, "FA2cu": { name: "FA2cu", desc: "32K CBS RAM+ CU Image", priority: 103, tryFormat: function(rom) { if (rom.content.length === 32768) { // Check for the values $10adab1e, for "loadable", starting at position 32 (33rd byte) // This is a hint that the content is in CU format var foundHint = jt.Util.arraysEqual(rom.content.slice(32, 32 + 4), this.cuMagicWord); this.priority = 103 - (foundHint ? 30 : 0); return this; } }, createCartridgeFromRom: function(rom) { // ROM is only 28K. The first 1024 bytes are custom ARM content. ROM begins after that return new jt.Cartridge24K_28K_32K_FA2(rom, this, 1024); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(state, cart); }, cuMagicWord: [0x1e, 0xab, 0xad, 0x10] }, "FA2": { name: "FA2", desc: "24K/28K/32K CBS RAM+", priority: 102, tryFormat: function(rom) { if (rom.content.length === 24576 || rom.content.length === 28672 || rom.content.length === 32768) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge24K_28K_32K_FA2(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState(state, cart); } }, "FA": { name: "FA", desc: "12K CBS RAM Plus", priority: 101, tryFormat: function(rom) { if (rom.content.length === 12288) return this; }, createCartridgeFromRom: function(rom) { return new jt.CartridgeBankedByMaskedRange(rom, this, 0x0ff8, true, 256); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(state, cart); } }, "EF": { name: "EF", desc: "8K-64K H. Runner (+RAM)", priority: 114, tryFormat: function(rom) { if (rom.content.length % 4096 === 0 && rom.content.length >= 8192 && rom.content.length <= 65536) return this; }, createCartridgeFromRom: function(rom) { return new jt.CartridgeBankedByMaskedRange(rom, this, 0x0fe0, null, 128); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.CartridgeBankedByMaskedRange.recreateFromSaveState(state, cart); } }, "DPC": { name: "DPC", desc: "10K DPC Pitfall 2 (Enhanced)", priority: 101, tryFormat: function(rom) { if (rom.content.length >= (8192 + 2048) && rom.content.length <= (8192 + 2048 + 256)) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge10K_DPCa(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge10K_DPCa.recreateFromSaveState(state, cart); } }, "3F": { name: "3F", desc: "8K-512K Tigervision", priority: 112, tryFormat: function(rom) { if (rom.content.length % 2048 === 0 && rom.content.length >= 2048 && rom.content.length <= 256 * 2048) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_512K_3F(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_512K_3F.recreateFromSaveState(state, cart); } }, "3E": { name: "3E", desc: "8K-512K Tigervision (+RAM)", priority: 111, tryFormat: function(rom) { if (rom.content.length % 2048 === 0 && rom.content.length >= 2048 && rom.content.length <= 256 * 2048) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_512K_3E(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_512K_3E.recreateFromSaveState(state, cart); } }, "X07": { name: "X07", desc: "64K AtariAge", priority: 102, tryFormat: function(rom) { if (rom.content.length === 65536) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge64K_X07(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge64K_X07.recreateFromSaveState(state, cart); } }, "0840": { name: "0840", desc: "8K Econobanking", priority: 116, tryFormat: function(rom) { if (rom.content.length === 8192) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_0840(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_0840.recreateFromSaveState(state, cart); } }, "UA": { name: "UA", desc: "8K UA Limited", priority: 115, tryFormat: function(rom) { if (rom.content.length === 8192) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_UA(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_UA.recreateFromSaveState(state, cart); } }, "SB": { name: "SB", desc: "8K-256K Superbanking", priority: 113, tryFormat: function(rom) { if (rom.content.length % 4096 === 0 && rom.content.length >= 8192 && rom.content.length <= 64 * 4096) return this; }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_256K_SB(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_256K_SB.recreateFromSaveState(state, cart); } }, "AR": { name: "AR", desc: "8K-64K Arcadia/Supercharger", priority: 101, tryFormat: function(rom) { // Any number of parts between 1 and 8 if (rom.content.length % jt.Cartridge8K_64K_AR.PART_SIZE === 0 && rom.content.length / jt.Cartridge8K_64K_AR.PART_SIZE >= 1 && rom.content.length / jt.Cartridge8K_64K_AR.PART_SIZE <= 8) { // Check if the content starts with Part 0 if (jt.Cartridge8K_64K_AR.checkTape(rom)) return this; // Accepts only a Tape Start or Full Tape } }, createCartridgeFromRom: function(rom) { return new jt.Cartridge8K_64K_AR(rom, this); }, recreateCartridgeFromSaveState: function(state, cart) { return jt.Cartridge8K_64K_AR.recreateFromSaveState(state, cart); } } }; // Formats available for user selection, in order jt.CartridgeFormatsUserOptions = [ "4K", "CV", "E0", "F0", "FE", "E7", "F8", "F6", "F4", "FA2cu", "FA2", "FA", "EF", "DPC", "3F", "3E", "X07", "0840", "UA", "SB", "AR" ]; ================================================ FILE: src/main/atari/cartridge/ROM.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.ROM = function(source, content, info, formatHint) { "use strict"; this.source = source; this.content = content; if (info) this.info = info; else this.info = jt.CartridgeCreator.produceInfo(this, formatHint); // Savestate ------------------------------------------- this.saveState = function(includeContent) { return { s: this.source, i: this.info, c: includeContent ? jt.Util.compressInt8BitArrayToStringBase64(this.content) : null // content may not be needed in savestates }; }; }; jt.ROM.loadState = function(state) { "use strict"; var c = state.c ? jt.Util.uncompressStringBase64ToInt8BitArray(state.c) : null; return new jt.ROM(state.s, c, state.i); }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge10K_DPCa.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K + 2K "DPCa" (Pitfall2) format, enhanced version with TIA audio updates every DPC audio clock! jt.Cartridge10K_DPCa = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.powerOn = function() { audioClockStep = AUDIO_CLOCK_DEFAULT_STEP; audioClockCycles = 0; }; this.connectBus = function(bus) { dpcAudioChannel = bus.getTia().getAudioOutput().getChannel0(); }; this.needsAudioClock = function() { return true; }; this.read = function(address) { var maskedAddress = maskAddress(address); // Check for DPC register read if (maskedAddress <= 0x03f || (maskedAddress >= 0x800 && maskedAddress <= 0x83f)) return readDPCRegister(maskedAddress & 0x00ff); // Always add the correct bank offset return bytes[bankAddressOffset + maskedAddress]; // ROM }; this.write = function(address, val) { var maskedAddress = maskAddress(address); // Check for DPC register write if ((maskedAddress >= 0x040 && maskedAddress <= 0x07f) || (maskedAddress >= 0x840 && maskedAddress <= 0x87f)) writeDPCRegister(maskedAddress & 0x00ff, val); }; this.audioClockPulse = function() { if (((audioClockCycles + audioClockStep) | 0) > (audioClockCycles | 0)) { // Actual integer clock for (var f = 5; f <= 7; f++) { if (!audioMode[f]) continue; fetcherPointer[f]--; if ((fetcherPointer[f] & 0x00ff) == 0xff) setFetcherPointer(f, fetcherPointer[f] & 0xff00 | fetcherStart[f]); updateFetcherMask(f); if (!audioChanged) audioChanged = true; } } audioClockCycles += audioClockStep; if (!audioChanged) return; // Send a volume update directly to TIA Audio Channel 0 updateAudioOutput(); dpcAudioChannel.setVolume(audioOutput); }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check and perform bank-switch as necessary if (maskedAddress === 0xff8) bankAddressOffset = 0; else if (maskedAddress === 0xff9) bankAddressOffset = 4096; return maskedAddress; }; var updateAudioOutput = function() { audioOutput = AUDIO_MIXED_OUTPUT[ (audioMode[5] ? fetcherMask[5] & 0x04 : 0) | (audioMode[6] ? fetcherMask[6] & 0x02 : 0) | (audioMode[7] ? fetcherMask[7] & 0x01 : 0)]; audioChanged = false; }; // TODO Fix bug when reading register as normal fetcher while in audio mode var readDPCRegister = function(reg) { var res; // Random number if (reg >= 0x00 && reg <= 0x03) { clockRandomNumber(); return randomNumber; } // Audio value (MOVAMT not supported) if (reg >= 0x04 && reg <= 0x07) { if (audioChanged) updateAudioOutput(); return audioOutput; } // Fetcher unmasked value if (reg >= 0x08 && reg <= 0x0f) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x08]]; clockFetcher(reg - 0x08); return res; } // Fetcher masked value if (reg >= 0x10 && reg <= 0x17) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x10]] & fetcherMask[reg - 0x10]; clockFetcher(reg - 0x10); return res; } // Fetcher masked value, nibbles swapped if (reg >= 0x18 && reg <= 0x1f) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x18]] & fetcherMask[reg - 0x18]; clockFetcher(reg - 0x18); res = (res & 0x0f << 4) | (res & 0xf0 >>> 4); return res; } // Fetcher masked value, byte reversed if (reg >= 0x20 && reg <= 0x27) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x20]] & fetcherMask[reg - 0x20]; clockFetcher(reg - 0x20); res = (res & 0x01 << 7) | (res & 0x02 << 5) | (res & 0x04 << 3) | (res & 0x08 << 1) | (res & 0x10 >>> 1) | (res & 0x20 >>> 3) | (res & 0x40 >>> 5) | (res & 0x80 >> 7); return res; } // Fetcher masked value, byte rotated right if (reg >= 0x28 && reg <= 0x2f) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x28]] & fetcherMask[reg - 0x28]; clockFetcher(reg - 0x28); res = ((res >>> 1) | (res << 7)) & 0xff; return res; } // Fetcher masked value, byte rotated left if (reg >= 0x30 && reg <= 0x37) { res = bytes[DPC_ROM_END - fetcherPointer[reg - 0x30]] & fetcherMask[reg - 0x30]; clockFetcher(reg - 0x30); res = ((res << 1) | ((res >> 7) & 0x01)) & 0xff; return res; } // Fetcher mask if (reg >= 0x38 && reg <= 0x3f) { return fetcherMask[reg - 0x38]; } return 0; }; var writeDPCRegister = function(reg, b) { // Fetchers Start if (reg >= 0x40 && reg <= 0x47) { var f = reg - 0x40; fetcherStart[f] = b; if ((fetcherPointer[f] & 0xff) === fetcherStart[f]) fetcherMask[f] = 0xff; return; } // Fetchers End if (reg >= 0x48 && reg <= 0x4f) { fetcherEnd[reg - 0x48] = b; fetcherMask[reg - 0x48] = 0x00; return; } // Fetchers Pointers LSB if (reg >= 0x50 && reg <= 0x57) { setFetcherPointer(reg - 0x50, (fetcherPointer[reg - 0x50] & 0xff00) | (b & 0xff)); return; // LSB } // Fetchers 0-3 Pointers MSB if (reg >= 0x58 && reg <= 0x5b) { setFetcherPointer(reg - 0x58, (fetcherPointer[reg - 0x58] & 0x00ff) | ((b & (0x07)) << 8)); return; // MSB bits 0-2 } // Fetchers 4 Pointers MSB (Draw Line enable not supported) if (reg == 0x5c) { setFetcherPointer(4, (fetcherPointer[4] & 0x00ff) | ((b & (0x07)) << 8)); // MSB bits 0-2 return; } // Fetchers 5-7 Pointers MSB and Audio Mode enable if (reg >= 0x5d && reg <= 0x5f) { setFetcherPointer(reg - 0x58, (fetcherPointer[reg - 0x58] & 0x00ff) + ((b & (0x07)) << 8)); // MSB bits 0-2 audioMode[reg - 0x58] = ((b & 0x10) >>> 4); return; } // Draw Line MOVAMT value (not supported) if (reg >= 0x60 && reg <= 0x67) { return; } // 0x68 - 0x6f Not used // Random Number reset if (reg >= 0x70 && reg <= 0x77) { randomNumber = 0x00; } // 0x78 - 0x7f Not used }; var setFetcherPointer = function(f, pointer) { fetcherPointer[f] = pointer; }; var clockFetcher = function(f) { var newPointer = fetcherPointer[f] - 1; if (newPointer < 0 ) newPointer = 0x07ff; setFetcherPointer(f, newPointer); updateFetcherMask(f); }; var updateFetcherMask = function(f) { var lsb = fetcherPointer[f] & 0xff; if (lsb == fetcherStart[f]) fetcherMask[f] = 0xff; else if (lsb == fetcherEnd[f]) fetcherMask[f] = 0x00; }; var clockRandomNumber = function() { randomNumber = ((randomNumber << 1) | (~((randomNumber >> 7) ^ (randomNumber >> 5) ^ (randomNumber >> 4) ^ (randomNumber >> 3)) & 0x01)) & 0xff; if (randomNumber === 0xff) randomNumber = 0; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, rn: randomNumber, fp: jt.Util.compressInt8BitArrayToStringBase64(fetcherPointer), fs: jt.Util.compressInt8BitArrayToStringBase64(fetcherStart), fe: jt.Util.compressInt8BitArrayToStringBase64(fetcherEnd), fm: jt.Util.compressInt8BitArrayToStringBase64(fetcherMask), a: jt.Util.compressInt8BitArrayToStringBase64(audioMode) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; randomNumber = state.rn; fetcherPointer = jt.Util.uncompressStringBase64ToInt8BitArray(state.fp, fetcherPointer); fetcherStart = jt.Util.uncompressStringBase64ToInt8BitArray(state.fs, fetcherStart); fetcherEnd = jt.Util.uncompressStringBase64ToInt8BitArray(state.fe, fetcherEnd); fetcherMask = jt.Util.uncompressStringBase64ToInt8BitArray(state.fm, fetcherMask); audioMode = jt.Util.uncompressStringBase64ToInt8BitArray(state.a, audioMode); }; var AUDIO_MIXED_OUTPUT = [0x0, 0x5, 0x5, 0xa, 0x5, 0xa, 0xa, 0xf]; // var AUDIO_MIXED_OUTPUT = [0x0, 0x4, 0x5, 0x9, 0x6, 0xa, 0xb, 0xf]; // Per specification var ADDRESS_MASK = 0x0fff; var AUDIO_CLOCK_DEFAULT_STEP = 0.62; var DPC_ROM_END = 8192 + 2048 - 1; var dpcAudioChannel; var bytes; var bankAddressOffset = 0; var randomNumber = 0; var fetcherPointer = jt.Util.arrayFill(new Array(8), 0); var fetcherStart = jt.Util.arrayFill(new Array(8), 0); var fetcherEnd = jt.Util.arrayFill(new Array(8), 0); var fetcherMask = jt.Util.arrayFill(new Array(8), 0); var audioMode = jt.Util.arrayFill(new Array(8), 0); var audioClockStep = AUDIO_CLOCK_DEFAULT_STEP; var audioClockCycles = 0; var audioChanged = true; var audioOutput = 0; if (rom) init(this); }; jt.Cartridge10K_DPCa.prototype = jt.Cartridge.base; jt.Cartridge10K_DPCa.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge10K_DPCa(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge16K_E7.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 16K "E7" M-Network format jt.Cartridge16K_E7 = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { var maskedAddress = maskAddress(address); // Check for Extra RAM Slice1 (always ON) if (maskedAddress >= 0x0900 && maskedAddress <= 0x09ff) return extraRAM[extraRAMSlice1Offset + maskedAddress - 0x0900]; // Check for Extra RAM Slice0 if (extraRAMSlice0Active && maskedAddress >= 0x0400 && maskedAddress <= 0x07ff) return extraRAM[maskedAddress - 0x0400]; // ROM if (maskedAddress < ROM_FIXED_SLICE_START) return bytes[bankAddressOffset + maskedAddress]; // ROM Selectable Slice else return bytes[ROM_FIXED_SLICE_OFFSET + maskedAddress]; // ROM Fixed Slice }; this.write = function(address, val) { var maskedAddress = maskAddress(address); // Check for Extra RAM Slice1 (always ON) if (maskedAddress >= 0x0800 && maskedAddress <= 0x08ff) extraRAM[extraRAMSlice1Offset + maskedAddress - 0x0800] = val; else // Check for Extra RAM Slice0 if (extraRAMSlice0Active && maskedAddress <= 0x03ff) extraRAM[maskedAddress] = val; }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check if address is within range of bank selection if (maskedAddress >= 0x0fe0 && maskedAddress <= 0x0feb) { if (/* maskedAddress >= 0x0fe0 && */ maskedAddress <= 0x0fe6) // Selectable ROM Slice bankAddressOffset = BANK_SIZE * (maskedAddress - 0x0fe0); else if (maskedAddress == 0x0fe7) // Extra RAM Slice0 extraRAMSlice0Active = true; else if (/* maskedAddress >= 0x0fe8 && */ maskedAddress <= 0x0feb) // Extra RAM Slice1 extraRAMSlice1Offset = EXTRA_RAM_SLICE1_START + EXTRA_RAM_SLICE1_BANK_SIZE * (maskedAddress - 0x0fe8); } return maskedAddress; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, rs: extraRAMSlice0Active, ro: extraRAMSlice1Offset, ra: jt.Util.compressInt8BitArrayToStringBase64(extraRAM) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; extraRAMSlice0Active = state.rs; extraRAMSlice1Offset = state.ro; extraRAM = jt.Util.uncompressStringBase64ToInt8BitArray(state.ra, extraRAM); }; var bytes; var bankAddressOffset = 0; var EXTRA_RAM_SLICE1_START = 1024; var extraRAM = jt.Util.arrayFill(new Array(2048), 0); var extraRAMSlice0Active = false; var extraRAMSlice1Offset = EXTRA_RAM_SLICE1_START; var ADDRESS_MASK = 0x0fff; var SIZE = 16384; var BANK_SIZE = 2048; var ROM_FIXED_SLICE_START = 0x0800; var ROM_FIXED_SLICE_OFFSET = SIZE - BANK_SIZE - ROM_FIXED_SLICE_START; var EXTRA_RAM_SLICE1_BANK_SIZE = 256; if (rom) init(this); }; jt.Cartridge16K_E7.prototype = jt.Cartridge.base; jt.Cartridge16K_E7.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge16K_E7(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge24K_28K_32K_FA2.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 24K/28K/32K "FA2" CBS RAM Plus format // Also supports SC RAM Saving on Harmony Flash memory (emulated to a "savestate" file) jt.Cartridge24K_28K_32K_FA2 = function(rom, format, pRomStartAddress) { "use strict"; var self = this; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; romStartAddress = pRomStartAddress || 0; bankAddressOffset = romStartAddress; var numBanks = (bytes.length - romStartAddress) / BANK_SIZE; topBankSwitchAddress = baseBankSwitchAddress + numBanks - 1; } this.connectBus = function(pBus) { bus = pBus; }; this.connectSaveStateSocket = function(socket) { saveStateSocket = socket; }; this.read = function(address) { var val; var maskedAddress = maskAddress(address); // Check for SuperChip Extra RAM reads if (maskedAddress >= 256 && maskedAddress < (256 * 2)) val = extraRAM[maskedAddress - 256]; else val = bytes[bankAddressOffset + maskedAddress]; // Normal behavior if not the Flash Operation Hotspot address if (maskedAddress !== FLASH_OP_HOTSPOT) return val; // Should trigger new operation? if (harmonyFlashOpInProgress === 0) { var op = extraRAM[FLASH_OP_CONTROL]; if (op === 1 || op === 2) { performFlashOperation(op); return val | 0x40; // In progress, set bit 6 } } // Report operation completion if (harmonyFlashOpInProgress !== 0) detectFlashOperationCompletion(); else return val & 0xbf; // Not busy, clear bit 6 if (harmonyFlashOpInProgress !== 0) return val | 0x40; // Still in progress, set bit 6 else return val & 0xbf; // Finished, clear bit 6 }; this.write = function(address, val) { var maskedAddress = maskAddress(address); // Check for Extra RAM writes if (maskedAddress < 256) extraRAM[maskedAddress] = val; }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check and perform bank-switch as necessary if (maskedAddress >= baseBankSwitchAddress && maskedAddress <= topBankSwitchAddress) bankAddressOffset = romStartAddress + BANK_SIZE * (maskedAddress - baseBankSwitchAddress); return maskedAddress; }; var performFlashOperation = function(op) { harmonyFlashOpInProgress = op; harmonyFlashOpChecksCount = 0; // 1 = read, 2 = write if (op === 1) readMemoryFromFlash(); else if (op === 2) saveMemoryToFlash(); }; var readMemoryFromFlash = function() { bus.getTia().getVideoOutput().showOSD("Reading from Cartridge Flash Memory...", true); if (saveStateSocket) { var data = saveStateSocket.getMedia().loadResource(flashMemoryResourceName()); if (data) harmonyFlashMemory = jt.Util.uncompressStringBase64ToInt8BitArray(data, harmonyFlashMemory); } jt.Util.arrayCopy(harmonyFlashMemory, 0, extraRAM); }; var saveMemoryToFlash = function() { bus.getTia().getVideoOutput().showOSD("Writing to Cartridge Flash Memory...", true); jt.Util.arrayCopy(extraRAM, 0, harmonyFlashMemory); if (saveStateSocket) saveStateSocket.getMedia().saveResource(flashMemoryResourceName(), jt.Util.compressInt8BitArrayToStringBase64(harmonyFlashMemory)); }; var detectFlashOperationCompletion = function() { if (++harmonyFlashOpChecksCount > 140) { harmonyFlashOpChecksCount = 0; harmonyFlashOpInProgress = 0; extraRAM[FLASH_OP_CONTROL] = 0; // Set return code for Successful operation bus.getTia().getVideoOutput().showOSD("Done.", true); // Signal a external state modification, Flash memory may have been loaded from file and changed if (saveStateSocket) saveStateSocket.externalStateChange(); } }; var flashMemoryResourceName = function() { return "hfm" + self.rom.info.h; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), rs: romStartAddress, bo: bankAddressOffset, tb: topBankSwitchAddress, e: jt.Util.compressInt8BitArrayToStringBase64(extraRAM), ho: harmonyFlashOpInProgress, ht: harmonyFlashOpChecksCount }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; romStartAddress = state.rs || 0; bankAddressOffset = state.bo; topBankSwitchAddress = state.tb; extraRAM = jt.Util.uncompressStringBase64ToInt8BitArray(state.e, extraRAM); harmonyFlashOpInProgress = state.ho || 0; harmonyFlashOpChecksCount = state.ht || 0; }; var bus; var saveStateSocket; var bytes; var romStartAddress = 0; var bankAddressOffset = 0; var baseBankSwitchAddress = 0x0ff5; var topBankSwitchAddress; var extraRAM = jt.Util.arrayFill(new Array(256), 0); var harmonyFlashOpChecksCount = 0; var harmonyFlashOpInProgress = 0; // 0 = none, 1 = read, 2 = write var harmonyFlashMemory = jt.Util.arrayFill(new Array(256), 0); var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; var FLASH_OP_HOTSPOT = 0x0ff4; var FLASH_OP_CONTROL = 0x00ff; if (rom) init(this); }; jt.Cartridge24K_28K_32K_FA2.prototype = jt.Cartridge.base; jt.Cartridge24K_28K_32K_FA2.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge24K_28K_32K_FA2(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge2K_CV.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 2K "CV" Commavid + 1K RAM format jt.Cartridge2K_CV = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; // Always use a 4K ROM image, multiplying the ROM internally bytes = new Array(4096); self.bytes = bytes; var len = rom.content.length; for (var pos = 0; pos < bytes.length; pos += len) jt.Util.arrayCopy(rom.content, 0, bytes, pos, len); } this.read = function(address) { var maskedAddress = maskAddress(address); // Check for Extra RAM reads if (maskedAddress < 0x0400) // RAM return extraRAM[maskedAddress]; else return bytes[maskedAddress]; // ROM }; this.write = function(address, val) { var maskedAddress = maskAddress(address); // Check for Extra RAM writes if (maskedAddress >= 0x0400 && maskedAddress <= 0x07ff) extraRAM[maskedAddress - 0x0400] = val; }; var maskAddress = function(address) { return address & ADDRESS_MASK; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), ra: jt.Util.compressInt8BitArrayToStringBase64(extraRAM) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; extraRAM = jt.Util.uncompressStringBase64ToInt8BitArray(state.ra, extraRAM); }; var bytes; var extraRAM = jt.Util.arrayFill(new Array(1024), 0); var ADDRESS_MASK = 0x0fff; if (rom) init(this); }; jt.Cartridge2K_CV.prototype = jt.Cartridge.base; jt.Cartridge2K_CV.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge2K_CV(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge4K.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 4K unbanked format. Smaller ROMs will be copied multiple times to fill the entire 4K jt.Cartridge4K = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; // Always use a 4K ROM image, multiplying the ROM internally bytes = new Array(4096); self.bytes = bytes; var len = rom.content.length; for (var pos = 0; pos < bytes.length; pos += len) jt.Util.arrayCopy(rom.content, 0, bytes, pos, len); } this.read = function(address) { return bytes[address & ADDRESS_MASK]; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; }; var bytes; var ADDRESS_MASK = 0x0fff; if (rom) init(this); }; jt.Cartridge4K.prototype = jt.Cartridge.base; jt.Cartridge4K.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge4K(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge64K_F0.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 64K "F0" Dynacom Megaboy format jt.Cartridge64K_F0 = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { var maskedAddress = maskAddress(address); return bytes[bankAddressOffset + maskedAddress]; }; this.write = function(address, val) { maskAddress(address); // Writing to ROMs is possible, but nothing is changed }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check and perform bank-switch as necessary if (maskedAddress == BANKSW_ADDRESS) { // Bank selection. Increments bank bankAddressOffset += BANK_SIZE; if (bankAddressOffset >= SIZE) bankAddressOffset = 0; } return maskedAddress; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; }; var bytes; var bankAddressOffset = 0; var ADDRESS_MASK = 0x0fff; var SIZE = 65536; var BANK_SIZE = 4096; var BANKSW_ADDRESS = 0x0ff0; if (rom) init(this); }; jt.Cartridge64K_F0.prototype = jt.Cartridge.base; jt.Cartridge64K_F0.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge64K_F0(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge64K_X07.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 64K "X07" AtariAge format jt.Cartridge64K_X07 = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { // Always add the correct offset to access bank selected return bytes[bankAddressOffset + (address & ADDRESS_MASK)]; }; this.performBankSwitchOnMonitoredAccess = function(address) { if ((address & 0x180f) === 0x080d) // Method 1 bankAddressOffset = ((address & 0x00f0) >> 4) * BANK_SIZE; // Pick bank from bits 7-4 else if (bankAddressOffset >= BANK_14_ADDRESS && (address & 0x1880) === 0x0000) // Method 2, only if at bank 14 or 15 bankAddressOffset = ((address & 0x0040) === 0 ? 14 : 15) * BANK_SIZE; // Pick bank 14 or 15 from bit 6 }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; }; var bytes; var bankAddressOffset = 0; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; var BANK_14_ADDRESS = 14 * BANK_SIZE; if (rom) init(this); }; jt.Cartridge64K_X07.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge64K_X07.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge64K_X07(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_0840.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K "0840" Econobanking format jt.Cartridge8K_0840 = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { // Always add the correct offset to access bank selected return bytes[bankAddressOffset + (address & ADDRESS_MASK)]; }; this.performBankSwitchOnMonitoredAccess = function(address) { var addrBank = address & 0x1840; if (addrBank === 0x0800) { if (bankAddressOffset !== 0) bankAddressOffset = 0; } else if (addrBank === 0x0840) { if (bankAddressOffset !== BANK_SIZE) bankAddressOffset = BANK_SIZE; } }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; }; var bytes; var bankAddressOffset = 0; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; if (rom) init(this); }; jt.Cartridge8K_0840.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_0840.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_0840(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_256K_SB.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K-256K "SB" Superbanking format jt.Cartridge8K_256K_SB = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; maxBank = bytes.length / BANK_SIZE - 1; } this.read = function(address) { // Always add the correct offset to access bank selected return bytes[bankAddressOffset + (address & ADDRESS_MASK)]; }; this.performBankSwitchOnMonitoredAccess = function(address) { if ((address & 0x1800) !== 0x0800) return; var bank = address & 0x007f; if (bank > maxBank) return; bankAddressOffset = bank * BANK_SIZE; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, m: maxBank }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; maxBank = state.m; }; var bytes; var bankAddressOffset = 0; var maxBank; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; if (rom) init(this); }; jt.Cartridge8K_256K_SB.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_256K_SB.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_256K_SB(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_512K_3E.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K-512K "3E" Tigervision (+RAM) format jt.Cartridge8K_512K_3E = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; selectableSliceMaxBank = (bytes.length - BANK_SIZE) / BANK_SIZE - 1; fixedSliceAddressOffset = bytes.length - BANK_SIZE * 2; } this.read = function(address) { var maskedAddress = maskAddress(address); if (maskedAddress >= FIXED_SLICE_START_ADDRESS) // ROM Fixed Slice return bytes[fixedSliceAddressOffset + maskedAddress]; else if (extraRAMBankAddressOffset >= 0 && maskedAddress < 0x0400) // RAM return extraRAM[extraRAMBankAddressOffset + maskedAddress] || 0; else return bytes[bankAddressOffset + maskedAddress]; // ROM Selectable Slice }; this.write = function(address, val) { // Check if Extra RAM bank is selected if (extraRAMBankAddressOffset < 0) return; var maskedAddress = maskAddress(address); // Check for Extra RAM writes if (maskedAddress >= 0x0400 && maskedAddress <= 0x07ff) extraRAM[extraRAMBankAddressOffset + maskedAddress - 0x0400] = val; }; var maskAddress = function(address) { return address & ADDRESS_MASK; }; // Bank switching is done only on monitored writes this.monitorBusBeforeWrite = function(address, data) { // Perform ROM bank switching as needed if (address === 0x003f) { var bank = data & 0xff; // unsigned if (bank <= selectableSliceMaxBank) { bankAddressOffset = bank * BANK_SIZE; extraRAMBankAddressOffset = -1; } return; } // Perform RAM bank switching as needed if (address === 0x003e) { var ramBank = data & 0xff; // unsigned extraRAMBankAddressOffset = ramBank * EXTRA_RAM_BANK_SIZE; } }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, sm: selectableSliceMaxBank, fo: fixedSliceAddressOffset, ro: extraRAMBankAddressOffset, ra: jt.Util.compressInt8BitArrayToStringBase64(extraRAM) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; selectableSliceMaxBank = state.sm; fixedSliceAddressOffset = state.fo; extraRAMBankAddressOffset = state.ro; extraRAM = jt.Util.uncompressStringBase64ToInt8BitArray(state.ra, extraRAM); }; var bytes; var EXTRA_RAM_BANK_SIZE = 1024; var bankAddressOffset = 0; var selectableSliceMaxBank; var fixedSliceAddressOffset; // This slice is fixed at the last bank var extraRAMBankAddressOffset = -1; // No Extra RAM bank selected var extraRAM = jt.Util.arrayFill(new Array(EXTRA_RAM_BANK_SIZE), 0); // Pre allocate minimum RAM bank for performance var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 2048; var FIXED_SLICE_START_ADDRESS = 2048; if (rom) init(this); }; jt.Cartridge8K_512K_3E.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_512K_3E.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_512K_3E(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_512K_3F.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K-512K "Enhanced 3F" Tigervision format jt.Cartridge8K_512K_3F = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; selectableSliceMaxBank = (bytes.length - BANK_SIZE) / BANK_SIZE - 1; fixedSliceAddressOffset = bytes.length - BANK_SIZE * 2; } this.read = function(address) { var maskedAddress = address & ADDRESS_MASK; if (maskedAddress >= FIXED_SLICE_START_ADDRESS) // Fixed slice return bytes[fixedSliceAddressOffset + maskedAddress]; else return bytes[bankAddressOffset + maskedAddress]; // Selectable slice }; // Bank switching is done only on monitored writes this.monitorBusBeforeWrite = function(address, data) { // Perform bank switching as needed if (address <= 0x003f) { var bank = data & 0xff; // unsigned if (bank <= selectableSliceMaxBank) bankAddressOffset = bank * BANK_SIZE; } }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, sm: selectableSliceMaxBank, fo: fixedSliceAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; selectableSliceMaxBank = state.sm; fixedSliceAddressOffset = state.fo; }; var bytes; var bankAddressOffset = 0; var selectableSliceMaxBank; var fixedSliceAddressOffset; // This slice is fixed at the last bank var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 2048; var FIXED_SLICE_START_ADDRESS = 2048; if (rom) init(this); }; jt.Cartridge8K_512K_3F.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_512K_3F.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_512K_3F(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_64K_AR.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the n * 8448 byte "AR" Arcadia/Starpath/Supercharger tape format jt.Cartridge8K_64K_AR = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; // Cannot use the contents of the ROM directly, as cartridge is all RAM and can be modified // Also, ROM content represents the entire tape and can have multiple parts bytes = jt.Util.arrayFill(new Array(4 * BANK_SIZE)); self.bytes = bytes; loadBIOS(); // Initialize Random seeds for (var i = 0; i < 31; ++i) randomSeeds[i] = (Math.random() * 256) | 0; } this.powerOn = function() { // Always start with bank configuration 000 (bank2, bank3 = BIOS ROM), writes disabled and BIOS ROM powered on setControlRegister(0x00); // Rewind Tape tapeOffset = 0; // BIOS will ask to load Part Number 0 at System Reset }; this.connectBus = function(pBus) { bus = pBus; }; this.read = function(address) { // maskedAddress already set on bus monitoring method // bank0 if (maskedAddress < BANK_SIZE) return bytes[bank0AddressOffset + maskedAddress]; else // bank1 return bytes[bank1AddressOffset + maskedAddress - BANK_SIZE]; }; this.write = function(address, b) { // No direct writes are possible // But check for BIOS Load Part Hotspot range if (bank1AddressOffset === BIOS_BANK_OFFSET && maskedAddress >= BIOS_INT_EMUL_LOAD_HOTSPOT && maskedAddress < BIOS_INT_EMUL_LOAD_HOTSPOT + 256) { loadPart(maskedAddress - BIOS_INT_EMUL_LOAD_HOTSPOT); } }; this.performBankSwitchOnMonitoredAccess = function(address) { maskedAddress = address & ADDRESS_MASK; address &= 0x1fff; // Set ControlRegister if the hotspot was triggered if (address === 0x1ff8) { setControlRegister(valueToWrite); return; } // Check for writes pending and watch for address transitions if (addressChangeCountdown > 0) { if (address !== lastAddress) { lastAddress = address; if (--addressChangeCountdown === 0) { // 5th address transition detected, perform write if ((address & CHIP_MASK) === CHIP_SELECT) { // Do not write outside Cartridge range // bank0 if (maskedAddress < BANK_SIZE) bytes[bank0AddressOffset + maskedAddress] = valueToWrite; // bank1 else if (bank1AddressOffset < BIOS_BANK_OFFSET) // Do not write to BIOS ROM bytes[bank1AddressOffset + maskedAddress - BANK_SIZE] = valueToWrite; } } } return; } // Check and store desired value to write if (((address & CHIP_MASK) === CHIP_SELECT) && maskedAddress <= 0x00ff) { valueToWrite = maskedAddress; if (writeEnabled) { lastAddress = address; // Will be watched for the 5th address change addressChangeCountdown = 5; } } }; var setControlRegister = function(controlRegister) { var banksConfig = (controlRegister >> 2) & 0x07; switch (banksConfig) { case 0: bank0AddressOffset = 2 * BANK_SIZE; bank1AddressOffset = BIOS_BANK_OFFSET; break; case 1: bank0AddressOffset = 0 * BANK_SIZE; bank1AddressOffset = BIOS_BANK_OFFSET; break; case 2: bank0AddressOffset = 2 * BANK_SIZE; bank1AddressOffset = 0 * BANK_SIZE; break; // as used in Commie Mutants and many others case 3: bank0AddressOffset = 0 * BANK_SIZE; bank1AddressOffset = 2 * BANK_SIZE; break; // as used in Suicide Mission case 4: bank0AddressOffset = 2 * BANK_SIZE; bank1AddressOffset = BIOS_BANK_OFFSET; break; case 5: bank0AddressOffset = 1 * BANK_SIZE; bank1AddressOffset = BIOS_BANK_OFFSET; break; case 6: bank0AddressOffset = 2 * BANK_SIZE; bank1AddressOffset = 1 * BANK_SIZE; break; // as used in Killer Satellites case 7: bank0AddressOffset = 1 * BANK_SIZE; bank1AddressOffset = 2 * BANK_SIZE; break; // as we use for 2k/4k ROM cloning } default: throw new Error("Invalid bank configuration"); } addressChangeCountdown = 0; // Setting ControlRegister cancels any pending write writeEnabled = (controlRegister & 0x02) !== 0; biosRomPower = (controlRegister & 0x01) === 0; // System.out.println("Banks: " + banksConfig + ", Writes: " + (writeEnabled ? "ON" : "OFF")); }; var loadPart = function(part) { var tapeRewound = false; do { // Check for tape end if (tapeOffset > rom.content.length - 1) { // Check if tape was already rewound once to avoid infinite tries if (tapeRewound) { if (part === 0) bus.getTia().getVideoOutput().showOSD("Could not load Tape from Start. Not a Start Tape ROM!", true); else bus.getTia().getVideoOutput().showOSD("Could not find next Part to load in Tape!", true); signalPartLoadedOK(false); // BIOS will handle this return; } // Rewind tape tapeOffset = 0; tapeRewound = true; } // Check if the next part is the one we are looking for if (jt.Cartridge8K_64K_AR.peekPartNoOnTape(rom.content, tapeOffset) === part) { if (part === 0) bus.getTia().getVideoOutput().showOSD("Loaded Tape from Start", true); else bus.getTia().getVideoOutput().showOSD("Loaded next Part from Tape", true); loadNextPart(); return; } else { // Advance tape tapeOffset += PART_SIZE; } } while(true); }; var loadNextPart = function() { loadHeaderData(); loadPagesIntoBanks(); patchPartDataIntoBIOS(); }; var loadHeaderData = function() { // Store header info jt.Util.arrayCopy(rom.content, tapeOffset + 4 * BANK_SIZE, header, 0, header.length); romStartupAddress = (header[1] << 8) | (header[0] & 0xff); romControlRegister = header[2]; romPageCount = header[3]; romChecksum = header[4]; romMultiLoadIndex = header[5]; romProgressBarSpeed = (header[7] << 8) | (header[6] & 0xff); romPageOffsets = jt.Util.arrayFill(new Array(romPageCount), 0); jt.Util.arrayCopy(header, 16, romPageOffsets, 0, romPageCount); }; var loadPagesIntoBanks = function() { // Clear last page of first bank, as per original BIOS jt.Util.arrayFillSegment(bytes, 7 * PAGE_SIZE, 8 * PAGE_SIZE - 1, 0); // Load pages var romOffset = tapeOffset; for (var i = 0, len = romPageOffsets.length; i < len; i++) { var pageInfo = romPageOffsets[i]; var bankOffset = (pageInfo & 0x03) * BANK_SIZE; var pageOffset = (pageInfo >> 2) * PAGE_SIZE; // Only write if not in BIOS area if (bankOffset + pageOffset + 255 < BIOS_BANK_OFFSET) jt.Util.arrayCopy(rom.content, romOffset, bytes, bankOffset + pageOffset, PAGE_SIZE); romOffset += PAGE_SIZE; } // Advance tape tapeOffset += PART_SIZE; }; var patchPartDataIntoBIOS = function() { // Patch BIOS interface area with correct values from stored Header data bytes[BIOS_BANK_OFFSET + BIOS_INT_CONTROL_REG_ADDR - 0xf800] = romControlRegister; bytes[BIOS_BANK_OFFSET + BIOS_INT_PART_NO_ADDR - 0xf800] = romMultiLoadIndex; bytes[BIOS_BANK_OFFSET + BIOS_INT_RANDOM_SEED_ADDR - 0xf800] = randomSeeds[currentRandomSeed++]; if (currentRandomSeed > 30) currentRandomSeed = 0; bytes[BIOS_BANK_OFFSET + BIOS_INT_START_ADDR - 0xf800] = romStartupAddress & 0xff; bytes[BIOS_BANK_OFFSET + BIOS_INT_START_ADDR + 1 - 0xf800] = (romStartupAddress >> 8) & 0xff; signalPartLoadedOK(true); }; var signalPartLoadedOK = function(ok) { bytes[BIOS_BANK_OFFSET + BIOS_INT_PART_LOADED_OK - 0xf800] = (ok ? 1 : 0); }; var loadBIOS = function() { var bios = jt.Util.uncompressStringBase64ToInt8BitArray(STARPATH_BIOS); jt.Util.arrayCopy(bios, 0, bytes, BIOS_BANK_OFFSET, BANK_SIZE); }; var bus; var bytes; var bank0AddressOffset = 0; var bank1AddressOffset = 0; var valueToWrite = 0; var writeEnabled = false; var lastAddress = -1; var addressChangeCountdown = 0; var biosRomPower = false; var romStartupAddress = 0; var romControlRegister = 0; var romPageCount = 0; var romChecksum = 0; var romMultiLoadIndex = 0; var romProgressBarSpeed = 0; var romPageOffsets; var randomSeeds = new Array(31); // Circular Random seeds pre-determined at init() and preserved at saveStates to avoid indeterminism var currentRandomSeed = 0; var tapeOffset = 0; var HEADER_SIZE = 256; var header = jt.Util.arrayFill(new Array(HEADER_SIZE), 0); // local buffer, not part of the state var maskedAddress; var BIOS_INT_PART_NO_ADDR = 0xfb00; var BIOS_INT_CONTROL_REG_ADDR = 0xfb01; var BIOS_INT_START_ADDR = 0xfb02; var BIOS_INT_RANDOM_SEED_ADDR = 0xfb04; var BIOS_INT_PART_LOADED_OK = 0xfb05; var BIOS_INT_EMUL_LOAD_HOTSPOT = 0x0c00; var PAGE_SIZE = 256; var BANK_SIZE = 8 * PAGE_SIZE; var BIOS_BANK_OFFSET = 3 * BANK_SIZE; var PART_SIZE = 4 * BANK_SIZE + HEADER_SIZE; // 4 * 2048 banks + header // Bios is 2048 bytes. This is compressed (zip) and stored in base64 var STARPATH_BIOS = "7dSxCsIwEAbgv6niGkeddPVZ8kCOXc43yCIokkGIUN+gLxAoZHTxHRxjYq2xk7vSIPS75bb7uYNTuOJWu/bod3iU42BzUTiBe9sTzSj" + "ToBnNBVxfQz/nQ+2NhA2a05KYmhhjmxhoQZymxGil8gpeesOdyioW5DN25yxsiri3chQOUO1WeCSI/hPx9AJ/m/576KROMUhlfdE4dQ+AfJoPNBikgOZdLw=="; var ADDRESS_MASK = 0x0fff; var CHIP_MASK = 0x1000; var CHIP_SELECT = 0x1000; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(true), // ROM contents needed for later part loads b: jt.Util.compressInt8BitArrayToStringBase64(bytes), b0o: bank0AddressOffset, b1o: bank1AddressOffset, vw: valueToWrite, we: writeEnabled, la: lastAddress, ac: addressChangeCountdown, bp: biosRomPower, rs: romStartupAddress, rc: romControlRegister, rp: romPageCount, rk: romChecksum, rm: romMultiLoadIndex, rb: romProgressBarSpeed, ro: romPageOffsets, to: tapeOffset, rnd: jt.Util.storeInt8BitArrayToStringBase64(randomSeeds), rnc: currentRandomSeed }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bank0AddressOffset = state.b0o; bank1AddressOffset = state.b1o; valueToWrite = state.vw; writeEnabled = state.we; lastAddress = state.la; addressChangeCountdown = state.ac; biosRomPower = state.bp; romStartupAddress = state.rs; romControlRegister = state.rc; romPageCount = state.rp; romChecksum = state.rk; romMultiLoadIndex = state.rm; romProgressBarSpeed = state.rb; romPageOffsets = state.ro; tapeOffset = state.to; jt.Util.restoreStringBase64ToInt8BitArray(state.rnd, randomSeeds); currentRandomSeed = state.rnc; }; if (rom) init(this); }; jt.Cartridge8K_64K_AR.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_64K_AR.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_64K_AR(); cart.loadState(state); return cart; }; jt.Cartridge8K_64K_AR.HEADER_SIZE = 256; jt.Cartridge8K_64K_AR.PAGE_SIZE = 256; jt.Cartridge8K_64K_AR.BANK_SIZE = 8 * jt.Cartridge8K_64K_AR.PAGE_SIZE; jt.Cartridge8K_64K_AR.PART_SIZE = 4 * jt.Cartridge8K_64K_AR.BANK_SIZE + jt.Cartridge8K_64K_AR.HEADER_SIZE; // 4 * 2048 banks + header jt.Cartridge8K_64K_AR.peekPartNoOnTape = function(tapeContent, tapeOffset) { return tapeContent[tapeOffset + 4*jt.Cartridge8K_64K_AR.BANK_SIZE + 5]; }; jt.Cartridge8K_64K_AR.checkTape = function(rom) { if (jt.Cartridge8K_64K_AR.peekPartNoOnTape(rom.content, 0) === 0) return true; jt.Util.warning("Wrong Supercharger Tape Part ROM! Please load a Full Tape ROM file"); return false; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_E0.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K "E0" Parker Bros. format jt.Cartridge8K_E0 = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { var maskedAddress = maskAddress(address); // Always add the correct offset to access bank selected on the corresponding slice if (maskedAddress < 0x0400) // Slice 0 return bytes[slice0AddressOffset + maskedAddress]; if (maskedAddress < 0x0800) // Slice 1 return bytes[slice1AddressOffset + maskedAddress - 0x0400]; if (maskedAddress < 0x0c00) // Slice 2 return bytes[slice2AddressOffset + maskedAddress - 0x0800]; // Slice 3 (0x0c00 - 0x0fff) is always at 0x1c00 (bank 7) return bytes[0x1000 + maskedAddress]; }; this.write = function(address, val) { maskAddress(address); // Writing to ROMs is possible, but nothing is changed }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check if address is within range of bank selection if (maskedAddress >= 0x0fe0 && maskedAddress <= 0x0ff7) { // Each bank is 0x0400 bytes each, 0 to 7 if (/* maskedAddress >= 0x0fe0 && */ maskedAddress <= 0x0fe7) // Slice 0 bank selection slice0AddressOffset = (maskedAddress - 0x0fe0) * 0x0400; else if (/* maskedAddress >= 0x0fe8 && */ maskedAddress <= 0x0fef) // Slice 1 bank selection slice1AddressOffset = (maskedAddress - 0x0fe8) * 0x0400; else if (/* maskedAddress >= 0x0ff0 && */ maskedAddress <= 0x0ff7) // Slice 2 bank selection slice2AddressOffset = (maskedAddress - 0x0ff0) * 0x0400; } return maskedAddress; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), s0: slice0AddressOffset, s1: slice1AddressOffset, s2: slice2AddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; slice0AddressOffset = state.s0; slice1AddressOffset = state.s1; slice2AddressOffset = state.s2; }; var bytes; var slice0AddressOffset = 0; var slice1AddressOffset = 0; var slice2AddressOffset = 0; // Slice 3 is fixed at bank 7 var ADDRESS_MASK = 0x0fff; if (rom) init(this); }; jt.Cartridge8K_E0.prototype = jt.Cartridge.base; jt.Cartridge8K_E0.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_E0(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_FE.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K "FE" Robotank/Decathlon format jt.Cartridge8K_FE = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { var maskedAddress = maskAddress(address); return bytes[bankAddressOffset + maskedAddress]; }; this.write = function(address, val) { maskAddress(address); // Writing to ROMs is possible, but nothing is changed }; var maskAddress = function(address) { // Bankswitching: Look at the address to determine the correct bank to be if ((address & 0x2000) !== 0) { // Check bit 13. Address is like Fxxx or Dxxx? if (bankAddressOffset !== 0) bankAddressOffset = 0; } else { if (bankAddressOffset != BANK_SIZE) bankAddressOffset = BANK_SIZE; } return address & ADDRESS_MASK; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; }; var bytes; var bankAddressOffset = 0; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; if (rom) init(this); }; jt.Cartridge8K_FE.prototype = jt.Cartridge.base; jt.Cartridge8K_FE.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_FE(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/Cartridge8K_UA.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements the 8K "UA" UA Limited format jt.Cartridge8K_UA = function(rom, format) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; } this.read = function(address) { // Always add the correct offset to access bank selected return bytes[bankAddressOffset + (address & ADDRESS_MASK)]; }; this.performBankSwitchOnMonitoredAccess = function(address) { if (address === 0x0220) { if (bankAddressOffset !== 0) bankAddressOffset = 0; } else if (address === 0x0240) { if (bankAddressOffset !== BANK_SIZE) bankAddressOffset = BANK_SIZE; } }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; }; var bytes; var bankAddressOffset = 0; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; if (rom) init(this); }; jt.Cartridge8K_UA.prototype = jt.CartridgeBankedByBusMonitoring.base; jt.Cartridge8K_UA.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.Cartridge8K_UA(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/cartridge/formats/CartridgeBankedByBusMonitoring.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Implements generic bank switching using unmasked address access via bus monitoring (outside Cart area) jt.CartridgeBankedByBusMonitoring = function(rom, format) { "use strict"; this.needsBusMonitoring = function() { return true; }; this.monitorBusBeforeRead = function(address) { this.performBankSwitchOnMonitoredAccess(address) }; this.monitorBusBeforeWrite = function(address, data) { this.performBankSwitchOnMonitoredAccess(address) }; this.performBankSwitchOnMonitoredAccess = function(address) { }; }; jt.CartridgeBankedByBusMonitoring.prototype = jt.Cartridge.base; jt.CartridgeBankedByBusMonitoring.base = new jt.CartridgeBankedByBusMonitoring(); ================================================ FILE: src/main/atari/cartridge/formats/CartridgeBankedByMaskedRange.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. /** * Implements the simple bank switching method by masked address range access (within Cart area) * Supports SuperChip extra RAM (ON/OFF/AUTO). * Used by several n * 4K bank formats with varying extra RAM sizes */ jt.CartridgeBankedByMaskedRange = function(rom, format, pBaseBankSwitchAddress, superChip, pExtraRAMSize) { "use strict"; function init(self) { self.rom = rom; self.format = format; bytes = rom.content; // uses the content of the ROM directly self.bytes = bytes; var numBanks = bytes.length / BANK_SIZE; baseBankSwitchAddress = pBaseBankSwitchAddress; topBankSwitchAddress = baseBankSwitchAddress + numBanks - 1; extraRAMSize = pExtraRAMSize; // SuperChip mode. null = automatic mode if (superChip == null || superChip == undefined) { superChipMode = false; superChipAutoDetect = true; } else { superChipMode = !!superChip; superChipAutoDetect = false; } extraRAM = superChip !== false ? jt.Util.arrayFill(new Array(extraRAMSize), 0) : null; } this.read = function(address) { var maskedAddress = maskAddress(address); // Check for SuperChip Extra RAM reads if (superChipMode && (maskedAddress >= extraRAMSize) && (maskedAddress < extraRAMSize * 2)) return extraRAM[maskedAddress - extraRAMSize]; else // Always add the correct offset to access bank selected return bytes[bankAddressOffset + maskedAddress]; }; this.write = function(address, val) { var maskedAddress = maskAddress(address); // Check for Extra RAM writes and then turn superChip mode on if (maskedAddress < extraRAMSize && (superChipMode || superChipAutoDetect)) { if (!superChipMode) superChipMode = true; extraRAM[maskedAddress] = val; } }; var maskAddress = function(address) { var maskedAddress = address & ADDRESS_MASK; // Check and perform bank-switch as necessary if (maskedAddress >= baseBankSwitchAddress && maskedAddress <= topBankSwitchAddress) bankAddressOffset = BANK_SIZE * (maskedAddress - baseBankSwitchAddress); return maskedAddress; }; // Savestate ------------------------------------------- this.saveState = function() { return { f: this.format.name, r: this.rom.saveState(), b: jt.Util.compressInt8BitArrayToStringBase64(bytes), bo: bankAddressOffset, bb: baseBankSwitchAddress, es: extraRAMSize, tb: topBankSwitchAddress, s: superChipMode | 0, sa: superChipAutoDetect | 0, e: extraRAM && jt.Util.compressInt8BitArrayToStringBase64(extraRAM) }; }; this.loadState = function(state) { this.format = jt.CartridgeFormats[state.f]; this.rom = jt.ROM.loadState(state.r); bytes = jt.Util.uncompressStringBase64ToInt8BitArray(state.b, bytes); this.bytes = bytes; bankAddressOffset = state.bo; baseBankSwitchAddress = state.bb; extraRAMSize = state.es; topBankSwitchAddress = state.tb; superChipMode = !!state.s; superChipAutoDetect = !!state.sa; extraRAM = state.e && jt.Util.uncompressStringBase64ToInt8BitArray(state.e, extraRAM); }; var bytes; var bankAddressOffset = 0; var baseBankSwitchAddress; var topBankSwitchAddress; var superChipMode = false; var superChipAutoDetect; var extraRAMSize; var extraRAM; var ADDRESS_MASK = 0x0fff; var BANK_SIZE = 4096; if (rom) init(this); }; jt.CartridgeBankedByMaskedRange.prototype = jt.Cartridge.base; jt.CartridgeBankedByMaskedRange.recreateFromSaveState = function(state, prevCart) { var cart = prevCart || new jt.CartridgeBankedByMaskedRange(); cart.loadState(state); return cart; }; ================================================ FILE: src/main/atari/console/AtariConsole.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.AtariConsole = function(mainVideoClock) { "use strict"; var self = this; function init() { mainComponentsCreate(); socketsCreate(); } this.socketsConnected = function() { setDefaults(); }; this.powerOn = function(fromState) { if (this.powerIsOn) this.powerOff(); bus.powerOn(); this.powerIsOn = true; consoleControlsSocket.controlsStatesRedefined(); updateVideoSynchronization(); videoStandardAutoDetectionStart(); if (!fromState) consoleControlsSocket.firePowerAndUserPauseStateUpdate(); // loadState will fire it }; this.powerOff = function() { bus.powerOff(); this.powerIsOn = false; // consoleControlsSocket.releaseControllers(); TODO Really needed? Causing problems... consoleControlsSocket.controlsStatesRedefined(); if (userPaused) this.userPause(false); else consoleControlsSocket.firePowerAndUserPauseStateUpdate(); }; this.userPowerOn = function() { if (isLoading) return; this.powerOn(); if (!bus.getCartridge()) this.showOSD("NO CARTRIDGE INSERTED!", false, true); }; this.setLoading = function(state) { isLoading = state; }; this.userPause = function(pause, keepAudio) { var prev = userPaused; if (userPaused !== pause) { userPaused = !!pause; userPauseMoreFrames = -1; if (userPaused && !keepAudio) audioSocket.muteAudio(); else audioSocket.unMuteAudio(); consoleControlsSocket.firePowerAndUserPauseStateUpdate(); } return prev; }; this.systemPause = function(val) { var prev = systemPaused; if (systemPaused !== val) { systemPaused = !!val; if (systemPaused) audioSocket.pauseAudio(); else audioSocket.unpauseAudio(); } return prev; }; this.isSystemPaused = function() { return systemPaused; }; this.videoClockPulse = function() { // Video clock will be the Tia Frame video clock (60Hz/50Hz) // CPU and other clocks (Pia, Audio) will be sent by the Tia this.videoClockPulseApplyPulldowns(self.videoClockPulseGetNextPulldowns()); }; this.videoClockPulseApplyPulldowns = function(pulls) { if (!self.powerIsOn) return; while(pulls-- > 0) videoFrame(); // Finish audio signal (generate any missing samples to adjust to sample rate) if (!userPaused) audioSocket.audioFinishFrame(); }; this.videoClockPulseGetNextPulldowns = function() { // Simple pulldown with 1:1 cadence if (videoPulldown.steps === 1) return 1; // Complex pulldown if (--videoPulldownStep < 0) videoPulldownStep = videoPulldown.steps - 1; return videoPulldown.cadence[videoPulldownStep]; }; function videoFrame() { if (userPaused && userPauseMoreFrames-- <= 0) return; if (videoStandardAutoDetectionInProgress) videoStandardAutoDetectionTry(); tia.frame(); } this.getCartridgeSocket = function() { return cartridgeSocket; }; this.getConsoleControlsSocket = function() { return consoleControlsSocket; }; this.getVideoOutput = function() { return tia.getVideoOutput(); }; this.getAudioOutput = function() { return tia.getAudioOutput(); }; this.getSavestateSocket = function() { return saveStateSocket; }; this.getVideoClockSocket = function() { return videoClockSocket; }; this.getAudioSocket = function() { return audioSocket; }; this.showOSD = function(message, overlap, error) { this.getVideoOutput().showOSD(message, overlap, error); }; this.vSynchSetSupported = function(boo) { // To be called once and only by Room during Native Video Freq detection var user = Javatari.userPreferences.current.vSynch; vSynchMode = Javatari.SCREEN_VSYNCH_MODE !== -1 && boo ? Javatari.SCREEN_VSYNCH_MODE >= 0 ? Javatari.SCREEN_VSYNCH_MODE : user !== null && user >= 0 ? user : 1 : -1; }; function vSynchToggleMode() { if (vSynchMode === -1) { self.showOSD("V-Synch is DISABLED / UNSUPPORTED", true, true); return; } vSynchMode = vSynchMode ? 0 : 1; updateVideoSynchronization(); self.showOSD("V-Synch: " + (vSynchMode ? "ON" : "OFF"), true); // Persist Javatari.userPreferences.current.vSynch = vSynchMode; Javatari.userPreferences.setDirty(); Javatari.userPreferences.save(); } var setCartridge = function(cartridge) { Javatari.cartridge = cartridge; var removedCartridge = getCartridge(); bus.setCartridge(cartridge); cartridgeSocket.cartridgeInserted(cartridge, removedCartridge); }; var getCartridge = function() { return bus.getCartridge(); }; var setVideoStandard = function (pVideoStandard) { if (videoStandard !== pVideoStandard) { videoStandard = pVideoStandard; tia.setVideoStandard(videoStandard); updateVideoSynchronization(); } }; function showVideoStandardMessage() { self.showOSD((videoStandardIsAuto ? "AUTO: " : "") + videoStandard.name, true); } var setVideoStandardAuto = function(state) { videoStandardIsAuto = state; if (state) { if (self.powerIsOn) videoStandardAutoDetectionStart(); else setVideoStandard(jt.VideoStandard.NTSC); } }; var videoStandardAutoDetectionStart = function() { if (!videoStandardIsAuto || videoStandardAutoDetectionInProgress) return; // If no Cartridge present, use NTSC if (!bus.getCartridge()) { setVideoStandard(jt.VideoStandard.NTSC); return; } // Otherwise use the VideoStandard detected by the monitor if (!tia.getVideoOutput().monitor) return; videoStandardAutoDetectionInProgress = true; videoStandardAutoDetectionTries = 0; tia.getVideoOutput().monitor.videoStandardDetectionStart(); }; var videoStandardAutoDetectionTry = function() { videoStandardAutoDetectionTries++; var standard = tia.getVideoOutput().monitor.getVideoStandardDetected(); if (!standard && videoStandardAutoDetectionTries < VIDEO_STANDARD_AUTO_DETECTION_FRAMES) return; if (standard) { if (standard !== videoStandard) { setVideoStandard(standard); showVideoStandardMessage(); } } else self.showOSD("AUTO: FAILED", true, true); videoStandardAutoDetectionInProgress = false; }; var setVideoStandardForced = function(forcedVideoStandard) { videoStandardIsAuto = false; setVideoStandard(forcedVideoStandard); }; function updateVideoSynchronization() { // According to the native video frequency detected, target Video Standard and vSynchMode, use a specific pulldown configuration if (vSynchMode === 1) { // ON // Will V-synch to host freq if detected and supported, or use optimal timer configuration) videoPulldown = videoStandard.pulldowns[videoClockSocket.getVSynchNativeFrequency()] || videoStandard.pulldowns.TIMER; } else { // OFF, DISABLED // No V-synch. Always use the optimal timer configuration) videoPulldown = videoStandard.pulldowns.TIMER; } videoPulldownStep = 0; videoClockUpdateSpeed(); //console.error("Update Synchronization: " + videoPulldown.frequency); } var powerFry = function() { ram.powerFry(); saveStateSocket.externalStateChange(); }; var cycleCartridgeFormat = function() { }; var saveState = function(extended) { var s = { t: tia.saveState(extended), p: pia.saveState(), r: ram.saveState(), b: bus.saveState(), c: cpu.saveState(), ca: getCartridge() && getCartridge().saveState(), vsa: videoStandardIsAuto, vs: videoStandard.name }; if (extended) { s.pw = self.powerIsOn; s.up = userPaused; s.upf = userPauseMoreFrames; } return s; }; this.saveState = saveState; var loadState = function(s) { // Extended if (s.pw !== undefined) if (self.powerIsOn !== s.pw) s.pw ? self.powerOn() : self.powerOff(); if (s.up !== undefined) self.userPause(s.up); if (s.upf !== undefined) userPauseMoreFrames = s.upf; // Normal videoClockUpdateSpeed(); tia.loadState(s.t); pia.loadState(s.p); ram.loadState(s.r); if (s.b) bus.loadState(s.b); cpu.loadState(s.c); setCartridge(s.ca && jt.CartridgeCreator.recreateCartridgeFromSaveState(s.ca, getCartridge())); if (s.vsa !== undefined) setVideoStandardAuto(s.vsa); setVideoStandard(jt.VideoStandard[s.vs]); consoleControlsSocket.firePowerAndUserPauseStateUpdate(); consoleControlsSocket.controlsStatesRedefined(); saveStateSocket.externalStateChange(); }; this.loadState = loadState; function setDefaults() { setVideoStandardAuto(true); speedControl = 1; alternateSpeed = null; videoClockUpdateSpeed(); tia.debug(0); tia.debugNoCollisions(false); } function videoClockUpdateSpeed() { videoClockSocket.setVSynch(vSynchMode === 1); var hostFreq = (videoPulldown.frequency * (alternateSpeed || speedControl)) | 0; videoClockSocket.setFrequency(hostFreq, videoPulldown.divider); audioSocket.setFps(hostFreq / videoPulldown.divider); } var mainComponentsCreate = function() { cpu = new jt.M6502(); pia = new jt.Pia(); tia = new jt.Tia(cpu, pia); self.tia = tia; ram = new jt.Ram(); bus = new jt.Bus(cpu, tia, pia, ram); }; var socketsCreate = function() { videoClockSocket = new VideoClockSocket(); consoleControlsSocket = new ConsoleControlsSocket(); cartridgeSocket = new CartridgeSocket(); saveStateSocket = new SaveStateSocket(); audioSocket = new AudioSocket(); tia.getAudioOutput().connectAudioSocket(audioSocket); }; this.powerIsOn = false; var isLoading = false; var userPaused = false; var userPauseMoreFrames = 0; var systemPaused = false; var speedControl = 1; var alternateSpeed = false; var cpu; var pia; var tia; var ram; var bus; var videoStandard; var videoPulldown, videoPulldownStep; var videoClockSocket; var consoleControlsSocket; var cartridgeSocket; var saveStateSocket; var audioSocket; var videoStandardIsAuto = false; var videoStandardAutoDetectionInProgress = false; var videoStandardAutoDetectionTries = 0; var vSynchMode = -1; var VIDEO_STANDARD_AUTO_DETECTION_FRAMES = 90; var SPEEDS = [ 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 2, 3, 5, 10 ]; var SPEED_FAST = 10, SPEED_SLOW = 0.3; // Controls interface -------------------------------------------- var controls = jt.ConsoleControls; this.controlStateChanged = function (control, state) { // Normal state controls if (control === controls.FAST_SPEED) { if (state && alternateSpeed !== SPEED_FAST) { alternateSpeed = SPEED_FAST; videoClockUpdateSpeed(); self.showOSD("FAST FORWARD", true); } else if (!state && alternateSpeed === SPEED_FAST) { alternateSpeed = null; videoClockUpdateSpeed(); self.showOSD(null, true); } return; } if (control === controls.SLOW_SPEED) { if (state && alternateSpeed !== SPEED_SLOW) { alternateSpeed = SPEED_SLOW; videoClockUpdateSpeed(); self.showOSD("SLOW MOTION", true); } else if (!state && alternateSpeed === SPEED_SLOW) { alternateSpeed = null; videoClockUpdateSpeed(); self.showOSD(null, true); } return; } // Toggles if (!state) return; switch (control) { case controls.POWER: if (self.powerIsOn) self.powerOff(); else self.userPowerOn(); break; case controls.POWER_OFF: if (self.powerIsOn) self.powerOff(); break; case controls.POWER_FRY: powerFry(); break; case controls.PAUSE: self.userPause(!userPaused, false); self.getVideoOutput().showOSD(userPaused ? "PAUSE" : "RESUME", true); return; case controls.PAUSE_AUDIO_ON: self.userPause(!userPaused, true); self.getVideoOutput().showOSD(userPaused ? "PAUSE with AUDIO ON" : "RESUME", true); return; case controls.FRAME: if (userPaused) userPauseMoreFrames = 1; return; case controls.INC_SPEED: case controls.DEC_SPEED: case controls.NORMAL_SPEED: case controls.MIN_SPEED: var speedIndex = SPEEDS.indexOf(speedControl); if (control === controls.INC_SPEED && speedIndex < SPEEDS.length - 1) ++speedIndex; else if (control === controls.DEC_SPEED && speedIndex > 0) --speedIndex; else if (control === controls.MIN_SPEED) speedIndex = 0; else if (control === controls.NORMAL_SPEED) speedIndex = SPEEDS.indexOf(1); speedControl = SPEEDS[speedIndex]; self.showOSD("Speed: " + ((speedControl * 100) | 0) + "%", true); videoClockUpdateSpeed(); break; case controls.SAVE_STATE_0: case controls.SAVE_STATE_1: case controls.SAVE_STATE_2: case controls.SAVE_STATE_3: case controls.SAVE_STATE_4: case controls.SAVE_STATE_5: case controls.SAVE_STATE_6: case controls.SAVE_STATE_7: case controls.SAVE_STATE_8: case controls.SAVE_STATE_9: case controls.SAVE_STATE_10: case controls.SAVE_STATE_11: case controls.SAVE_STATE_12: var wasPaused = self.systemPause(true); saveStateSocket.saveState(control & 0xff); // get binary encoded slot number if (!wasPaused) self.systemPause(false); break; case controls.SAVE_STATE_FILE: wasPaused = self.systemPause(true); saveStateSocket.saveStateFile(); if (!wasPaused) self.systemPause(false); break; case controls.LOAD_STATE_0: case controls.LOAD_STATE_1: case controls.LOAD_STATE_2: case controls.LOAD_STATE_3: case controls.LOAD_STATE_4: case controls.LOAD_STATE_5: case controls.LOAD_STATE_6: case controls.LOAD_STATE_7: case controls.LOAD_STATE_8: case controls.LOAD_STATE_9: case controls.LOAD_STATE_10: case controls.LOAD_STATE_11: case controls.LOAD_STATE_12: wasPaused = self.systemPause(true); saveStateSocket.loadState(control & 0xff); // get binary encoded slot number if (!wasPaused) self.systemPause(false); break; case controls.VIDEO_STANDARD: if (videoStandardIsAuto) setVideoStandardForced(jt.VideoStandard.NTSC); else if (videoStandard == jt.VideoStandard.NTSC) setVideoStandardForced(jt.VideoStandard.PAL); else setVideoStandardAuto(true); showVideoStandardMessage(); break; case controls.VSYNCH: vSynchToggleMode(); break; case controls.CARTRIDGE_FORMAT: cycleCartridgeFormat(); break; case controls.DEFAULTS: setDefaults(); self.showOSD("Default Settings", true); break; } }; this.controlsStateReport = function (report) { // Only Power Control is visible from outside report[controls.POWER] = self.powerIsOn; }; // Video Clock Socket ----------------------------------------- function VideoClockSocket() { this.connectClock = function(clock) { videoClock = clock; }; this.getVSynchNativeFrequency = function() { return videoClock.getVSynchNativeFrequency(); }; this.setVSynch = function(state) { videoClock.setVSynch(state); }; this.setFrequency = function(freq, div) { videoClock.setFrequency(freq, div); }; var videoClock; } // CartridgeSocket ----------------------------------------- function CartridgeSocket() { this.insert = function (cartridge, autoPower) { if (autoPower && self.powerIsOn) self.powerOff(); setCartridge(cartridge); if (autoPower && !self.powerIsOn) self.powerOn(); saveStateSocket.externalStateChange(); }; this.inserted = function () { return getCartridge(); }; this.cartridgeInserted = function (cartridge, removedCartridge) { tia.getAudioOutput().cartridgeInserted(cartridge, removedCartridge); consoleControlsSocket.cartridgeInserted(cartridge, removedCartridge); saveStateSocket.cartridgeInserted(cartridge, removedCartridge); tia.getVideoOutput().monitor.cartridgeInserted(cartridge, removedCartridge); }; // Data operations unavailable this.loadCartridgeData = function (port, name, arrContent) { // would need: saveStateSocket.externalStateChange(); }; this.saveCartridgeDataFile = function (port) { }; } // ConsoleControlsSocket ----------------------------------------- function ConsoleControlsSocket() { this.connectControls = function(pControls) { controls = pControls; }; this.cartridgeInserted = function(cartridge, removedCartridge) { if (controls) controls.cartridgeInserted(cartridge, removedCartridge); }; this.controlStateChanged = function(control, state) { self.controlStateChanged(control, state); pia.controlStateChanged(control, state); tia.controlStateChanged(control, state); tia.getVideoOutput().monitor.controlStateChanged(control, state); }; this.controlValueChanged = function(control, position) { tia.controlValueChanged(control, position); }; this.controlsStateReport = function(report) { self.controlsStateReport(report); pia.controlsStateReport(report); }; this.controlsStatesRedefined = function() { tia.getVideoOutput().monitor.controlsStatesRedefined(); }; this.firePowerAndUserPauseStateUpdate = function() { controls.consolePowerAndUserPauseStateUpdate(self.powerIsOn, userPaused); tia.getVideoOutput().monitor.consolePowerAndUserPauseStateUpdate(self.powerIsOn, userPaused); }; this.releaseControllers = function() { controls.releaseControllers(); }; this.controlsClockPulse = function() { controls.controlsClockPulse(); }; this.getControlReport = function(control) { switch(control) { case jt.ConsoleControls.VIDEO_STANDARD: return { label: videoStandardIsAuto ? "Auto" : videoStandard.name, active: !videoStandardIsAuto }; case jt.ConsoleControls.VSYNCH: return { label: vSynchMode === -1 ? "DISABL" : vSynchMode ? "ON" : "OFF", active: vSynchMode === 1 }; case jt.ConsoleControls.NO_COLLISIONS: return { label: tia.getDebugNoCollisions() ? "ON" : "OFF", active: tia.getDebugNoCollisions() }; default: return { label: "Unknown", active: false }; } }; var controls; } // SavestateSocket ----------------------------------------- function SaveStateSocket() { this.connectMedia = function(pMedia) { media = pMedia; }; this.getMedia = function() { return media; }; this.cartridgeInserted = function(cartridge) { if (cartridge) cartridge.connectSaveStateSocket(this); }; this.externalStateChange = function() { media.externalStateChange(); }; this.saveState = function(slot) { if (!self.powerIsOn) return; var state = saveState(); state.v = VERSION; if (media.saveState(slot, state)) self.showOSD("State " + slot + " saved", true); else self.showOSD("State " + slot + " save failed", true); }; this.loadState = function(slot) { var state = media.loadState(slot); if (!state) { self.showOSD("State " + slot + " not found", true); return; } if (state.v !== VERSION) { self.showOSD("State " + slot + " load failed, wrong version", true); return; } if (!self.powerIsOn) self.powerOn(true); // true = from state loading loadState(state); self.showOSD("State " + slot + " loaded", true); }; this.saveStateFile = function() { if (!self.powerIsOn) return; // Use Cartrige label as file name var fileName = cartridgeSocket.inserted() && cartridgeSocket.inserted().rom.info.l; var state = saveState(); state.v = VERSION; if (media.saveStateFile(fileName, state)) self.showOSD("State Cartridge saved", true); else self.showOSD("State file save failed", true); }; this.loadStateFile = function(data) { // Return true if data was indeed a SaveState var state = media.loadStateFile(data); if (!state) return; if (state.v !== VERSION) { self.showOSD("State file load failed, wrong version", true); return true; } if (!self.powerIsOn) self.powerOn(); loadState(state); self.showOSD("State file loaded", true); return true; }; var media; var VERSION = 2; } // Audio Socket --------------------------------------------- function AudioSocket() { this.connectMonitor = function (pMonitor) { monitor = pMonitor; for (var i = signals.length - 1; i >= 0; i--) monitor.connectAudioSignal(signals[i]); }; this.connectAudioSignal = function(signal) { if (signals.indexOf(signal) >= 0) return; jt.Util.arrayAdd(signals, signal); this.flushAllSignals(); // To always keep signals in synch signal.setFps(fps); if (monitor) monitor.connectAudioSignal(signal); }; this.disconnectAudioSignal = function(signal) { jt.Util.arrayRemoveAllElement(signals, signal); if (monitor) monitor.disconnectAudioSignal(signal); }; this.audioClockPulse = function() { for (var i = signals.length - 1; i >= 0; --i) signals[i].audioClockPulse(); }; this.audioFinishFrame = function() { for (var i = signals.length - 1; i >= 0; --i) signals[i].audioFinishFrame(); }; this.muteAudio = function() { if (monitor) monitor.mute(); }; this.unMuteAudio = function() { if (monitor) monitor.unMute(); }; this.setFps = function(pFps) { fps = pFps; for (var i = signals.length - 1; i >= 0; --i) signals[i].setFps(fps); }; this.pauseAudio = function() { if (monitor) monitor.pause(); }; this.unpauseAudio = function() { if (monitor) monitor.unpause(); }; this.flushAllSignals = function() { for (var i = signals.length - 1; i >= 0; --i) signals[i].flush(); }; var signals = []; var monitor; var fps; } // Debug methods ------------------------------------------------------ this.eval = function(str) { return eval(str); }; init(); }; ================================================ FILE: src/main/atari/console/Bus.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Bus = function(pCpu, pTia, pPia, pRam) { "use strict"; function init(self) { cpu = pCpu; tia = pTia; pia = pPia; ram = pRam; cpu.connectBus(self); tia.connectBus(self); pia.connectBus(self); } this.powerOn = function() { // Power on devices connected to the BUS if (cartridge != null) cartridge.powerOn(); ram.powerOn(); pia.powerOn(); cpu.powerOn(); tia.powerOn(); }; this.powerOff = function() { tia.powerOff(); cpu.powerOff(); pia.powerOff(); ram.powerOff(); }; this.setCartridge = function(pCartridge) { cartridge = pCartridge; if (cartridge) { data = 0; cartridge.connectBus(this); } cartridgeNeedsBusMonitoring = cartridge && cartridge.needsBusMonitoring(); }; this.getCartridge = function() { return cartridge; }; this.getTia = function() { return tia; }; this.clockPulse = function() { pia.clockPulse(); cpu.clockPulse(); }; this.read = function(address) { // CART Bus monitoring if (cartridgeNeedsBusMonitoring) cartridge.monitorBusBeforeRead(address); if ((address & CART_MASK) === CART_SELECT) { if (cartridge) return data = cartridge.read(address); else return data; } else if ((address & RAM_MASK) === RAM_SELECT) { return data = ram.read(address); } else if ((address & PIA_MASK) === PIA_SELECT) { return data = pia.read(address); } else { // Only bit 7 and 6 are connected to TIA read registers. return data = data & 0x3f | tia.read(address); // Use the retained data for bits 5-0 } }; this.write = function(address, val) { // CART Bus monitoring if (cartridgeNeedsBusMonitoring) cartridge.monitorBusBeforeWrite(address, val); data = val; if ((address & TIA_MASK) === TIA_SELECT) tia.write(address, val); else if ((address & RAM_MASK) === RAM_SELECT) ram.write(address, val); else if ((address & PIA_MASK) === PIA_SELECT) pia.write(address, val); else if (cartridge) cartridge.write(address, val); }; // Savestate ------------------------------------------- this.saveState = function() { return { d: data }; }; this.loadState = function(state) { data = state.d; }; var cpu; var tia; var pia; var ram; var cartridge; var cartridgeNeedsBusMonitoring = false; var data = (Math.random()* 256) | 0; // Comes random ate creation! var CART_MASK = 0x1000; var CART_SELECT = 0x1000; var RAM_MASK = 0x1280; var RAM_SELECT = 0x0080; var TIA_MASK = 0x1080; var TIA_SELECT = 0x0000; var PIA_MASK = 0x1280; var PIA_SELECT = 0x0280; init(this); }; ================================================ FILE: src/main/atari/controls/ConsoleControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.ConsoleControls = { // CAUTION: cannot use 0 or falsy values for controls JOY0_UP: 11, JOY0_DOWN: 12, JOY0_LEFT: 13, JOY0_RIGHT: 14, JOY0_BUTTON: 15, JOY1_UP: 21, JOY1_DOWN: 22, JOY1_LEFT: 23, JOY1_RIGHT: 24, JOY1_BUTTON: 25, PADDLE0_BUTTON: 41, PADDLE1_BUTTON: 42, PADDLE0_POSITION: 16384, PADDLE1_POSITION: 16384 + 512, // Value controls (not press). Value will be from 380 (Left) to 190 (Center) to 0 (Right); -1 = disconnected, won't charge POTs POWER: 51, BLACK_WHITE: 52, SELECT: 53, RESET: 54, DIFFICULTY0: 55, DIFFICULTY1: 56, POWER_OFF: 57, POWER_FRY: 58, CARTRIDGE_FORMAT: 91, DEBUG: 101, TRACE: 102, SHOW_INFO: 103, NO_COLLISIONS: 104, PAUSE: 105, PAUSE_AUDIO_ON: 106, FRAME: 107, FAST_SPEED: 111, SLOW_SPEED: 112, INC_SPEED: 113, DEC_SPEED: 114, NORMAL_SPEED: 115, MIN_SPEED: 116, VIDEO_STANDARD: 123, VSYNCH: 124, DEFAULTS: 130, SAVE_STATE_0: 256 + 0, SAVE_STATE_1: 256 + 1, SAVE_STATE_2: 256 + 2, SAVE_STATE_3: 256 + 3, SAVE_STATE_4: 256 + 4, SAVE_STATE_5: 256 + 5, SAVE_STATE_6: 256 + 6, SAVE_STATE_7: 256 + 7, SAVE_STATE_8: 256 + 8, SAVE_STATE_9: 256 + 9, SAVE_STATE_10: 256 + 10, SAVE_STATE_11: 256 + 11, SAVE_STATE_12: 256 + 12, LOAD_STATE_0: 512 + 0, LOAD_STATE_1: 512 + 1, LOAD_STATE_2: 512 + 2, LOAD_STATE_3: 512 + 3, LOAD_STATE_4: 512 + 4, LOAD_STATE_5: 512 + 5, LOAD_STATE_6: 512 + 6, LOAD_STATE_7: 512 + 7, LOAD_STATE_8: 512 + 8, LOAD_STATE_9: 512 + 9, LOAD_STATE_10: 512 + 10, LOAD_STATE_11: 512 + 11, LOAD_STATE_12: 512 + 12, SAVE_STATE_FILE: 201 }; ================================================ FILE: src/main/atari/controls/JoystickButtons.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.JoystickButtons = { // Real Atari 2600 buttons, register mask J_UP: { button: "J_UP", mask: 0x01, n: "UP" }, J_DOWN: { button: "J_DOWN", mask: 0x02, n: "DOWN" }, J_LEFT: { button: "J_LEFT", mask: 0x04, n: "LEFT" }, J_RIGHT: { button: "J_RIGHT", mask: 0x08, n: "RIGHT" }, J_A: { button: "J_A", mask: 0x10, n: "A" }, J_B: { button: "J_B", mask: 0x20, n: "B" }, J_AB: { button: "J_AB", mask: 0x30, n: "AB" }, // Special case, both A and B buttons // Virtual buttons, no valid mask J_X: { button: "J_X", n: "X" }, J_Y: { button: "J_Y", n: "Y" }, J_L: { button: "J_L", n: "L" }, J_R: { button: "J_R", n: "R" }, J_BACK: { button: "J_BACK", n: "BACK" }, J_START: { button: "J_START", n: "START" } }; ================================================ FILE: src/main/atari/cpu/M6502.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.M6502 = function() { "use strict"; var self = this; this.powerOn = function() { this.reset(); }; this.powerOff = function() { }; this.clockPulse = function() { if (!RDY) return; // TODO Should be ignored in the last cycle of the instruction T++; instruction[T](); }; this.connectBus = function(aBus) { bus = aBus; }; this.setRDY = function(boo) { RDY = boo; }; this.reset = function() { I = 1; T = -1; opcode = -1; instruction = boostrapInstruction; PC = bus.read(RESET_VECTOR) | (bus.read(RESET_VECTOR + 1) << 8); this.setRDY(true); }; // Interfaces var bus; var RDY = false; // Registers var PC = 0; var SP = 0; var A = 0; var X = 0; var Y = 0; // Status Bits var N = 0; var V = 0; var D = 0; var I = 0; var Z = 0; var C = 0; // Internal decoding registers var T = -1; var opcode = -1; var instruction; var data = 0; var AD = 0; var BA = 0; var BALCrossed = false; var IA = 0; var branchOffset = 0; var branchOffsetCrossAdjust = 0; // Vectors //var NMI_VECTOR = 0xfffa; var RESET_VECTOR = 0xfffc; var IRQ_VECTOR = 0xfffe; // Index registers names var rX = 0; var rY = 1; // Status bits names var bN = 7; var bV = 6; // var bE = 5; // Not used // var bB = 4; // Not used // var bD = 3; // Not used // var bI = 2; // Not used var bZ = 1; var bC = 0; // Auxiliary variables //noinspection JSUnusedGlobalSymbols this.debug = false; //noinspection JSUnusedGlobalSymbols this.trace = false; // Internal operations var fetchOpcodeAndDecodeInstruction = function() { opcode = bus.read(PC); instruction = instructions[opcode]; T = 0; // if (self.trace) self.breakpoint("TRACE"); // console.log("PC: " + PC + ", op: " + opcode + ": " + opcodes[opcode]); PC++; }; var fetchNextOpcode = fetchOpcodeAndDecodeInstruction; var boostrapInstruction = [ fetchOpcodeAndDecodeInstruction ]; var fetchOpcodeAndDiscard = function() { bus.read(PC); }; var fetchBranchOffset = function() { branchOffset = bus.read(PC); PC++; }; var fetchADL = function() { AD = bus.read(PC); PC++; }; var fetchADH = function() { AD |= bus.read(PC) << 8; PC++; }; var fetchADLFromBA = function() { AD = bus.read(BA); }; var fetchADHFromBA = function() { AD |= bus.read(BA) << 8; }; var fetchBAL = function() { BA = bus.read(PC); PC++; }; var fetchBAH = function() { BA |= bus.read(PC) << 8; PC++; }; var fetchBALFromIA = function() { BA = bus.read(IA); }; var fetchBAHFromIA = function() { BA |= bus.read(IA) << 8; }; var addXtoBAL = function() { var low = (BA & 255) + X; BALCrossed = low > 255; BA = (BA & 0xff00) | (low & 255); }; var addYtoBAL = function() { var low = (BA & 255) + Y; BALCrossed = low > 255; BA = (BA & 0xff00) | (low & 255); }; var add1toBAL = function() { var low = (BA & 255) + 1; BALCrossed = low > 255; BA = (BA & 0xff00) | (low & 255); }; var add1toBAHifBALCrossed = function() { if (BALCrossed) BA = (BA + 0x0100) & 0xffff; }; var fetchIAL = function() { IA = bus.read(PC); PC++; }; var fetchIAH = function() { IA |= bus.read(PC) << 8; PC++; }; var add1toIAL = function() { var low = (IA & 255) + 1; IA = (IA & 0xff00) | (low & 255); }; var fetchDataFromImmediate = function() { data = bus.read(PC); PC++; }; var fetchDataFromAD = function() { data = bus.read(AD); }; var fetchDataFromBA = function() { data = bus.read(BA); }; var writeDataToAD = function() { bus.write(AD, data); }; var writeDataToBA = function() { bus.write(BA, data); }; var addBranchOffsetToPCL = function() { var oldLow = (PC & 0x00ff); var newLow = (oldLow + branchOffset) & 255; // Negative offset? if (branchOffset > 127) branchOffsetCrossAdjust = (newLow > oldLow) ? -0x0100 : 0; else branchOffsetCrossAdjust = (newLow < oldLow) ? 0x0100 : 0; PC = (PC & 0xff00) | newLow; }; var adjustPCHForBranchOffsetCross = function() { PC = (PC + branchOffsetCrossAdjust) & 0xffff; }; var setZ = function(val) { Z = (val === 0) ? 1 : 0; }; var setN = function(val) { N = (val & 0x080) ? 1 : 0; }; var setV = function(boo) { V = boo ? 1 : 0; }; var setC = function(boo) { C = boo ? 1 : 0; }; var popFromStack = function() { SP = (SP + 1) & 255; return bus.read(0x0100 + SP); }; var peekFromStack = function() { return bus.read(0x0100 + SP); }; var pushToStack = function(val) { bus.write(0x0100 + SP, val); SP = (SP - 1) & 255; }; var getStatusBits = function() { return N << 7 | V << 6 | 0x30 // Always push with E (bit 5) and B (bit 4) ON | D << 3 | I << 2 | Z << 1 | C; }; var setStatusBits = function(val) { N = val >>> 7; V = val >>> 6 & 1; // E and B flags actually do not exist as real flags, so ignore D = val >>> 3 & 1; I = val >>> 2 & 1; Z = val >>> 1 & 1; C = val & 1; }; var illegalOpcode = function(op) { if (self.debug) self.breakpoint("Illegal Opcode: " + op); }; // Addressing routines var implied = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, function implied() { operation(); fetchNextOpcode(); } ]; }; var immediateRead = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchDataFromImmediate, function immediateRead() { operation(); fetchNextOpcode(); } ]; }; var zeroPageRead = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, // ADH will be zero fetchDataFromAD, function zeroPageRead() { operation(); fetchNextOpcode(); } ]; }; var absoluteRead = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, fetchADH, fetchDataFromAD, function absoluteRead() { operation(); fetchNextOpcode(); } ]; }; var indirectXRead = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function indirectXRead1() { addXtoBAL(); fetchADLFromBA(); }, function indirectXRead2() { add1toBAL(); fetchADHFromBA(); }, fetchDataFromAD, function indirectXRead3() { operation(); fetchNextOpcode(); } ]; }; var absoluteIndexedRead = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, fetchBAH, function absoluteIndexedRead1() { addIndex(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, function absoluteIndexedRead2() { if (BALCrossed) { fetchDataFromBA(); } else { operation(); fetchNextOpcode(); } }, function absoluteIndexedRead3() { operation(); fetchNextOpcode(); } ]; }; }; var zeroPageIndexedRead = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function zeroPageIndexedRead1() { addIndex(); fetchDataFromBA(); }, function zeroPageIndexedRead2() { operation(); fetchNextOpcode(); } ]; }; }; var indirectYRead = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchIAL, // IAH will be zero fetchBALFromIA, function indirectYRead1() { add1toIAL(); fetchBAHFromIA(); }, function indirectYRead2() { addYtoBAL(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, function indirectYRead3() { if(BALCrossed) { fetchDataFromBA(); } else { operation(); fetchNextOpcode(); } }, function indirectYRead4() { operation(); fetchNextOpcode(); } ]; }; var zeroPageWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, // ADH will be zero function zeroPageWrite() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var absoluteWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, fetchADH, function absoluteWrite() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var indirectXWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function indirectXWrite1() { addXtoBAL(); fetchADLFromBA(); }, function indirectXWrite2() { add1toBAL(); fetchADHFromBA(); }, function indirectXWrite3() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var absoluteIndexedWrite = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, fetchBAH, function absoluteIndexedWrite1() { addIndex(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, function absoluteIndexedWrite2() { operation(); writeDataToBA(); }, fetchNextOpcode ]; }; }; var zeroPageIndexedWrite = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function zeroPageIndexedWrite() { addIndex(); operation(); writeDataToBA(); }, fetchNextOpcode ]; }; }; var indirectYWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchIAL, // IAH will be zero fetchBALFromIA, function indirectYWrite1() { add1toIAL(); fetchBAHFromIA(); }, function indirectYWrite2() { addYtoBAL(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, function indirectYWrite3() { operation(); writeDataToBA(); }, fetchNextOpcode ]; }; var zeroPageReadModifyWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, // ADH will be zero fetchDataFromAD, writeDataToAD, function zeroPageReadModifyWrite() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var absoluteReadModifyWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchADL, fetchADH, fetchDataFromAD, writeDataToAD, function absoluteReadModifyWrite() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var zeroPageIndexedReadModifyWrite = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function zeroPageIndexedReadModifyWrite1() { addIndex(); fetchDataFromBA(); }, writeDataToBA, function zeroPageIndexedReadModifyWrite2() { operation(); writeDataToBA(); }, fetchNextOpcode ]; }; }; var absoluteIndexedReadModifyWrite = function(index) { var addIndex = index === rX ? addXtoBAL : addYtoBAL; return function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, fetchBAH, function absoluteIndexedReadModifyWrite1() { addIndex(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, fetchDataFromBA, writeDataToBA, function absoluteIndexedReadModifyWrite2() { operation(); writeDataToBA(); }, fetchNextOpcode ]; }; }; var indirectXReadModifyWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchBAL, // BAH will be zero fetchDataFromBA, function indirectXReadModifyWrite1() { addXtoBAL(); fetchADLFromBA(); }, function indirectXReadModifyWrite2() { add1toBAL(); fetchADHFromBA(); }, fetchDataFromAD, writeDataToAD, function indirectXReadModifyWrite3() { operation(); writeDataToAD(); }, fetchNextOpcode ]; }; var indirectYReadModifyWrite = function(operation) { return [ fetchOpcodeAndDecodeInstruction, fetchIAL, // IAH will be zero fetchBALFromIA, function indirectYReadModifyWrite1() { add1toIAL(); fetchBAHFromIA(); }, function indirectYReadModifyWrite2() { addYtoBAL(); fetchDataFromBA(); add1toBAHifBALCrossed(); }, fetchDataFromBA, writeDataToBA, function indirectYReadModifyWrite3() { operation(); writeDataToBA(); }, fetchNextOpcode ]; }; // Instructions ======================================================================================== // Complete instruction set var opcodes = new Array(256); var instructions = new Array(256); opcodes[0x00] = "BRK"; instructions[0x00] = newBRK(); opcodes[0x01] = "ORA"; instructions[0x01] = newORA(indirectXRead); opcodes[0x02] = "uKIL"; instructions[0x02] = newuKIL(); opcodes[0x03] = "uSLO"; instructions[0x03] = newuSLO(indirectXReadModifyWrite); opcodes[0x04] = "uNOP"; instructions[0x04] = newuNOP(zeroPageRead); opcodes[0x05] = "ORA"; instructions[0x05] = newORA(zeroPageRead); opcodes[0x06] = "ASL"; instructions[0x06] = newASL(zeroPageReadModifyWrite); opcodes[0x07] = "uSLO"; instructions[0x07] = newuSLO(zeroPageReadModifyWrite); opcodes[0x08] = "PHP"; instructions[0x08] = newPHP(); opcodes[0x09] = "ORA"; instructions[0x09] = newORA(immediateRead); opcodes[0x0a] = "ASL"; instructions[0x0a] = newASL_ACC(); opcodes[0x0b] = "uANC"; instructions[0x0b] = newuANC(immediateRead); opcodes[0x0c] = "uNOP"; instructions[0x0c] = newuNOP(absoluteRead); opcodes[0x0d] = "ORA"; instructions[0x0d] = newORA(absoluteRead); opcodes[0x0e] = "ASL"; instructions[0x0e] = newASL(absoluteReadModifyWrite); opcodes[0x0f] = "uSLO"; instructions[0x0f] = newuSLO(absoluteReadModifyWrite); opcodes[0x10] = "BPL"; instructions[0x10] = newBxx(bN, 0); // BPL opcodes[0x11] = "ORA"; instructions[0x11] = newORA(indirectYRead); opcodes[0x12] = "uKIL"; instructions[0x12] = newuKIL(); opcodes[0x13] = "uSLO"; instructions[0x13] = newuSLO(indirectYReadModifyWrite); opcodes[0x14] = "uNOP"; instructions[0x14] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0x15] = "ORA"; instructions[0x15] = newORA(zeroPageIndexedRead(rX)); opcodes[0x16] = "ASL"; instructions[0x16] = newASL(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x17] = "uSLO"; instructions[0x17] = newuSLO(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x18] = "CLC"; instructions[0x18] = newCLC(); opcodes[0x19] = "ORA"; instructions[0x19] = newORA(absoluteIndexedRead(rY)); opcodes[0x1a] = "uNOP"; instructions[0x1a] = newuNOP(implied); opcodes[0x1b] = "uSLO"; instructions[0x1b] = newuSLO(absoluteIndexedReadModifyWrite(rY)); opcodes[0x1c] = "uNOP"; instructions[0x1c] = newuNOP(absoluteIndexedRead(rX)); opcodes[0x1d] = "ORA"; instructions[0x1d] = newORA(absoluteIndexedRead(rX)); opcodes[0x1e] = "ASL"; instructions[0x1e] = newASL(absoluteIndexedReadModifyWrite(rX)); opcodes[0x1f] = "uSLO"; instructions[0x1f] = newuSLO(absoluteIndexedReadModifyWrite(rX)); opcodes[0x20] = "JSR"; instructions[0x20] = newJSR(); opcodes[0x21] = "AND"; instructions[0x21] = newAND(indirectXRead); opcodes[0x22] = "uKIL"; instructions[0x22] = newuKIL(); opcodes[0x23] = "uRLA"; instructions[0x23] = newuRLA(indirectXReadModifyWrite); opcodes[0x24] = "BIT"; instructions[0x24] = newBIT(zeroPageRead); opcodes[0x25] = "AND"; instructions[0x25] = newAND(zeroPageRead); opcodes[0x26] = "ROL"; instructions[0x26] = newROL(zeroPageReadModifyWrite); opcodes[0x27] = "uRLA"; instructions[0x27] = newuRLA(zeroPageReadModifyWrite); opcodes[0x28] = "PLP"; instructions[0x28] = newPLP(); opcodes[0x29] = "AND"; instructions[0x29] = newAND(immediateRead); opcodes[0x2a] = "ROL"; instructions[0x2a] = newROL_ACC(); opcodes[0x2b] = "uANC"; instructions[0x2b] = newuANC(immediateRead); opcodes[0x2c] = "BIT"; instructions[0x2c] = newBIT(absoluteRead); opcodes[0x2d] = "AND"; instructions[0x2d] = newAND(absoluteRead); opcodes[0x2e] = "ROL"; instructions[0x2e] = newROL(absoluteReadModifyWrite); opcodes[0x2f] = "uRLA"; instructions[0x2f] = newuRLA(absoluteReadModifyWrite); opcodes[0x30] = "BMI"; instructions[0x30] = newBxx(bN, 1); // BMI opcodes[0x31] = "AND"; instructions[0x31] = newAND(indirectYRead); opcodes[0x32] = "uKIL"; instructions[0x32] = newuKIL(); opcodes[0x33] = "uRLA"; instructions[0x33] = newuRLA(indirectYReadModifyWrite); opcodes[0x34] = "uNOP"; instructions[0x34] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0x35] = "AND"; instructions[0x35] = newAND(zeroPageIndexedRead(rX)); opcodes[0x36] = "ROL"; instructions[0x36] = newROL(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x37] = "uRLA"; instructions[0x37] = newuRLA(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x38] = "SEC"; instructions[0x38] = newSEC(); opcodes[0x39] = "AND"; instructions[0x39] = newAND(absoluteIndexedRead(rY)); opcodes[0x3a] = "uNOP"; instructions[0x3a] = newuNOP(implied); opcodes[0x3b] = "uRLA"; instructions[0x3b] = newuRLA(absoluteIndexedReadModifyWrite(rY)); opcodes[0x3c] = "uNOP"; instructions[0x3c] = newuNOP(absoluteIndexedRead(rX)); opcodes[0x3d] = "AND"; instructions[0x3d] = newAND(absoluteIndexedRead(rX)); opcodes[0x3e] = "ROL"; instructions[0x3e] = newROL(absoluteIndexedReadModifyWrite(rX)); opcodes[0x3f] = "uRLA"; instructions[0x3f] = newuRLA(absoluteIndexedReadModifyWrite(rX)); opcodes[0x40] = "RTI"; instructions[0x40] = newRTI(); opcodes[0x41] = "EOR"; instructions[0x41] = newEOR(indirectXRead); opcodes[0x42] = "uKIL"; instructions[0x42] = newuKIL(); opcodes[0x43] = "uSRE"; instructions[0x43] = newuSRE(indirectXReadModifyWrite); opcodes[0x44] = "uNOP"; instructions[0x44] = newuNOP(zeroPageRead); opcodes[0x45] = "EOR"; instructions[0x45] = newEOR(zeroPageRead); opcodes[0x46] = "LSR"; instructions[0x46] = newLSR(zeroPageReadModifyWrite); opcodes[0x47] = "uSRE"; instructions[0x47] = newuSRE(zeroPageReadModifyWrite); opcodes[0x48] = "PHA"; instructions[0x48] = mewPHA(); opcodes[0x49] = "EOR"; instructions[0x49] = newEOR(immediateRead); opcodes[0x4a] = "LSR"; instructions[0x4a] = newLSR_ACC(); opcodes[0x4b] = "uASR"; instructions[0x4b] = newuASR(immediateRead); opcodes[0x4c] = "JMP"; instructions[0x4c] = newJMP_ABS(); opcodes[0x4d] = "EOR"; instructions[0x4d] = newEOR(absoluteRead); opcodes[0x4e] = "LSR"; instructions[0x4e] = newLSR(absoluteReadModifyWrite); opcodes[0x4f] = "uSRE"; instructions[0x4f] = newuSRE(absoluteReadModifyWrite); opcodes[0x50] = "BVC"; instructions[0x50] = newBxx(bV, 0); // BVC opcodes[0x51] = "EOR"; instructions[0x51] = newEOR(indirectYRead); opcodes[0x52] = "uKIL"; instructions[0x52] = newuKIL(); opcodes[0x53] = "uSRE"; instructions[0x53] = newuSRE(indirectYReadModifyWrite); opcodes[0x54] = "uNOP"; instructions[0x54] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0x55] = "EOR"; instructions[0x55] = newEOR(zeroPageIndexedRead(rX)); opcodes[0x56] = "LSR"; instructions[0x56] = newLSR(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x57] = "uSRE"; instructions[0x57] = newuSRE(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x58] = "CLI"; instructions[0x58] = newCLI(); opcodes[0x59] = "EOR"; instructions[0x59] = newEOR(absoluteIndexedRead(rY)); opcodes[0x5a] = "uNOP"; instructions[0x5a] = newuNOP(implied); opcodes[0x5b] = "uSRE"; instructions[0x5b] = newuSRE(absoluteIndexedReadModifyWrite(rY)); opcodes[0x5c] = "uNOP"; instructions[0x5c] = newuNOP(absoluteIndexedRead(rX)); opcodes[0x5d] = "EOR"; instructions[0x5d] = newEOR(absoluteIndexedRead(rX)); opcodes[0x5e] = "LSR"; instructions[0x5e] = newLSR(absoluteIndexedReadModifyWrite(rX)); opcodes[0x5f] = "uSRE"; instructions[0x5f] = newuSRE(absoluteIndexedReadModifyWrite(rX)); opcodes[0x60] = "RTS"; instructions[0x60] = newRTS(); opcodes[0x61] = "ADC"; instructions[0x61] = newADC(indirectXRead); opcodes[0x62] = "uKIL"; instructions[0x62] = newuKIL(); opcodes[0x63] = "uRRA"; instructions[0x63] = newuRRA(indirectXReadModifyWrite); opcodes[0x64] = "uNOP"; instructions[0x64] = newuNOP(zeroPageRead); opcodes[0x65] = "ADC"; instructions[0x65] = newADC(zeroPageRead); opcodes[0x66] = "ROR"; instructions[0x66] = newROR(zeroPageReadModifyWrite); opcodes[0x67] = "uRRA"; instructions[0x67] = newuRRA(zeroPageReadModifyWrite); opcodes[0x68] = "PLA"; instructions[0x68] = newPLA(); opcodes[0x69] = "ADC"; instructions[0x69] = newADC(immediateRead); opcodes[0x6a] = "ROR"; instructions[0x6a] = newROR_ACC(); opcodes[0x6b] = "uARR"; instructions[0x6b] = newuARR(immediateRead); opcodes[0x6c] = "JMP"; instructions[0x6c] = newJMP_IND(); opcodes[0x6d] = "ADC"; instructions[0x6d] = newADC(absoluteRead); opcodes[0x6e] = "ROR"; instructions[0x6e] = newROR(absoluteReadModifyWrite); opcodes[0x6f] = "uRRA"; instructions[0x6f] = newuRRA(absoluteReadModifyWrite); opcodes[0x70] = "BVS"; instructions[0x70] = newBxx(bV, 1); // BVS opcodes[0x71] = "ADC"; instructions[0x71] = newADC(indirectYRead); opcodes[0x72] = "uKIL"; instructions[0x72] = newuKIL(); opcodes[0x73] = "uRRA"; instructions[0x73] = newuRRA(indirectYReadModifyWrite); opcodes[0x74] = "uNOP"; instructions[0x74] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0x75] = "ADC"; instructions[0x75] = newADC(zeroPageIndexedRead(rX)); opcodes[0x76] = "ROR"; instructions[0x76] = newROR(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x77] = "uRRA"; instructions[0x77] = newuRRA(zeroPageIndexedReadModifyWrite(rX)); opcodes[0x78] = "SEI"; instructions[0x78] = newSEI(); opcodes[0x79] = "ADC"; instructions[0x79] = newADC(absoluteIndexedRead(rY)); opcodes[0x7a] = "uNOP"; instructions[0x7a] = newuNOP(implied); opcodes[0x7b] = "uRRA"; instructions[0x7b] = newuRRA(absoluteIndexedReadModifyWrite(rY)); opcodes[0x7c] = "uNOP"; instructions[0x7c] = newuNOP(absoluteIndexedRead(rX)); opcodes[0x7d] = "ADC"; instructions[0x7d] = newADC(absoluteIndexedRead(rX)); opcodes[0x7e] = "ROR"; instructions[0x7e] = newROR(absoluteIndexedReadModifyWrite(rX)); opcodes[0x7f] = "uRRA"; instructions[0x7f] = newuRRA(absoluteIndexedReadModifyWrite(rX)); opcodes[0x80] = "uNOP"; instructions[0x80] = newuNOP(immediateRead); opcodes[0x81] = "STA"; instructions[0x81] = newSTA(indirectXWrite); opcodes[0x82] = "uNOP"; instructions[0x82] = newuNOP(immediateRead); opcodes[0x83] = "uSAX"; instructions[0x83] = newuSAX(indirectXWrite); opcodes[0x84] = "STY"; instructions[0x84] = newSTY(zeroPageWrite); opcodes[0x85] = "STA"; instructions[0x85] = newSTA(zeroPageWrite); opcodes[0x86] = "STX"; instructions[0x86] = newSTX(zeroPageWrite); opcodes[0x87] = "uSAX"; instructions[0x87] = newuSAX(zeroPageWrite); opcodes[0x88] = "DEY"; instructions[0x88] = newDEY(); opcodes[0x89] = "uNOP"; instructions[0x89] = newuNOP(immediateRead); opcodes[0x8a] = "TXA"; instructions[0x8a] = newTXA(); opcodes[0x8b] = "uANE"; instructions[0x8b] = newuANE(immediateRead); opcodes[0x8c] = "STY"; instructions[0x8c] = newSTY(absoluteWrite); opcodes[0x8d] = "STA"; instructions[0x8d] = newSTA(absoluteWrite); opcodes[0x8e] = "STX"; instructions[0x8e] = newSTX(absoluteWrite); opcodes[0x8f] = "uSAX"; instructions[0x8f] = newuSAX(absoluteWrite); opcodes[0x90] = "BCC"; instructions[0x90] = newBxx(bC, 0); // BCC opcodes[0x91] = "STA"; instructions[0x91] = newSTA(indirectYWrite); opcodes[0x92] = "uKIL"; instructions[0x92] = newuKIL(); opcodes[0x93] = "uSHA"; instructions[0x93] = newuSHA(indirectYWrite); opcodes[0x94] = "STY"; instructions[0x94] = newSTY(zeroPageIndexedWrite(rX)); opcodes[0x95] = "STA"; instructions[0x95] = newSTA(zeroPageIndexedWrite(rX)); opcodes[0x96] = "STX"; instructions[0x96] = newSTX(zeroPageIndexedWrite(rY)); opcodes[0x97] = "uSAX"; instructions[0x97] = newuSAX(zeroPageIndexedWrite(rY)); opcodes[0x98] = "TYA"; instructions[0x98] = newTYA(); opcodes[0x99] = "STA"; instructions[0x99] = newSTA(absoluteIndexedWrite(rY)); opcodes[0x9a] = "TXS"; instructions[0x9a] = newTXS(); opcodes[0x9b] = "uSHS"; instructions[0x9b] = newuSHS(absoluteIndexedWrite(rY)); opcodes[0x9c] = "uSHY"; instructions[0x9c] = newuSHY(absoluteIndexedWrite(rX)); opcodes[0x9d] = "STA"; instructions[0x9d] = newSTA(absoluteIndexedWrite(rX)); opcodes[0x9e] = "uSHX"; instructions[0x9e] = newuSHX(absoluteIndexedWrite(rY)); opcodes[0x9f] = "uSHA"; instructions[0x9f] = newuSHA(absoluteIndexedWrite(rY)); opcodes[0xa0] = "LDY"; instructions[0xa0] = newLDY(immediateRead); opcodes[0xa1] = "LDA"; instructions[0xa1] = newLDA(indirectXRead); opcodes[0xa2] = "LDX"; instructions[0xa2] = newLDX(immediateRead); opcodes[0xa3] = "uLAX"; instructions[0xa3] = newuLAX(indirectXRead); opcodes[0xa4] = "LDY"; instructions[0xa4] = newLDY(zeroPageRead); opcodes[0xa5] = "LDA"; instructions[0xa5] = newLDA(zeroPageRead); opcodes[0xa6] = "LDX"; instructions[0xa6] = newLDX(zeroPageRead); opcodes[0xa7] = "uLAX"; instructions[0xa7] = newuLAX(zeroPageRead); opcodes[0xa8] = "TAY"; instructions[0xa8] = newTAY(); opcodes[0xa9] = "LDA"; instructions[0xa9] = newLDA(immediateRead); opcodes[0xaa] = "TAX"; instructions[0xaa] = newTAX(); opcodes[0xab] = "uLXA"; instructions[0xab] = newuLXA(immediateRead); opcodes[0xac] = "LDY"; instructions[0xac] = newLDY(absoluteRead); opcodes[0xad] = "LDA"; instructions[0xad] = newLDA(absoluteRead); opcodes[0xae] = "LDX"; instructions[0xae] = newLDX(absoluteRead); opcodes[0xaf] = "uLAX"; instructions[0xaf] = newuLAX(absoluteRead); opcodes[0xb0] = "BCS"; instructions[0xb0] = newBxx(bC, 1); // BCS opcodes[0xb1] = "LDA"; instructions[0xb1] = newLDA(indirectYRead); opcodes[0xb2] = "uKIL"; instructions[0xb2] = newuKIL(); opcodes[0xb3] = "uLAX"; instructions[0xb3] = newuLAX(indirectYRead); opcodes[0xb4] = "LDY"; instructions[0xb4] = newLDY(zeroPageIndexedRead(rX)); opcodes[0xb5] = "LDA"; instructions[0xb5] = newLDA(zeroPageIndexedRead(rX)); opcodes[0xb6] = "LDX"; instructions[0xb6] = newLDX(zeroPageIndexedRead(rY)); opcodes[0xb7] = "uLAX"; instructions[0xb7] = newuLAX(zeroPageIndexedRead(rY)); opcodes[0xb8] = "CLV"; instructions[0xb8] = newCLV(); opcodes[0xb9] = "LDA"; instructions[0xb9] = newLDA(absoluteIndexedRead(rY)); opcodes[0xba] = "TSX"; instructions[0xba] = newTSX(); opcodes[0xbb] = "uLAS"; instructions[0xbb] = newuLAS(absoluteIndexedRead(rY)); opcodes[0xbc] = "LDY"; instructions[0xbc] = newLDY(absoluteIndexedRead(rX)); opcodes[0xbd] = "LDA"; instructions[0xbd] = newLDA(absoluteIndexedRead(rX)); opcodes[0xbe] = "LDX"; instructions[0xbe] = newLDX(absoluteIndexedRead(rY)); opcodes[0xbf] = "uLAX"; instructions[0xbf] = newuLAX(absoluteIndexedRead(rY)); opcodes[0xc0] = "CPY"; instructions[0xc0] = newCPY(immediateRead); opcodes[0xc1] = "CMP"; instructions[0xc1] = newCMP(indirectXRead); opcodes[0xc2] = "uNOP"; instructions[0xc2] = newuNOP(immediateRead); opcodes[0xc3] = "uDCP"; instructions[0xc3] = newuDCP(indirectXReadModifyWrite); opcodes[0xc4] = "CPY"; instructions[0xc4] = newCPY(zeroPageRead); opcodes[0xc5] = "CMP"; instructions[0xc5] = newCMP(zeroPageRead); opcodes[0xc6] = "DEC"; instructions[0xc6] = newDEC(zeroPageReadModifyWrite); opcodes[0xc7] = "uDCP"; instructions[0xc7] = newuDCP(zeroPageReadModifyWrite); opcodes[0xc8] = "INY"; instructions[0xc8] = newINY(); opcodes[0xc9] = "CMP"; instructions[0xc9] = newCMP(immediateRead); opcodes[0xca] = "DEX"; instructions[0xca] = newDEX(); opcodes[0xcb] = "uSBX"; instructions[0xcb] = newuSBX(immediateRead); opcodes[0xcc] = "CPY"; instructions[0xcc] = newCPY(absoluteRead); opcodes[0xcd] = "CMP"; instructions[0xcd] = newCMP(absoluteRead); opcodes[0xce] = "DEC"; instructions[0xce] = newDEC(absoluteReadModifyWrite); opcodes[0xcf] = "uDCP"; instructions[0xcf] = newuDCP(absoluteReadModifyWrite); opcodes[0xd0] = "BNE"; instructions[0xd0] = newBxx(bZ, 0); // BNE opcodes[0xd1] = "CMP"; instructions[0xd1] = newCMP(indirectYRead); opcodes[0xd2] = "uKIL"; instructions[0xd2] = newuKIL(); opcodes[0xd3] = "uDCP"; instructions[0xd3] = newuDCP(indirectYReadModifyWrite); opcodes[0xd4] = "uNOP"; instructions[0xd4] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0xd5] = "CMP"; instructions[0xd5] = newCMP(zeroPageIndexedRead(rX)); opcodes[0xd6] = "DEC"; instructions[0xd6] = newDEC(zeroPageIndexedReadModifyWrite(rX)); opcodes[0xd7] = "uDCP"; instructions[0xd7] = newuDCP(zeroPageIndexedReadModifyWrite(rX)); opcodes[0xd8] = "CLD"; instructions[0xd8] = newCLD(); opcodes[0xd9] = "CMP"; instructions[0xd9] = newCMP(absoluteIndexedRead(rY)); opcodes[0xda] = "uNOP"; instructions[0xda] = newuNOP(implied); opcodes[0xdb] = "uDCP"; instructions[0xdb] = newuDCP(absoluteIndexedReadModifyWrite(rY)); opcodes[0xdc] = "uNOP"; instructions[0xdc] = newuNOP(absoluteIndexedRead(rX)); opcodes[0xdd] = "CMP"; instructions[0xdd] = newCMP(absoluteIndexedRead(rX)); opcodes[0xde] = "DEC"; instructions[0xde] = newDEC(absoluteIndexedReadModifyWrite(rX)); opcodes[0xdf] = "uDCP"; instructions[0xdf] = newuDCP(absoluteIndexedReadModifyWrite(rX)); opcodes[0xe0] = "CPX"; instructions[0xe0] = newCPX(immediateRead); opcodes[0xe1] = "SBC"; instructions[0xe1] = newSBC(indirectXRead); opcodes[0xe2] = "uNOP"; instructions[0xe2] = newuNOP(immediateRead); opcodes[0xe3] = "uISB"; instructions[0xe3] = newuISB(indirectXReadModifyWrite); opcodes[0xe4] = "CPX"; instructions[0xe4] = newCPX(zeroPageRead); opcodes[0xe5] = "SBC"; instructions[0xe5] = newSBC(zeroPageRead); opcodes[0xe6] = "INC"; instructions[0xe6] = newINC(zeroPageReadModifyWrite); opcodes[0xe7] = "uISB"; instructions[0xe7] = newuISB(zeroPageReadModifyWrite); opcodes[0xe8] = "newINX"; instructions[0xe8] = newINX(); opcodes[0xe9] = "SBC"; instructions[0xe9] = newSBC(immediateRead); opcodes[0xea] = "NOP"; instructions[0xea] = newNOP(); opcodes[0xeb] = "SBC"; instructions[0xeb] = newSBC(immediateRead); opcodes[0xec] = "CPX"; instructions[0xec] = newCPX(absoluteRead); opcodes[0xed] = "SBC"; instructions[0xed] = newSBC(absoluteRead); opcodes[0xee] = "INC"; instructions[0xee] = newINC(absoluteReadModifyWrite); opcodes[0xef] = "uISB"; instructions[0xef] = newuISB(absoluteReadModifyWrite); opcodes[0xf0] = "BEQ"; instructions[0xf0] = newBxx(bZ, 1); // BEQ opcodes[0xf1] = "SBC"; instructions[0xf1] = newSBC(indirectYRead); opcodes[0xf2] = "uKIL"; instructions[0xf2] = newuKIL(); opcodes[0xf3] = "uISB"; instructions[0xf3] = newuISB(indirectYReadModifyWrite); opcodes[0xf4] = "uNOP"; instructions[0xf4] = newuNOP(zeroPageIndexedRead(rX)); opcodes[0xf5] = "SBC"; instructions[0xf5] = newSBC(zeroPageIndexedRead(rX)); opcodes[0xf6] = "INC"; instructions[0xf6] = newINC(zeroPageIndexedReadModifyWrite(rX)); opcodes[0xf7] = "uISB"; instructions[0xf7] = newuISB(zeroPageIndexedReadModifyWrite(rX)); opcodes[0xf8] = "SED"; instructions[0xf8] = newSED(); opcodes[0xf9] = "SBC"; instructions[0xf9] = newSBC(absoluteIndexedRead(rY)); opcodes[0xfa] = "uNOP"; instructions[0xfa] = newuNOP(implied); opcodes[0xfb] = "uISB"; instructions[0xfb] = newuISB(absoluteIndexedReadModifyWrite(rY)); opcodes[0xfc] = "uNOP"; instructions[0xfc] = newuNOP(absoluteIndexedRead(rX)); opcodes[0xfd] = "SBC"; instructions[0xfd] = newSBC(absoluteIndexedRead(rX)); opcodes[0xfe] = "INC"; instructions[0xfe] = newINC(absoluteIndexedReadModifyWrite(rX)); opcodes[0xff] = "uISB"; instructions[0xff] = newuISB(absoluteIndexedReadModifyWrite(rX)); // Single Byte instructions function newASL_ACC() { return implied(function ASL_ACC() { setC(A > 127); A = (A << 1) & 255; setZ(A); setN(A); }); } function newCLC() { return implied(function CLC() { C = 0; }); } function newCLD() { return implied(function CLD() { D = 0; }); } function newCLI() { return implied(function CLI() { I = 0; }); } function newCLV() { return implied(function CLV() { V = 0; }); } function newDEX() { return implied(function DEX() { X = (X - 1) & 255; setZ(X); setN(X); }); } function newDEY() { return implied(function DEY() { Y = (Y - 1) & 255; setZ(Y); setN(Y); }); } function newINX() { return implied(function INX() { X = (X + 1) & 255; setZ(X); setN(X); }); } function newINY() { return implied(function INY() { Y = (Y + 1) & 255; setZ(Y); setN(Y); }); } function newLSR_ACC() { return implied(function LSR_ACC() { C = A & 0x01; A >>>= 1; setZ(A); N = 0; }); } function newNOP() { return implied(function NOP() { // nothing }); } function newROL_ACC() { return implied(function ROL_ACC() { var newC = A > 127; A = ((A << 1) | C) & 255; setC(newC); setZ(A); setN(A); }); } function newROR_ACC() { return implied(function ROR_ACC() { var newC = A & 0x01; A = (A >>> 1) | (C << 7); setC(newC); setZ(A); setN(A); }); } function newSEC() { return implied(function SEC() { C = 1; }); } function newSED() { return implied(function SED() { D = 1; }); } function newSEI() { return implied(function SEI() { I = 1; }); } function newTAX() { return implied(function TAX() { X = A; setZ(X); setN(X); }); } function newTAY() { return implied(function TAY() { Y = A; setZ(Y); setN(Y); }); } function newTSX() { return implied(function TSX() { X = SP; setZ(X); setN(X); }); } function newTXA() { return implied(function TXA() { A = X; setZ(A); setN(A); }); } function newTXS() { return implied(function TXS() { SP = X; }); } function newTYA() { return implied(function TYA() { A = Y; setZ(A); setN(A); }); } function newuKIL() { return [ fetchOpcodeAndDecodeInstruction, function() { illegalOpcode("KIL/HLT/JAM"); }, function() { T--; // Causes the processor to be stuck in this instruction forever } ]; } function newuNOP(addressing) { return addressing(function uNOP() { illegalOpcode("NOP/DOP"); // nothing }); } // Internal Execution on Memory Data function newADC(addressing) { return addressing(function ADC() { if (D) { var operand = data; var AL = (A & 15) + (operand & 15) + C; if (AL > 9) { AL += 6; } var AH = ((A >> 4) + (operand >> 4) + (AL > 15)) << 4; setZ((A + operand + C) & 255); setN(AH); setV(((A ^AH) & ~(A ^ operand)) & 128); if (AH > 0x9f) { AH += 0x60; } setC(AH > 255); A = (AH | (AL & 15)) & 255; } else { var add = A + data + C; setC(add > 255); setV(((A ^ add) & (data ^ add)) & 0x80); A = add & 255; setZ(A); setN(A); } }); } function newAND(addressing) { return addressing(function AND() { A &= data; setZ(A); setN(A); }); } function newBIT(addressing) { return addressing(function BIT() { var par = data; setZ(A & par); setV(par & 0x40); setN(par); }); } function newCMP(addressing) { return addressing(function CMP() { var val = (A - data) & 255; setC(A >= data); setZ(val); setN(val); }); } function newCPX(addressing) { return addressing(function CPX() { var val = (X - data) & 255; setC(X >= data); setZ(val); setN(val); }); } function newCPY(addressing) { return addressing(function CPY() { var val = (Y - data) & 255; setC(Y >= data); setZ(val); setN(val); }); } function newEOR(addressing) { return addressing(function EOR() { A ^= data; setZ(A); setN(A); }); } function newLDA(addressing) { return addressing(function LDA() { A = data; setZ(A); setN(A); }); } function newLDX(addressing) { return addressing(function LDX() { X = data; setZ(X); setN(X); }); } function newLDY(addressing) { return addressing(function LDY() { Y = data; setZ(Y); setN(Y); }); } function newORA(addressing) { return addressing(function ORA() { A |= data; setZ(A); setN(A); }); } function newSBC(addressing) { return addressing(function SBC() { if (D) { var operand = data; var AL = (A & 15) - (operand & 15) - (1-C); var AH = (A >> 4) - (operand >> 4) - (AL < 0); if (AL < 0) { AL -= 6; } if (AH < 0) { AH -= 6; } var sub = A - operand - (1-C); setC(~sub & 256); setV(((A ^ operand) & (A ^ sub)) & 128); setZ(sub & 255); setN(sub); A = ((AH << 4) | (AL & 15)) & 255; } else { operand = (~data) & 255; sub = A + operand + C; setC(sub > 255); setV(((A ^ sub) & (operand ^ sub) & 0x80)); A = sub & 255; setZ(A); setN(A); } }); } function newuANC(addressing) { return addressing(function uANC() { illegalOpcode("ANC"); A &= data; setZ(A); N = C = (A & 0x080) ? 1 : 0; }); } function newuANE(addressing) { return addressing(function uANE() { illegalOpcode("ANE"); // Exact operation unknown. Do nothing }); } function newuARR(addressing) { // Some sources say flags are affected per ROR, others say its more complex. The complex one is chosen return addressing(function uARR() { illegalOpcode("ARR"); var val = A & data; var oldC = C ? 0x80 : 0; val = (val >>> 1) | oldC; A = val; setZ(val); setN(val); var comp = A & 0x60; if (comp == 0x60) { C = 1; V = 0; } else if (comp == 0x00) { C = 0; V = 0; } else if (comp == 0x20) { C = 0; V = 1; } else if (comp == 0x40) { C = 1; V = 1; } }); } function newuASR(addressing) { return addressing(function uASR() { illegalOpcode("ASR"); var val = A & data; C = (val & 0x01); // bit 0 val = val >>> 1; A = val; setZ(val); N = 0; }); } function newuLAS(addressing) { return addressing(function uLAS() { illegalOpcode("LAS"); var val = SP & data; A = val; X = val; SP = val; setZ(val); setN(val); }); } function newuLAX(addressing) { return addressing(function uLAX() { illegalOpcode("LAX"); var val = data; A = val; X = val; setZ(val); setN(val); }); } function newuLXA(addressing) { return addressing(function uLXA() { // Some sources say its an OR with $EE then AND with IMM, others exclude the OR, // others exclude both the OR and the AND. Excluding just the OR... illegalOpcode("LXA"); var val = A /* | 0xEE) */ & data; A = val; X = val; setZ(val); setN(val); }); } function newuSBX(addressing) { return addressing(function uSBX() { illegalOpcode("SBX"); var par = A & X; var val = data; var newX = (par - val) & 255; X = newX; setC(par >= val); setZ(newX); setN(newX); }); } // Store operations function newSTA(addressing) { return addressing(function STA() { data = A; }); } function newSTX(addressing) { return addressing(function STX() { data = X; }); } function newSTY(addressing) { return addressing(function STY() { data = Y; }); } function newuSAX(addressing) { return addressing(function uSAX() { // Some sources say it would affect N and Z flags, some say it wouldn't. Chose not to affect illegalOpcode("SAX"); data = A & X; }); } function newuSHA(addressing) { return addressing(function uSHA() { illegalOpcode("SHA"); data = A & X & ((BA >>> 8) + 1) & 255; // A & X & (High byte of effective address + 1) !!! // data would also be stored BAH if page boundary is crossed. Unobservable, not needed here }); } function newuSHS(addressing) { return addressing(function uSHS() { illegalOpcode("SHS"); var val = A & X; SP = val; data = val & ((BA >>> 8) + 1) & 255; // A & X & (High byte of effective address + 1) !!! // data would also be stored BAH if page boundary is crossed. Unobservable, not needed here }); } function newuSHX(addressing) { return addressing(function uSHX() { illegalOpcode("SHX"); data = X & ((BA >>> 8) + 1) & 255; // X & (High byte of effective address + 1) !!! // data would also be stored BAH if page boundary is crossed. Unobservable, not needed here }); } function newuSHY(addressing) { return addressing(function uSHY() { illegalOpcode("SHY"); data = Y & ((BA >>> 8) + 1) & 255; // Y & (High byte of effective address + 1) !!! // data would also be stored BAH if page boundary is crossed. Unobservable, not needed here }); } // Read-Modify-Write operations function newASL(addressing) { return addressing(function ASL() { setC(data > 127); var par = (data << 1) & 255; data = par; setZ(par); setN(par); }); } function newDEC(addressing) { return addressing(function DEC() { var par = (data - 1) & 255; data = par; setZ(par); setN(par); }); } function newINC(addressing) { return addressing(function INC() { var par = (data + 1) & 255; data = par; setZ(par); setN(par); }); } function newLSR(addressing) { return addressing(function LSR() { C = data & 0x01; data >>>= 1; setZ(data); N = 0; }); } function newROL(addressing) { return addressing(function ROL() { var newC = data > 127; var par = ((data << 1) | C) & 255; data = par; setC(newC); setZ(par); setN(par); }); } function newROR(addressing) { return addressing(function ROR() { var newC = data & 0x01; var par = (data >>> 1) | (C << 7); data = par; setC(newC); setZ(par); setN(par); }); } function newuDCP(addressing) { return addressing(function uDCP() { illegalOpcode("DCP"); var par = (data - 1) & 255; data = par; par = A - par; setC(par >= 0); setZ(par); setN(par); }); } function newuISB(addressing) { return addressing(function uISB() { illegalOpcode("ISB"); data = (data + 1) & 255; // ISB is the same as SBC but incs the operand first if (D) { var operand = data; var AL = (A & 15) - (operand & 15) - (1-C); var AH = (A >> 4) - (operand >> 4) - (AL < 0); if (AL < 0) { AL -= 6; } if (AH < 0) { AH -= 6; } var sub = A - operand - (1-C); setC(~sub & 256); setV(((A ^ operand) & (A ^ sub)) & 128); setZ(sub & 255); setN(sub); A = ((AH << 4) | (AL & 15)) & 255; } else { operand = (~data) & 255; sub = A + operand + C; setC(sub > 255); setV(((A ^ sub) & (operand ^ sub) & 0x80)); A = sub & 255; setZ(A); setN(A); } }); } function newuRLA(addressing) { return addressing(function uRLA() { illegalOpcode("RLA"); var val = data; var oldC = C; setC(val & 0x80); // bit 7 was set val = ((val << 1) | oldC) & 255; data = val; A &= val; setZ(val); // TODO Verify. May be A instead of val in the flags setting setN(val); }); } function newuRRA(addressing) { return addressing(function uRRA() { illegalOpcode("RRA"); var val = data; var oldC = C ? 0x80 : 0; setC(val & 0x01); // bit 0 was set val = (val >>> 1) | oldC; data = val; // RRA is the same as ADC from here if (D) { var operand = data; var AL = (A & 15) + (operand & 15) + C; if (AL > 9) { AL += 6; } var AH = ((A >> 4) + (operand >> 4) + (AL > 15)) << 4; setZ((A + operand + C) & 255); setN(AH); setV(((A ^AH) & ~(A ^ operand)) & 128); if (AH > 0x9f) { AH += 0x60; } setC(AH > 255); A = (AH | (AL & 15)) & 255; } else { var add = A + data + C; setC(add > 255); setV(((A ^ add) & (data ^ add)) & 0x80); A = add & 255; setZ(A); setN(A); } }); } function newuSLO(addressing) { return addressing(function uSLO() { illegalOpcode("SLO"); var val = data; setC(val & 0x80); // bit 7 was set val = (val << 1) & 255; data = val; val = A | val; A = val; setZ(val); setN(val); }); } function newuSRE(addressing) { return addressing(function uSRE() { illegalOpcode("SRE"); var val = data; setC(val & 0x01); // bit 0 was set val = val >>> 1; data = val; val = (A ^ val) & 255; A = val; setZ(val); setN(val); }); } // Miscellaneous operations function mewPHA() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, function PHA() { pushToStack(A); }, fetchNextOpcode ]; } function newPHP() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, function PHP() { pushToStack(getStatusBits()); }, fetchNextOpcode ]; } function newPLA() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, peekFromStack, function PLA() { A = popFromStack(); setZ(A); setN(A); }, fetchNextOpcode ]; } function newPLP() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, peekFromStack, function PLP() { setStatusBits(popFromStack()); }, fetchNextOpcode ]; } function newJSR() { return [ fetchOpcodeAndDecodeInstruction, fetchADL, peekFromStack, function JSR1() { pushToStack((PC >>> 8) & 0xff); }, function JSR2() { pushToStack(PC & 0xff); }, fetchADH, function JSR3() { PC = AD; fetchNextOpcode(); } ]; } function newBRK() { return [ fetchOpcodeAndDecodeInstruction, fetchDataFromImmediate, // For debugging purposes, use operand as an arg for BRK! function BRK1() { if (self.debug) self.breakpoint("BRK " + data); pushToStack((PC >>> 8) & 0xff); }, function BRK2() { pushToStack(PC & 0xff); }, function BRK3() { pushToStack(getStatusBits()); }, function BRK4() { AD = bus.read(IRQ_VECTOR); }, function BRK5() { AD |= bus.read(IRQ_VECTOR + 1) << 8; }, function BRK6() { PC = AD; fetchNextOpcode(); } ]; } function newRTI() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, peekFromStack, function RTI1() { setStatusBits(popFromStack()); }, function RTI2() { AD = popFromStack(); }, function RTI3() { AD |= popFromStack() << 8; }, function RTI4() { PC = AD; fetchNextOpcode(); } ]; } function newRTS() { return [ fetchOpcodeAndDecodeInstruction, fetchOpcodeAndDiscard, peekFromStack, function RTS1() { AD = popFromStack(); }, function RTS2() { AD |= popFromStack() << 8; }, function RTS3() { PC = AD; fetchDataFromImmediate(); }, fetchNextOpcode ]; } function newJMP_ABS() { return [ fetchOpcodeAndDecodeInstruction, fetchADL, fetchADH, function JMP_ABS() { PC = AD; fetchNextOpcode(); } ]; } function newJMP_IND() { return [ fetchOpcodeAndDecodeInstruction, fetchIAL, // IAH will be zero fetchIAH, fetchBALFromIA, function JMP_IND1() { add1toIAL(); fetchBAHFromIA(); }, function JMP_IND2() { PC = BA; fetchNextOpcode(); } ]; } function newBxx(reg, cond) { var branchTaken; if (reg === bZ) branchTaken = function BxxZ() { return Z === cond; }; else if (reg === bN) branchTaken = function BxxN() { return N === cond; }; else if (reg === bC) branchTaken = function BxxC() { return C === cond; }; else branchTaken = function BxxV() { return V === cond; }; return [ fetchOpcodeAndDecodeInstruction, fetchBranchOffset, function Bxx1() { if (branchTaken()) { fetchOpcodeAndDiscard(); addBranchOffsetToPCL(); } else { fetchNextOpcode(); } }, function Bxx2() { if(branchOffsetCrossAdjust) { fetchOpcodeAndDiscard(); adjustPCHForBranchOffsetCross(); } else { fetchNextOpcode(); } }, fetchNextOpcode ]; } // Savestate ------------------------------------------- this.saveState = function() { return { PC: PC, A: A, X: X, Y: Y, SP: SP, N: N, V: V, D: D, I: I, Z: Z, C: C, T: T, o: opcode, R: RDY | 0, d: data, AD: AD, BA: BA, BC: BALCrossed | 0, IA: IA, bo: branchOffset, boa: branchOffsetCrossAdjust }; }; this.loadState = function(state) { PC = state.PC; A = state.A; X = state.X; Y = state.Y; SP = state.SP; N = state.N; V = state.V; D = state.D; I = state.I; Z = state.Z; C = state.C; T = state.T; opcode = state.o; RDY = !!state.R; data = state.d; AD = state.AD; BA = state.BA; BALCrossed = !!state.BC; IA = state.IA; branchOffset = state.bo; branchOffsetCrossAdjust = state.boa; instruction = opcode === -1 ? boostrapInstruction : instructions[opcode]; // for states saved right after a reset or before first reset }; // Accessory methods this.toString = function() { return "CPU " + " PC: " + PC.toString(16) + " op: " + opcode.toString() + " T: " + T + " data: " + data + "\n" + " A: " + A.toString(16) + " X: " + X.toString(16) + " Y: " + Y.toString(16) + " SP: " + SP.toString(16) + " " + "N" + N + " " + "V" + V + " " + "D" + D + " " + "I" + I + " " + "Z" + Z + " " + "C" + C + " "; }; this.breakpoint = function(mes) { jt.Util.log(mes); if (this.trace) { var text = "CPU Breakpoint! " + (mes ? "(" + mes + ")" : "") + "\n\n" + this.toString(); jt.Util.message(text); } }; //noinspection JSUnusedGlobalSymbols this.runCycles = function(cycles) { //noinspection JSUnresolvedVariable var start = performance.now(); for (var i = 0; i < cycles; i++) { this.clockPulse(); } //noinspection JSUnresolvedVariable var end = performance.now(); jt.Util.message("Done running " + cycles + " cycles in " + (end - start) + " ms."); }; }; ================================================ FILE: src/main/atari/cpu/Ram64K.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Ram64K = function(data) { "use strict"; this.write = function(address, value) { data[address] = value; }; this.read = function(address) { return data[address]; }; this.dump = function(from, to) { var res = ""; var i; for(i = from; i <= to; i++) { res = res + i.toString(16, 2) + " "; } res += "\n"; for(i = from; i <= to; i++) { res = res + this.read(i).toString(16, 2) + " "; } return res; } }; ================================================ FILE: src/main/atari/pia/Pia.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Pia = function() { "use strict"; this.powerOn = function() { }; this.powerOff = function() { }; this.clockPulse = function() { if (--timerCount <= 0) decrementTimer(); }; this.connectBus = function(aBus) { bus = aBus; }; this.read = function(address) { var reg = address & ADDRESS_MASK; if (reg === 0x04 || reg === 0x06) { readFromINTIM(); return INTIM; } if (reg === 0x00) return SWCHA; if (reg === 0x02) return SWCHB; if (reg === 0x01) return SWACNT; if (reg === 0x03) return SWBCNT; if (reg === 0x05 || reg === 0x07) return INSTAT; // Undocumented // debugInfo(String.format("Invalid PIA read register address: %04x", address)); return 0; }; this.write = function(address, i) { var reg = address & ADDRESS_MASK; if (reg === 0x04) { TIM1T = i; setTimerInterval(i, 1); return; } if (reg === 0x05) { TIM8T = i; setTimerInterval(i, 8); return; } if (reg === 0x06) { TIM64T = i; setTimerInterval(i, 64); return; } if (reg === 0x07) { T1024T = i; setTimerInterval(i, 1024); return; } if (reg === 0x02) { swchbWrite(i); return; } if (reg === 0x03) { SWBCNT = i; debugInfo(">>>> Ineffective Write to PIA SWBCNT: " + i); return; } if (reg === 0x00) { debugInfo(">>>> Unsupported Write to PIA SWCHA: " + i); return; } // Output to controllers not supported if (reg === 0x01) { debugInfo(">>>> Unsupported Write to PIA SWACNT " + i); return; } // SWACNT configuration not supported // debugInfo(String.format("Invalid PIA write register address: %04x value %d", address, b)); return 0; }; var decrementTimer = function() { // TODO There might be an accuracy problem here // Also check for overflow if (--INTIM < 0) { INSTAT |= 0xc0; // Set bit 7 and 6 (Overflow since last INTIM read and since last TIMxx write) INTIM = 0xff; // Wrap timer timerCount = currentTimerInterval = 1; // If timer underflows, return to 1 cycle interval per specification } else timerCount = currentTimerInterval; }; var setTimerInterval = function(value, interval) { INTIM = value; INSTAT &= 0x3f; // Reset bit 7 and 6 (Overflow since last INTIM read and since last TIMxx write) timerCount = currentTimerInterval = lastSetTimerInterval = interval; decrementTimer(); // Timer immediately decrements after setting per specification }; var readFromINTIM = function() { INSTAT &= 0xbf; // Resets bit 6 (Overflow since last INTIM read) // If fastDecrement was active (currentTimerInterval == 1), interval always returns to set value after read per specification if (currentTimerInterval === 1) timerCount = currentTimerInterval = lastSetTimerInterval; }; var swchbWrite = function(val) { // Only bits 2, 4 and 5 can be written SWCHB = (SWCHB & 0xcb) | (val & 34); }; var debugInfo = function(str) { if (self.debug) jt.Util.log(str); }; // Controls interface ----------------------------------------- var controls = jt.ConsoleControls; this.controlStateChanged = function(control, state) { switch (control) { case controls.JOY0_UP: if (state) SWCHA &= 0xef; else SWCHA |= 0x10; return; // 0 = Pressed case controls.JOY0_DOWN: if (state) SWCHA &= 0xdf; else SWCHA |= 0x20; return; case controls.PADDLE1_BUTTON: case controls.JOY0_LEFT: if (state) SWCHA &= 0xbf; else SWCHA |= 0x40; return; case controls.PADDLE0_BUTTON: case controls.JOY0_RIGHT: if (state) SWCHA &= 0x7f; else SWCHA |= 0x80; return; case controls.JOY1_UP: if (state) SWCHA &= 0xfe; else SWCHA |= 0x01; return; case controls.JOY1_DOWN: if (state) SWCHA &= 0xfd; else SWCHA |= 0x02; return; case controls.JOY1_LEFT: if (state) SWCHA &= 0xfb; else SWCHA |= 0x04; return; case controls.JOY1_RIGHT: if (state) SWCHA &= 0xf7; else SWCHA |= 0x08; return; case controls.RESET: if (state) SWCHB &= 0xfe; else SWCHB |= 0x01; return; case controls.SELECT: if (state) SWCHB &= 0xfd; else SWCHB |= 0x02; return; } // Toggles if (!state) return; switch (control) { case controls.BLACK_WHITE: if ((SWCHB & 0x08) == 0) SWCHB |= 0x08; else SWCHB &= 0xf7; // 0 = B/W, 1 = Color bus.getTia().getVideoOutput().showOSD((SWCHB & 0x08) != 0 ? "COLOR" : "B/W", true); return; case controls.DIFFICULTY0: if ((SWCHB & 0x40) == 0) SWCHB |= 0x40; else SWCHB &= 0xbf; // 0 = Beginner, 1 = Advanced bus.getTia().getVideoOutput().showOSD((SWCHB & 0x40) != 0 ? "P1 Expert" : "P1 Novice", true); return; case controls.DIFFICULTY1: if ((SWCHB & 0x80) == 0) SWCHB |= 0x80; else SWCHB &= 0x7f; // 0 = Beginner, 1 = Advanced bus.getTia().getVideoOutput().showOSD((SWCHB & 0x80) != 0 ? "P2 Expert" : "P2 Novice", true); return; } }; this.controlsStateReport = function(report) { // Only Panel Controls are visible from outside report[controls.BLACK_WHITE] = (SWCHB & 0x08) === 0; report[controls.DIFFICULTY0] = (SWCHB & 0x40) !== 0; report[controls.DIFFICULTY1] = (SWCHB & 0x80) !== 0; report[controls.SELECT] = (SWCHB & 0x02) === 0; report[controls.RESET] = (SWCHB & 0x01) === 0; }; // Savestate ------------------------------------------- this.saveState = function() { return { t: timerCount, c: currentTimerInterval, l: lastSetTimerInterval, SA: SWCHA, SAC: SWACNT, SB: SWCHB, SBC: SWBCNT, IT: INTIM, IS: INSTAT, T1: TIM1T, T8: TIM8T, T6: TIM64T, T2: T1024T }; }; this.loadState = function(state) { timerCount = state.t; currentTimerInterval = state.c; lastSetTimerInterval = state.l; // SWCHA = state.SA; // Do not load controls state SWACNT = state.SAC; SWCHB = state.SB; SWBCNT = state.SBC; INTIM = state.IT; INSTAT = state.IS; TIM1T = state.T1; TIM8T = state.T8; TIM64T = state.T6; T1024T = state.T2; }; // State Variables ---------------------------------------------- this.debug = false; var bus; var timerCount = 1024; // Start with the largest timer interval var currentTimerInterval = 1024; var lastSetTimerInterval = 1024; // Registers ---------------------------------------------------- var SWCHA= // 11111111 Port A; input or output (read or write) 0xff; // All directions of both controllers OFF var SWACNT = 0; // 11111111 Port A DDR, 0=input, 1=output var SWCHB = // 11..1.11 Port B; console switches (should be read only but unused bits can be written and read) 0x0b; // Reset OFF; Select OFF; B/W OFF; Difficult A/B OFF (Amateur) var SWBCNT = 0; // 11111111 Port B DDR (hard wired as input) var INTIM = // 11111111 Timer output (read only) (Math.random() * 256) | 0 ; // Some random value. Games use this at startup to seed random number generation var INSTAT = 0; // 11...... Timer Status (read only, undocumented) var TIM1T = 0; // 11111111 set 1 clock interval (838 nsec/interval) var TIM8T = 0; // 11111111 set 8 clock interval (6.7 usec/interval) var TIM64T = 0; // 11111111 set 64 clock interval (53.6 usec/interval) var T1024T = 0; // 11111111 set 1024 clock interval (858.2 usec/interval) // Constants ---------------------------------------------------- var ADDRESS_MASK = 0x0007; }; ================================================ FILE: src/main/atari/pia/Ram.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Ram = function() { "use strict"; function init() { // RAM comes totally random at creation for (var i = bytes.length - 1; i >= 0; i--) { bytes[i] = (Math.random() * 256) | 0; } } this.powerOn = function() { }; this.powerOff = function() { }; this.read = function(address) { return bytes[address & ADDRESS_MASK]; }; this.write = function(address, val) { bytes[address & ADDRESS_MASK] = val; }; this.powerFry = function() { var variance = 1 - FRY_VARIANCE + 2 * Math.random() * FRY_VARIANCE; // Randomly put "0" in bits on the ram var fryZeroBits = variance * FRY_ZERO_BITS; for (var i = 0; i < fryZeroBits; i++) bytes[(Math.random() * 128) | 0] &= ((Math.random() * 256) | 0); // Randomly put "1" in bits on the ram var fryOneBits = variance * FRY_ONE_BITS; for (i = 0; i < fryOneBits; i++) bytes[(Math.random() * 128) | 0] |= (0x01 << ((Math.random() * 8) | 0)); }; // Savestate ------------------------------------------- this.saveState = function() { return { b: jt.Util.storeInt8BitArrayToStringBase64(bytes) }; }; this.loadState = function(state) { bytes = jt.Util.restoreStringBase64ToInt8BitArray(state.b, bytes); }; // Variables ------------------------------------------- var bytes = new Array(128); var ADDRESS_MASK = 0x007f; var FRY_ZERO_BITS = 120; // Quantity of bits to change var FRY_ONE_BITS = 25; var FRY_VARIANCE = 0.3; init(); }; ================================================ FILE: src/main/atari/tia/Tia.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // TODO NUSIZ during scan with HMOVE not correct. For now kill the scan in progress // TODO Starfield Effect not implemented // TODO AUTO Video Standard Detection too aggressive? // TODO Vsynch lines count affects vertical position! jt.Tia = function(pCpu, pPia, audioSocket) { "use strict"; var self = this; function init() { generateObjectsLineSprites(); generateObjectsCopiesOffsets(); } this.powerOn = function() { jt.Util.arrayFill(linePixels, VBLANK_COLOR); jt.Util.arrayFill(debugPixels, 0); audioSignal.getChannel0().setVolume(0); audioSignal.getChannel1().setVolume(0); initLatchesAtPowerOn(); hMoveLateHit = false; changeClock = changeClockPrevLine = -1; audioSignal.powerOn(); powerOn = true; }; this.powerOff = function() { powerOn = false; // Let monitors know that the signals are off videoSignal.signalOff(); audioSignal.powerOff(); }; this.frame = function() { do { // Begin line clock = 0; changeClock = -1; renderClock = HBLANK_DURATION; if (debug) { if (debugLevel >= 4) jt.Util.arrayFill(linePixels, 0xff000000); // clear line else if (debugLevel >= 2 && debugLevel < 4) changeClock = 0; // force entire line render } checkLateHMOVE(); // Send the first clock/3 pulse to the CPU and PIA, perceived by TIA at clock 0 before releasing halt, then release halt bus.clockPulse(); cpu.setRDY(true); for (var x = 0; x < 22; ++x) { clock += 3; bus.clockPulse(); } // TIA 3..66 CPU 1..22 updateExtendedHBLANK(); for (var y = 0; y < 27; ++y) { clock += 3; bus.clockPulse(); } // TIA 69..147 CPU 23..49 audioSignal.audioClockPulse(); endObjectsAltStatusMidLine(); for (var z = 0; z < 26; ++z) { clock += 3; bus.clockPulse(); } // TIA 150..225 CPU 50..75 audioSignal.audioClockPulse(); finishLine(); } while(!videoSignal.nextLine(linePixels, vSyncOn)); videoSignal.finishFrame(); }; this.connectBus = function(aBus) { bus = aBus; }; this.getVideoOutput = function() { return videoSignal; }; this.getAudioOutput = function() { return audioSignal; }; this.setVideoStandard = function(standard) { videoSignal.setVideoStandard(standard); palette = jt.TiaPalettes[standard.name]; }; this.debug = function(level) { debugLevel = level > 4 ? 0 : level; debug = debugLevel !== 0; //cpu.debug = debug; pia.debug = debug; if (debug) debugSetColors(); else debugRestoreColors(); }; this.showDebugMessage = function() { videoSignal.showOSD(debug ? "Debug Level " + debugLevel : "Debug OFF", true); }; this.debugNoCollisions = function(state) { debugNoCollisions = !!state; }; this.getDebugNoCollisions = function() { return debugNoCollisions; }; this.read = function(address) { switch(address & READ_ADDRESS_MASK) { // P0P1, P0M0, P0M1, P0PF, P0BL, P1M0, P1M1, P1PF, P1BL, M0M1, M0PF, M0BL, M1PF, M1BL, PFBL, XXXX // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 case 0x00: updateToClock(); return ((collisions & 0x0400) >> 3) | ((collisions & 0x4000) >> 8); // CXM0P case 0x01: updateToClock(); return ((collisions & 0x2000) >> 6) | ((collisions & 0x0200) >> 3); // CXM1P case 0x02: updateToClock(); return ((collisions & 0x1000) >> 5) | ((collisions & 0x0800) >> 5); // CXP0FB case 0x03: updateToClock(); return ((collisions & 0x0100) >> 1) | ((collisions & 0x0080) >> 1); // CXP1FB case 0x04: updateToClock(); return ((collisions & 0x0020) << 2) | ((collisions & 0x0010) << 2); // CXM0FB case 0x05: updateToClock(); return ((collisions & 0x0008) << 4) | ((collisions & 0x0004) << 4); // CXM1FB case 0x06: updateToClock(); return ((collisions & 0x0002) << 6); // CXBLPF case 0x07: updateToClock(); return ((collisions & 0x8000) >> 8) | (collisions & 0x0040); // CXPPMM case 0x08: return INPT0; case 0x09: return INPT1; case 0x0A: return INPT2; case 0x0B: return INPT3; case 0x0C: return INPT4; case 0x0D: return INPT5; default: return 0; } }; this.write = function(address, i) { switch (address & WRITE_ADDRESS_MASK) { // VSync, VBlank and HSync case 0x00: vSyncSet(i); return; case 0x01: vBlankSet(i); return; case 0x02: cpu.setRDY(false); if (debug) debugPixel(DEBUG_WSYNC_COLOR); return; // Halts the CPU until the next HBLANK // Playfield case 0x09: if (COLUBK !== i && !debug) { changeAtClock(); COLUBK = i; playfieldBackground = palette[i]; } return; case 0x0D: if (PF0 !== (i & 0xf0)) { changePlayfieldAtClock(); PF0 = i & 0xf0; playfieldUpdateSprite(); } return; case 0x0E: if (PF1 !== i) { changePlayfieldAtClock(); PF1 = i; playfieldUpdateSprite(); } return; case 0x0F: if (PF2 !== i) { changePlayfieldAtClock(); PF2 = i; playfieldUpdateSprite(); } return; // Playfield & Ball case 0x08: if (COLUPF !== i && !debug) { if ((playfieldEnabled && !playfieldScoreMode) || ballEnabled) changeAtClock(); COLUPF = i; ballColor = palette[i]; if (!playfieldScoreMode) playfieldColor = playfieldLeftColor = playfieldRightColor = ballColor } return; case 0x0A: if (CTRLPF !== i) { playfieldSetShape(i); } return; // Ball case 0x14: hitRESBL(); return; case 0x1F: if (ENABLd !== (i & 0x02)) { ENABLd = i & 0x02; if (!VDELBL) { changeAtClock(); ballSetEnabled(ENABLd); } } return; case 0x27: if (VDELBL !== (i & 1)) { VDELBL = i & 1; if (ENABL !== ENABLd) { changeAtClock(); ballSetEnabled(VDELBL ? ENABL : ENABLd); } } return; // Player0 case 0x04: player0SetShape(i); return; case 0x06: if (COLUP0 !== i && !debug) { COLUP0 = i; if (player0Enabled || missile0Enabled || (playfieldEnabled && playfieldScoreMode)) changeAtClock(); player0Color = missile0Color = palette[i]; if (playfieldScoreMode) playfieldLeftColor = player0Color; } return; case 0x0B: if (REFP0 !== ((i >> 3) & 1)) { REFP0 = (i >> 3) & 1; player0UpdateSprite(0); } return; case 0x10: hitRESP0(); return; case 0x1B: player0SetSprite(i); return; case 0x25: if (VDELP0 !== (i & 1)) { VDELP0 = i & 1; if (GRP0 !== GRP0d) player0UpdateSprite(0); } return; // Player1 case 0x05: player1SetShape(i); return; case 0x07: if (COLUP1 !== i && !debug) { COLUP1 = i; if (player1Enabled || missile1Enabled || (playfieldEnabled && playfieldScoreMode)) changeAtClock(); player1Color = missile1Color = palette[i]; if (playfieldScoreMode) playfieldRightColor = player1Color; } return; case 0x0C: if (REFP1 !== ((i >> 3) & 1)) { REFP1 = (i >> 3) & 1; player1UpdateSprite(0); } return; case 0x11: hitRESP1(); return; case 0x1C: player1SetSprite(i); return; case 0x26: if (VDELP1 !== (i & 1)) { VDELP1 = i & 1; if (GRP1 !== GRP1d) player1UpdateSprite(0); } return; // Missile0 case 0x12: hitRESM0(); return; case 0x1D: if (ENAM0 !== (i & 0x02)) { ENAM0 = i & 0x02; if (!RESMP0) { changeAtClock(); missile0SetEnabled(ENAM0); } } return; case 0x28: missile0SetResetToPlayer(i); return; // Missile1 case 0x13: hitRESM1(); return; case 0x1E: if (ENAM1 !== (i & 0x02)) { ENAM1 = i & 0x02; if (!RESMP1) { changeAtClock(); missile1SetEnabled(ENAM1); } } return; case 0x29: missile1SetResetToPlayer(i); return; // HMOVE case 0x20: HMP0 = (i > 127 ? -16 : 0) + (i >> 4); return; case 0x21: HMP1 = (i > 127 ? -16 : 0) + (i >> 4); return; case 0x22: HMM0 = (i > 127 ? -16 : 0) + (i >> 4); return; case 0x23: HMM1 = (i > 127 ? -16 : 0) + (i >> 4); return; case 0x24: HMBL = (i > 127 ? -16 : 0) + (i >> 4); return; case 0x2A: hitHMOVE(); return; case 0x2B: HMP0 = HMP1 = HMM0 = HMM1 = HMBL = 0; return; // Collisions case 0x2C: changeAtClock(); collisions = 0; return; // RSYNC //case 0x03: clock = 0; return; // Audio case 0x15: if (AUDC0 !== i) { AUDC0 = i; audioSignal.getChannel0().setControl(i & 0x0f); } return; case 0x16: if (AUDC1 !== i) { AUDC1 = i; audioSignal.getChannel1().setControl(i & 0x0f); } return; case 0x17: if (AUDF0 !== i) { AUDF0 = i; audioSignal.getChannel0().setDivider((i & 0x1f) + 1); } return; // Bits 0-4, Divider from 1 to 32 case 0x18: if (AUDF1 !== i) { AUDF1 = i; audioSignal.getChannel1().setDivider((i & 0x1f) + 1); } return; case 0x19: if (AUDV0 !== i) { AUDV0 = i; audioSignal.getChannel0().setVolume(i & 0x0f); } return; // Bits 0-3, Volume from 0 to 15 case 0x1A: if (AUDV1 !== i) { AUDV1 = i; audioSignal.getChannel1().setVolume(i & 0x0f); } return; } }; // caution: endClock can exceed but never wrap end of line! function renderLineTo(endClock) { var p, finalClock = (endClock > LINE_WIDTH ? LINE_WIDTH : endClock); if (vBlankOn) { // No collisions will be detected during VBLANK for (var bPixel = renderClock; bPixel < finalClock; ++bPixel) linePixels[bPixel] = vBlankColor; return; } var newCollisions = collisions; for (var pixel = renderClock - HBLANK_DURATION, finalPixel = finalClock - HBLANK_DURATION; pixel < finalPixel; ++pixel) { // Pixel color and Flags for Collision latches var color = 0, collis = collisionsPossible; if (playfieldPriority) { // Playfield if (playfieldEnabled) { if ((pixel < 80 ? (playfieldPatternL >> (pixel >> 2)) : (playfieldPatternR >> ((pixel - 80) >> 2))) & 1) { color = playfieldColor; // ignore score mode } else collis &= PFC; } // Ball if (ballEnabled) { p = pixel - ballPixel; if (p < 0) p += 160; if ((missileBallLineSprites[ballLineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = ballColor; } else collis &= BLC; } } // Player0 if (player0Enabled) { p = pixel - player0Pixel; if (p < 0) p += 160; if ((playerLineSprites[player0LineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = player0Color; } else collis &= P0C; } // Missile0 if (missile0Enabled) { p = pixel - missile0Pixel; if (p < 0) p += 160; if ((missileBallLineSprites[missile0LineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = missile0Color; } else collis &= M0C; } // Player1 if (player1Enabled) { p = pixel - player1Pixel; if (p < 0) p += 160; if ((playerLineSprites[player1LineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = player1Color; } else collis &= P1C; } // Missile1 if (missile1Enabled) { p = pixel - missile1Pixel; if (p < 0) p += 160; if ((missileBallLineSprites[missile1LineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = missile1Color; } else collis &= M1C; } if (!playfieldPriority) { // Playfield if (playfieldEnabled) { if (pixel < 80) { if ((playfieldPatternL >> (pixel >> 2)) & 1) { if (!color) color = playfieldLeftColor; } else collis &= PFC; } else { if ((playfieldPatternR >> ((pixel - 80) >> 2)) & 1) { if (!color) color = playfieldRightColor; } else collis &= PFC; } } // Ball if (ballEnabled) { p = pixel - ballPixel; if (p < 0) p += 160; if ((missileBallLineSprites[ballLineSpritePointer + (p >> 3)] >> (p & 0x07)) & 1) { if (!color) color = ballColor; } else collis &= BLC; } } // Set pixel color, or background linePixels[pixel + HBLANK_DURATION] = color || playfieldBackground; // Update collision latches newCollisions |= collis; } if (!debugNoCollisions) collisions = newCollisions; } function changeAt(atClock) { if (vBlankOn) return; if (atClock > renderClock) { if (changeClock >= 0 || changeClockPrevLine >= 0) renderLineTo(atClock); renderClock = atClock; } changeClock = renderClock; } function changeAtClock() { changeAt(clock); } function changeAtClockPlus(add) { changeAt(clock + add); // Renders "add" pixels forward, for changes that are only effective after "add" clocks } function changePlayfieldAtClock() { if (debug) debugPixel(DEBUG_PF_GR_COLOR); // PF changes are only effective after 2 clocks. Additionally, once a playfield pixel (4 clocks wide) has started, // it will remain the same until the end. So we will perceive this change accordingly if (clock < renderClock - 1) return changeAtClock(); // Does not matter var ip = clock & 0x03; if (ip < 3) changeAtClockPlus(4 - ip); // Perceive change only at the next PF pixel else changeAtClockPlus(5); // Perceive change only 2 PF pixels later } function changeVBlankAtClockPlus1() { var atClock = clock + 1; if (atClock > renderClock) { if (changeClock >= 0 || changeClockPrevLine >= 0) renderLineTo(atClock); renderClock = atClock; } changeClock = renderClock; } function updateToClock() { // does not trigger change if (vBlankOn) return; if (clock > renderClock) { if (changeClock >= 0 || changeClockPrevLine >= 0) renderLineTo(clock); renderClock = clock; } } var finishLine = function() { // Render remaining part of current line if needed if (changeClock >= 0) { renderLineTo(LINE_WIDTH); changeClockPrevLine = changeClock; } else { if (changeClockPrevLine >= 0) { renderLineTo(changeClockPrevLine); changeClockPrevLine = -1; } } // Disabled repeat mode //renderLineTo(LINE_WIDTH); //changeClockPrevLine = 0; endObjectsAltStatusEndOfLine(); // Handle Paddles capacitor charging, only if paddles are connected (position >= 0) if (paddle0Position >= 0 && !paddleCapacitorsGrounded) { if (INPT0 < 0x80 && ++paddle0CapacitorCharge >= paddle0Position) INPT0 |= 0x80; if (INPT1 < 0x80 && ++paddle1CapacitorCharge >= paddle1Position) INPT1 |= 0x80; } // Inject debugging information in the line if needed if (debugLevel >= 1) processDebugPixelsInLine(); }; function augmentCollisionsPossible() { collisionsPossible = 0xfffe; if (!player0Enabled) collisionsPossible &= P0C; if (!player1Enabled) collisionsPossible &= P1C; if (!missile0Enabled) collisionsPossible &= M0C; if (!missile1Enabled) collisionsPossible &= M1C; if (!playfieldEnabled) collisionsPossible &= PFC; if (!ballEnabled) collisionsPossible &= BLC; } var playfieldSetShape = function(i) { if (CTRLPF === i) return; var v = i & 0x07; if (v !== (CTRLPF & 0x07)) { if (playfieldEnabled) changeAtClock(); v = (i & 0x01) !== 0; if (playfieldReflected !== v) { playfieldReflected = v; playfieldUpdateSpriteR(); } v = (i & 0x02) !== 0; if (playfieldScoreMode !== v) { playfieldScoreMode = v; if (!debug) { if (v) { playfieldLeftColor = player0Color; playfieldRightColor = player1Color } else playfieldColor = playfieldLeftColor = playfieldRightColor = ballColor; } } playfieldPriority = (i & 0x04) !== 0; } v = i & 0x30; if (v !== (CTRLPF & 0x30)) { if (ballEnabled) changeAtClock(); ballLineSpritePointer = (v >> 1) << 6; } CTRLPF = i; }; function playfieldUpdateSprite() { playfieldPatternL = (PF2 << 12) | (jt.Util.reverseInt8(PF1) << 4) | ((PF0 & 0xf0) >> 4); playfieldUpdateSpriteR(); } function playfieldUpdateSpriteR() { playfieldPatternR = playfieldReflected ? (jt.Util.reverseInt8(PF0) << 16) | (PF1 << 8) | jt.Util.reverseInt8(PF2) : playfieldPatternL; if (playfieldPatternL !== 0 || playfieldPatternR !== 0) { playfieldEnabled = true; augmentCollisionsPossible(); } else { playfieldEnabled = false; collisionsPossible &= PFC; } } function ballSetEnabled(boo) { if (boo) { ballEnabled = true; augmentCollisionsPossible(); } else { ballEnabled = false; collisionsPossible &= BLC; } } function player0SetShape(i) { if (NUSIZ0 === i) return; var dif = NUSIZ0 ^ i; var oldNUSIZ0 = NUSIZ0; NUSIZ0 = i; var newShape = (i & 7); var c = clock < HBLANK_DURATION ? 2 : clock - HBLANK_DURATION + 2; //if (debug) debugPixel(DEBUG_ALT_COLOR); if (dif & 0x07) { // Enter Alt mode? if (!player0Alt) { var into = c - player0Pixel; if (into < 0) into += 160; else if (into >= 160) into -= 160; var oldScan = playerScanOffsetsShape[(oldNUSIZ0 & 7) * 160 + into]; var newScan = playerScanOffsetsShape[newShape * 160 + into]; if (newScan !== oldScan) { if (player0Enabled) changeAtClockPlus(2); player0Alt = player0Pixel >= 80 ? 1 : 2; player0LineSpritePointer += 20; player0AltFrom = into; player0AltLength = playerCopyLengthPerShape[newShape]; if (oldScan & 0xc0) player0AltCopyOffset = oldScan & 0xbf; // Scan about to start or in empty area else if (clock < HBLANK_DURATION && hMoveHitBlank) player0AltCopyOffset = 0x80; // Middle of scan during HBLANK, kill scan else { var pixelSize = playerPixelSizePerShape[newShape]; player0AltCopyOffset = playerScanStartPerShape[newShape] + oldScan * pixelSize + (into & 1); player0AltLength -= (newScan & 0xc0 ? 0 : newScan) * pixelSize; } //if (debug && videoSignal.monitor.currentLine() === 150) debugInfo("oldScan: " + oldScan.toString(16) + ", newScan: " + newScan.toString(16) + ", len: " + player0AltLength); } } player0UpdateSprite(2); } if (dif & 0x37) { // Enter Alt mode? if (!missile0Alt) { into = c - missile0Pixel; if (into < 0) into += 160; else if (into >= 160) into -= 160; oldScan = missileScanOffsetsShape[(((oldNUSIZ0 & 0x30) >> 1) | (oldNUSIZ0 & 7)) * 160 + into]; newScan = missileScanOffsetsShape[(((i & 0x30) >> 1) | newShape) * 160 + into]; if (newScan !== oldScan) { if (missile0Enabled) changeAtClockPlus(2); missile0Alt = missile0Pixel >= 80 ? 1 : 2; missile0LineSpritePointer += 20; missile0AltFrom = into; var size = (i & 0x30) >> 4; missile0AltLength = 4 + (1 << size); if (oldScan & 0xc0) missile0AltCopyOffset = oldScan & 0xbf; // Scan about to start or in empty area else if (clock < HBLANK_DURATION && hMoveHitBlank) missile0AltCopyOffset = 0x80; // Middle of scan during HBLANK, kill scan else { missile0AltCopyOffset = 4 + (oldScan << size) + (into & 1); missile0AltLength -= (newScan & 0xc0 ? 0 : newScan) << size; } } } missile0UpdateSprite(2); } } function player0SetSprite(i) { if (debug) debugPixel(DEBUG_P0_GR_COLOR); if (GRP0d !== i) { GRP0d = i; if (!VDELP0) player0UpdateSprite(1); } if (GRP1 !== GRP1d) { GRP1 = GRP1d; if (VDELP1) player1UpdateSprite(1); } } function player0UpdateSprite(clockPlus) { var sprite = VDELP0 ? GRP0 : GRP0d; if (sprite) { var p = (((REFP0 << 11) | (sprite << 3) | (NUSIZ0 & 7)) << 6) + (player0Alt ? 20 : 0); if (!player0Enabled || player0LineSpritePointer !== p) { changeAtClockPlus(clockPlus); player0LineSpritePointer = p; if (player0Alt) player0DefineAlt(); } if (!player0Enabled) { player0Enabled = true; augmentCollisionsPossible(); } } else { if (player0Enabled) { changeAtClockPlus(clockPlus); player0Enabled = false; collisionsPossible &= P0C; } } } function player1SetShape(i) { if (NUSIZ1 === i) return; var dif = NUSIZ1 ^ i; var oldNUSIZ1 = NUSIZ1; NUSIZ1 = i; var newShape = (i & 7); var c = clock < HBLANK_DURATION ? 2 : clock - HBLANK_DURATION + 2; if (dif & 0x07) { // Enter Alt mode? if (!player1Alt) { var into = c - player1Pixel; if (into < 0) into += 160; else if (into >= 160) into -= 160; var oldScan = playerScanOffsetsShape[(oldNUSIZ1 & 7) * 160 + into]; var newScan = playerScanOffsetsShape[newShape * 160 + into]; if (newScan !== oldScan) { if (player1Enabled) changeAtClockPlus(2); player1Alt = player1Pixel >= 80 ? 1 : 2; player1LineSpritePointer += 40; player1AltFrom = into; player1AltLength = playerCopyLengthPerShape[newShape]; if (oldScan & 0xc0) player1AltCopyOffset = oldScan & 0xbf; // Scan about to start or in empty area else if (clock < HBLANK_DURATION && hMoveHitBlank) player1AltCopyOffset = 0x80; // Middle of scan during HBLANK, kill scan else { player1AltCopyOffset = playerScanStartPerShape[newShape] + oldScan * playerPixelSizePerShape[newShape] + (into & 1); player1AltLength -= (newScan & 0xc0 ? 0 : newScan) * playerPixelSizePerShape[newShape]; } } } player1UpdateSprite(2); } if (dif & 0x37) { // Enter Alt mode? if (!missile1Alt) { into = c - missile1Pixel; if (into < 0) into += 160; else if (into >= 160) into -= 160; oldScan = missileScanOffsetsShape[(((oldNUSIZ1 & 0x30) >> 1) | (oldNUSIZ1 & 7)) * 160 + into]; newScan = missileScanOffsetsShape[(((i & 0x30) >> 1) | newShape) * 160 + into]; if (newScan !== oldScan) { if (missile1Enabled) changeAtClockPlus(2); missile1Alt = missile1Pixel >= 80 ? 1 : 2; missile1LineSpritePointer += 40; missile1AltFrom = into; var size = (i & 0x30) >> 4; missile1AltLength = 4 + (1 << size); if (oldScan & 0xc0) missile1AltCopyOffset = oldScan & 0xbf; // Scan about to start or in empty area else if (clock < HBLANK_DURATION && hMoveHitBlank) missile1AltCopyOffset = 0x80; // Middle of scan during HBLANK, kill scan else { missile1AltCopyOffset = 4 + (oldScan << size) + (into & 1); missile1AltLength -= (newScan & 0xc0 ? 0 : newScan) << size; } } } missile1UpdateSprite(2); } } function player1SetSprite(i) { if (debug) debugPixel(DEBUG_P1_GR_COLOR); if (GRP1d !== i) { GRP1d = i; if (!VDELP1) player1UpdateSprite(1); } if (GRP0 !== GRP0d) { GRP0 = GRP0d; if (VDELP0) player0UpdateSprite(1); } if (ENABL !== ENABLd) { ENABL = ENABLd; if (VDELBL) changeAtClockPlus(1); ballSetEnabled(ENABL); } } function player1UpdateSprite(clockPlus) { var sprite = VDELP1 ? GRP1 : GRP1d; if (sprite) { var p = (((REFP1 << 11) | (sprite << 3) | (NUSIZ1 & 7)) << 6) + (player1Alt ? 40 : 0); if (!player1Enabled || player1LineSpritePointer !== p) { changeAtClockPlus(clockPlus); player1LineSpritePointer = p; if (player1Alt) player1DefineAlt(); } if (!player1Enabled) { player1Enabled = true; augmentCollisionsPossible(); } } else { if (player1Enabled) { changeAtClockPlus(clockPlus); player1Enabled = false; collisionsPossible &= P1C; } } } function missile0UpdateSprite(clockPlus) { var p = ((((NUSIZ0 & 0x30) >> 1) | (NUSIZ0 & 7)) << 6) + (missile0Alt ? 20 : 0); if (missile0LineSpritePointer !== p) { if (missile0Enabled) { changeAtClockPlus(clockPlus); missile0LineSpritePointer = p; if (missile0Alt) missile0DefineAlt(); } else missile0LineSpritePointer = p; } } function missile0SetEnabled(boo) { if (boo) { missile0Enabled = true; augmentCollisionsPossible(); if (missile0Alt) missile0DefineAlt(); } else { missile0Enabled = false; collisionsPossible &= M0C; } } function missile0SetResetToPlayer(i) { if (RESMP0 === (i & 0x02)) return; if (ENAM0) { changeAtClock(); missile0SetEnabled(!(RESMP0 = i & 0x02)); } else RESMP0 = i & 0x02; if (!RESMP0) { missile0Pixel = player0Pixel + missileCenterOffsetsPerPlayerSize[NUSIZ0 & 0x07]; if (missile0Pixel >= 160) missile0Pixel -= 160; } } function missile1UpdateSprite(clockPlus) { var p = ((((NUSIZ1 & 0x30) >> 1) | (NUSIZ1 & 7)) << 6) + (missile1Alt ? 40 : 0); if (missile1LineSpritePointer !== p) { if (missile1Enabled) { changeAtClockPlus(clockPlus); missile1LineSpritePointer = p; if (missile1Alt) missile1DefineAlt(); } else missile1LineSpritePointer = p; } } function missile1SetEnabled(boo) { if (boo) { missile1Enabled = true; augmentCollisionsPossible(); if (missile1Alt) missile1DefineAlt(); } else { missile1Enabled = false; collisionsPossible &= M1C; } } function missile1SetResetToPlayer(i) { if (RESMP1 === (i & 0x02)) return; if (ENAM1) { changeAtClock(); missile1SetEnabled(!(RESMP1 = i & 0x02)); } else RESMP1 = i & 0x02; if (!RESMP1) { missile1Pixel = player1Pixel + missileCenterOffsetsPerPlayerSize[NUSIZ1 & 0x07]; if (missile1Pixel >= 160) missile1Pixel -= 160; } } var hitRESP0 = function() { if (debug) debugPixel(DEBUG_P0_RES_COLOR); var r = getRESxPixel(); var p = r >= 0 ? r : -r; if (player0Pixel !== p) { if (player0Enabled) changeAtClock(); var pStart = (r >= 0 ? p : 0); var into = pStart - player0Pixel; if (into < 0) into += 160; player0Pixel = p; var nusiz = NUSIZ0 & 7; if (player0Alt) { if (into <= playerCopyLengthPerShape[nusiz]) return; // Keep current Alt def if still in first copy } else player0LineSpritePointer += 20; var delta = pStart - p; if (delta < -100) delta += 160; player0Alt = p >= 80 ? 1 : 2; player0AltFrom = delta >= 0 ? delta : 160 + delta; player0AltLength = playerCopyLengthPerShape[nusiz] - delta; player0AltCopyOffset = playerCopyOffsetsReset[nusiz * 160 + into]; if (player0Enabled) player0DefineAlt(); //if (debug && videoSignal.monitor.currentLine() === 80) debugInfo("player0Pixel: " + player0Pixel + ", into: " + into + ", delta: " + delta + ", from: " + player0AltFrom + ", len: " + player0AltLength + ", off: " + player0AltCopyOffset); } }; function player0DefineAlt() { var control = (player0AltFrom << 16) | (player0AltLength << 8) | player0AltCopyOffset; var controlPointer = (player0LineSpritePointer - 20) >> 6; if (player0AltControl[controlPointer] === control) return; var basePointer = player0LineSpritePointer - 20; for (var b = 0; b < 20; ++b) playerLineSprites[player0LineSpritePointer + b] = playerLineSprites[basePointer + b]; var p = player0AltFrom; if (player0AltCopyOffset & 0x80) { // Just clear bits for (var c = 0; c < player0AltLength; ++c) { playerLineSprites[player0LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } else { // Copy bits from base basePointer -= objectsLineSpritePointerDeltaToSingleCopy[(NUSIZ0 & 7)]; for (var pBase = player0AltCopyOffset, to = player0AltCopyOffset + player0AltLength; pBase < to; ++pBase) { if ((playerLineSprites[basePointer + (pBase >> 3)] >> (pBase & 0x07)) & 1) playerLineSprites[player0LineSpritePointer + (p >> 3)] |= (1 << (p & 0x07)); else playerLineSprites[player0LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } player0AltControl[controlPointer] = control; } var hitRESP1 = function() { if (debug) debugPixel(DEBUG_P1_RES_COLOR); var r = getRESxPixel(); var p = r >= 0 ? r : -r; if (player1Pixel !== p) { if (player1Enabled) changeAtClock(); var pStart = (r >= 0 ? p : 0); var into = pStart - player1Pixel; if (into < 0) into += 160; player1Pixel = p; var nusiz = NUSIZ1 & 7; if (player1Alt) { if (into <= playerCopyLengthPerShape[nusiz]) return; // Keep current Alt def if still in first copy } else player1LineSpritePointer += 40; var delta = pStart - p; if (delta < -100) delta += 160; player1Alt = p >= 80 ? 1 : 2; player1AltFrom = delta >= 0 ? delta : 160 + delta; player1AltLength = playerCopyLengthPerShape[nusiz] - delta; player1AltCopyOffset = playerCopyOffsetsReset[nusiz * 160 + into]; if (player1Enabled) player1DefineAlt(); } }; function player1DefineAlt() { var control = (player1AltFrom << 16) | (player1AltLength << 8) | player1AltCopyOffset; var controlPointer = (player1LineSpritePointer - 40) >> 6; if (player1AltControl[controlPointer] === control) return; var basePointer = player1LineSpritePointer - 40; for (var b = 0; b < 20; ++b) playerLineSprites[player1LineSpritePointer + b] = playerLineSprites[basePointer + b]; var p = player1AltFrom; if (player1AltCopyOffset & 0x80) { // Just clear bits for (var c = 0; c < player1AltLength; ++c) { playerLineSprites[player1LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } else { // Copy bits from base basePointer -= objectsLineSpritePointerDeltaToSingleCopy[(NUSIZ1 & 7)]; for (var pBase = player1AltCopyOffset, to = player1AltCopyOffset + player1AltLength; pBase < to; ++pBase) { if ((playerLineSprites[basePointer + (pBase >> 3)] >> (pBase & 0x07)) & 1) playerLineSprites[player1LineSpritePointer + (p >> 3)] |= (1 << (p & 0x07)); else playerLineSprites[player1LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } player1AltControl[controlPointer] = control; } var hitRESM0 = function() { if (debug) debugPixel(DEBUG_M0_COLOR); var r = getRESxPixel(); var p = r >= 0 ? r : -r; if (missile0Pixel !== p) { if (missile0Enabled) changeAtClock(); var pStart = (r >= 0 ? p : 0); var into = pStart - missile0Pixel; if (into < 0) into += 160; missile0Pixel = p; if (missile0Alt) { if (into <= 4 + (1 << ((NUSIZ0 & 0x30) >> 4))) return; // Keep current Alt def if still in first copy } else missile0LineSpritePointer += 20; var delta = pStart - p; if (delta < -100) delta += 160; missile0Alt = p >= 80 ? 1 : 2; missile0AltFrom = delta >= 0 ? delta : 160 + delta; missile0AltLength = 4 + (1 << ((NUSIZ0 & 0x30) >> 4)) - delta; missile0AltCopyOffset = missileCopyOffsetsReset[(((NUSIZ0 & 0x30) >> 1) | (NUSIZ0 & 7)) * 160 + into]; if (missile0Enabled) missile0DefineAlt(); } }; function missile0DefineAlt() { var control = (missile0AltFrom << 16) | (missile0AltLength << 8) | missile0AltCopyOffset; var controlPointer = (missile0LineSpritePointer - 20) >> 6; if (missile0AltControl[controlPointer] === control) return; var basePointer = missile0LineSpritePointer - 20; for (var b = 0; b < 20; ++b) missileBallLineSprites[missile0LineSpritePointer + b] = missileBallLineSprites[basePointer + b]; var p = missile0AltFrom; if (missile0AltCopyOffset & 0x80) { // Just clear bits for (var c = 0; c < missile0AltLength; ++c) { missileBallLineSprites[missile0LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } else { // Copy bits from base basePointer -= objectsLineSpritePointerDeltaToSingleCopy[(NUSIZ0 & 7)]; for (var pBase = missile0AltCopyOffset, to = missile0AltCopyOffset + missile0AltLength; pBase < to; ++pBase) { if ((missileBallLineSprites[basePointer + (pBase >> 3)] >> (pBase & 0x07)) & 1) missileBallLineSprites[missile0LineSpritePointer + (p >> 3)] |= (1 << (p & 0x07)); else missileBallLineSprites[missile0LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } missile0AltControl[controlPointer] = control; } var hitRESM1 = function() { if (debug) debugPixel(DEBUG_M1_COLOR); var r = getRESxPixel(); var p = r >= 1 ? r : -r; if (missile1Pixel !== p) { if (missile1Enabled) changeAtClock(); var pStart = (r >= 0 ? p : 0); var into = pStart - missile1Pixel; if (into < 0) into += 160; missile1Pixel = p; if (missile1Alt) { if (into <= 4 + (1 << ((NUSIZ1 & 0x30) >> 4))) return; // Keep current Alt def if still in first copy } else missile1LineSpritePointer += 40; var delta = pStart - p; if (delta < -100) delta += 160; missile1Alt = p >= 80 ? 1 : 2; missile1AltFrom = delta >= 0 ? delta : 160 + delta; missile1AltLength = 4 + (1 << ((NUSIZ1 & 0x30) >> 4)) - delta; missile1AltCopyOffset = missileCopyOffsetsReset[(((NUSIZ1 & 0x30) >> 1) | (NUSIZ1 & 7)) * 160 + into]; if (missile1Enabled) missile1DefineAlt(); } }; function missile1DefineAlt() { var control = (missile1AltFrom << 16) | (missile1AltLength << 8) | missile1AltCopyOffset; var controlPointer = (missile1LineSpritePointer - 40) >> 6; if (missile1AltControl[controlPointer] === control) return; var basePointer = missile1LineSpritePointer - 40; for (var b = 0; b < 20; ++b) missileBallLineSprites[missile1LineSpritePointer + b] = missileBallLineSprites[basePointer + b]; var p = missile1AltFrom; if (missile1AltCopyOffset & 0x80) { // Just clear bits for (var c = 0; c < missile1AltLength; ++c) { missileBallLineSprites[missile1LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } else { // Copy bits from base basePointer -= objectsLineSpritePointerDeltaToSingleCopy[(NUSIZ1 & 7)]; for (var pBase = missile1AltCopyOffset, to = missile1AltCopyOffset + missile1AltLength; pBase < to; ++pBase) { if ((missileBallLineSprites[basePointer + (pBase >> 3)] >> (pBase & 0x07)) & 1) missileBallLineSprites[missile1LineSpritePointer + (p >> 3)] |= (1 << (p & 0x07)); else missileBallLineSprites[missile1LineSpritePointer + (p >> 3)] &= ~(1 << (p & 0x07)); if (++p >= 160) p -= 160; } } missile1AltControl[controlPointer] = control; } var hitRESBL = function() { if (debug) debugPixel(DEBUG_BL_COLOR); var r = getRESxPixel(); var p = r >= 0 ? r : -r; if (ballPixel !== p) { if (ballEnabled) changeAtClock(); ballPixel = p; } }; var hitHMOVE = function() { if (debug) debugPixel(DEBUG_HMOVE_COLOR); // Normal HMOVE if (clock < HBLANK_DURATION) { hMoveHitClock = clock; hMoveHitBlank = true; performHMOVE(); return; } // Unsupported HMOVE if (clock < 219) { // debugInfo("Unsupported HMOVE hit"); return; } // Late HMOVE: Clocks [219-224] hide HMOVE blank next line, clocks [225, 0] produce normal behavior next line // debugInfo("Late HMOVE hit"); hMoveHitClock = 160 - clock; hMoveLateHit = true; hMoveLateHitBlank = clock >= 225; }; // Can only be called during HBLANK! var performHMOVE = function() { // Change objects position var add; var changed = false; add = (hMoveHitBlank ? HMP0 : HMP0 + 8); if (add !== 0) { player0Pixel -= add; if (player0Pixel >= 160) player0Pixel -= 160; else if (player0Pixel < 0) player0Pixel += 160; if (player0Enabled) changed = true; } add = (hMoveHitBlank ? HMP1 : HMP1 + 8); if (add !== 0) { player1Pixel -= add; if (player1Pixel >= 160) player1Pixel -= 160; else if (player1Pixel < 0) player1Pixel += 160; if (player1Enabled) changed = true; } add = (hMoveHitBlank ? HMM0 : HMM0 + 8); if (add !== 0) { missile0Pixel -= add; if (missile0Pixel >= 160) missile0Pixel -= 160; else if (missile0Pixel < 0) missile0Pixel += 160; if (missile0Enabled) changed = true; } add = (hMoveHitBlank ? HMM1 : HMM1 + 8); if (add !== 0) { missile1Pixel -= add; if (missile1Pixel >= 160) missile1Pixel -= 160; else if (missile1Pixel < 0) missile1Pixel += 160; if (missile1Enabled) changed = true; } add = (hMoveHitBlank ? HMBL : HMBL + 8); if (add !== 0) { ballPixel -= add; if (ballPixel >= 160) ballPixel -= 160; else if (ballPixel < 0) ballPixel += 160; if (ballEnabled) changed = true; } if (changed) changeClock = hMoveHitBlank ? HBLANK_DURATION + 8 : HBLANK_DURATION; }; // Negative values mean hit during HBLANK. Invert negative values to get object position, then Alt must be defined considering starting from pixel 0 function getRESxPixel() { // Hit after complete HBLANK or last pixel of Extended HBLANK if (clock >= HBLANK_DURATION + (hMoveHitBlank ? 8 - 1 : 0)) { return clock - HBLANK_DURATION; } else { // Hit during HBLANK if (hMoveHitBlank) { if (clock >= HBLANK_DURATION) { return -6; } else { var d = (clock - hMoveHitClock - 4) >> 2; // Shift right proportionally to distance from HMOVE, up to 8 pixels if (d > 8) return -6; else if (d > 1) return -(d - 2); else return -(158 + d); } } else return -158; } } function checkLateHMOVE() { if (hMoveLateHit) { hMoveLateHit = false; hMoveHitBlank = hMoveLateHitBlank; performHMOVE(); } else hMoveHitBlank = false; } function updateExtendedHBLANK() { // Detect change in the extended HBLANK filling if (hMoveHitBlank !== (linePixels[HBLANK_DURATION] === hBlankColor)) { if (hMoveHitBlank) { // Fills the extended HBLANK portion of the current line linePixels[HBLANK_DURATION] = linePixels[HBLANK_DURATION + 1] = linePixels[HBLANK_DURATION + 2] = linePixels[HBLANK_DURATION + 3] = linePixels[HBLANK_DURATION + 4] = linePixels[HBLANK_DURATION + 5] = linePixels[HBLANK_DURATION + 6] = linePixels[HBLANK_DURATION + 7] = hBlankColor; // This is faster than a fill } else changeClock = HBLANK_DURATION; } if (hMoveHitBlank) renderClock = HBLANK_DURATION + 8; } function endObjectsAltStatusMidLine() { if (player0Alt === 1) { if (player0Enabled) changeAtClock(); player0Alt = 0; player0LineSpritePointer -= 20; } if (player1Alt === 1) { if (player1Enabled) changeAtClock(); player1Alt = 0; player1LineSpritePointer -= 40; } if (missile0Alt === 1) { if (missile0Enabled) changeAtClock(); missile0Alt = 0; missile0LineSpritePointer -= 20; } if (missile1Alt === 1) { if (missile1Enabled) changeAtClock(); missile1Alt = 0; missile1LineSpritePointer -= 40; } } function endObjectsAltStatusEndOfLine() { if (player0Alt === 2) { player0Alt = 0; player0LineSpritePointer -= 20; } if (player1Alt === 2) { player1Alt = 0; player1LineSpritePointer -= 40; } if (missile0Alt === 2) { missile0Alt = 0; missile0LineSpritePointer -= 20; } if (missile1Alt === 2) { missile1Alt = 0; missile1LineSpritePointer -= 40; } } function vSyncSet(i) { if (debug) { debugPixel(VSYNC_COLOR); changeAtClock(); vSyncOn = (i & 0x02) !== 0; vBlankColor = vSyncOn ? VSYNC_COLOR : DEBUG_VBLANK_COLOR; } else vSyncOn = (i & 0x02) !== 0; } var vBlankSet = function(blank) { var v = (blank & 0x02) !== 0; if (vBlankOn !== v) { changeVBlankAtClockPlus1(); //changeAtClockPlus(1); vBlankOn = v; } if ((blank & 0x40) !== 0) { controlsButtonsLatched = true; // Enable Joystick Button latches } else { controlsButtonsLatched = false; // Disable latches and update registers with the current button state if (controlsJOY0ButtonPressed) INPT4 &= 0x7f; else INPT4 |= 0x80; if (controlsJOY1ButtonPressed) INPT5 &= 0x7f; else INPT5 |= 0x80; } if ((blank & 0x80) !== 0) { // Ground paddle capacitors paddleCapacitorsGrounded = true; paddle0CapacitorCharge = paddle1CapacitorCharge = 0; INPT0 &= 0x7f; INPT1 &= 0x7f; INPT2 &= 0x7f; INPT3 &= 0x7f; } else paddleCapacitorsGrounded = false; }; var initLatchesAtPowerOn = function() { collisions = 0; INPT0 = INPT1 = INPT2 = INPT3 = 0; INPT4 = INPT5 = 0x80; }; var debugPixel = function(color) { debugPixels[clock] = color; }; var processDebugPixelsInLine = function() { jt.Util.arrayFillSegment(linePixels, 0, HBLANK_DURATION + (hMoveHitBlank ? 8 : 0), hBlankColor); // Marks if (debugLevel >= 3 && videoSignal.monitor.currentLine() % 10 == 0) { for (var i = 0; i < LINE_WIDTH; i++) { if (debugPixels[i]) continue; if (i < HBLANK_DURATION) { if (i % 6 == 0 || i == 66 || i == 63) debugPixels[i] = DEBUG_MARKS_COLOR; } else { if ((i - HBLANK_DURATION - 1) % 6 == 0) debugPixels[i] = DEBUG_MARKS_COLOR; } } } // Debug Pixels if (debugLevel >= 2) { for (i = 0; i < LINE_WIDTH; i++) { if (debugPixels[i]) { linePixels[i] = debugPixels[i]; debugPixels[i] = 0; } } } }; var debugSetColors = function() { player0Color = DEBUG_P0_COLOR; player1Color = DEBUG_P1_COLOR; missile0Color = DEBUG_M0_COLOR; missile1Color = DEBUG_M1_COLOR; ballColor = DEBUG_BL_COLOR; playfieldColor = playfieldLeftColor = playfieldRightColor = DEBUG_PF_COLOR; playfieldBackground = DEBUG_BK_COLOR; hBlankColor = debugLevel >= 1 ? DEBUG_HBLANK_COLOR : HBLANK_COLOR; vBlankColor = debugLevel >= 1 ? DEBUG_VBLANK_COLOR : VBLANK_COLOR; }; var debugRestoreColors = function() { hBlankColor = HBLANK_COLOR; vBlankColor = VBLANK_COLOR; playfieldBackground = palette[0]; jt.Util.arrayFill(linePixels, hBlankColor); changeAtClock(); }; var info = function(str) { console.error("Line: " + videoSignal.monitor.currentLine() +", Pixel: " + clock + ". " + str); }; var debugInfo = function(str) { if (debug) console.error("Line: " + videoSignal.monitor.currentLine() +", Pixel: " + clock + ". " + str); }; // All possible entire line pixels for players, for all 8 bit patterns (sprites), including all variations (copies) and mirrors function generateObjectsLineSprites() { // Players var line = new Uint8Array(160); for (var mirror = 0; mirror <= 1; ++mirror) { for (var pattern = 0; pattern < 256; ++pattern) { var sprite = !mirror ? jt.Util.reverseInt8(pattern) : pattern; // 1 copy paintSprite(line, sprite, 4 + 1); addPlayerSprite(mirror, pattern, 0, 0, line); // 4 + 1 means player is delayed 4 + 1 pixels // 2 copies close paintSprite(line, sprite, 4 + 16 + 1); addPlayerSprite(mirror, pattern, 1, 0, line); // 3 copies close paintSprite(line, sprite, 4 + 32 + 1); addPlayerSprite(mirror, pattern, 3, 0, line); // 2 copies medium paintSprite(line, 0, 4 + 16 + 1); addPlayerSprite(mirror, pattern, 2, 0, line); // erase close copy // 3 copies medium paintSprite(line, sprite, 4 + 64 + 1); addPlayerSprite(mirror, pattern, 6, 0, line); // 2 copies wide paintSprite(line, 0, 4 + 32 + 1); addPlayerSprite(mirror, pattern, 4, 0, line); // erase medium copy // 1 copy double paintSprite(line, 0, 4 + 64 + 1); line[4 + 1] = 0; // erase wide copy and first pixel paintSpriteDouble(line, sprite, 4 + 1 + 1); addPlayerSprite(mirror, pattern, 5, 0, line); // 4 + 1 + 1 means Double and Quad are delayed 1 extra pixel // 1 copy quad paintSpriteQuad(line, sprite, 4 + 1 + 1); addPlayerSprite(mirror, pattern, 7, 0, line); // empty line paintSpriteQuad(line, 0, 4 + 1 + 1); } } // Missiles & Ball jt.Util.arrayFill(line, 0); for (var size = 0; size < 4; ++size) { sprite = (1 << (1 << size)) - 1; // 1 copy paintSprite(line, sprite, 4); // 4 means missile/ball is delayed 4 pixels addMissileBallSprite(size, 0, 0, line); addMissileBallSprite(size, 5, 0, line); addMissileBallSprite(size, 7, 0, line); // 2 copies close paintSprite(line, sprite, 4 + 16); addMissileBallSprite(size, 1, 0, line); // 3 copies close paintSprite(line, sprite, 4 + 32); addMissileBallSprite(size, 3, 0, line); // 2 copies medium paintSprite(line, 0, 4 + 16); addMissileBallSprite(size, 2, 0, line); // erase close copy // 3 copies medium paintSprite(line, sprite, 4 + 64); addMissileBallSprite(size, 6, 0, line); // 2 copies wide paintSprite(line, 0, 4 + 32); addMissileBallSprite(size, 4, 0, line); // erase medium copy paintSprite(line, 0, 4); // clean line: erase first and wide copy paintSprite(line, 0, 4 + 64); } function paintSprite(line, pat, pos) { for (var b = 0; b < 8; ++b) line[pos + b] = (pat >> b) & 1; } function paintSpriteDouble(line, pat, pos) { for (var b = 0; b < 8; ++b) line[pos + b*2] = line[pos + b*2 + 1] = (pat >> b) & 1; } function paintSpriteQuad(line, pat, pos) { for (var b = 0; b < 8; ++b) line[pos + b*4] = line[pos + b*4 + 1] = line[pos + b*4 + 2] = line[pos + b*4 + 3] = (pat >> b) & 1; } function addPlayerSprite(mirror, pattern, vari, alt, line) { var pos = (((mirror << 11) | (pattern << 3) | vari) << 6) + alt * 20; for (var i = 0; i < 20; ++i) for (var b = 0; b < 8; ++b) if (line[i * 8 + b]) playerLineSprites[pos + i] |= 1 << b; } function addMissileBallSprite(size, vari, alt, line) { var pos = (((size << 3) | vari) << 6) + alt * 20; for (var i = 0; i < 20; ++i) for (var b = 0; b < 8; ++b) if (line[i * 8 + b]) missileBallLineSprites[pos + i] |= 1 << b; } } function generateObjectsCopiesOffsets() { var delays = new Uint8Array(40); delays[0] = 0; delays[1] = 1; delays[2] = 2; delays[3] = 3; // Players jt.Util.arrayFill(playerCopyOffsetsReset, 0x80); jt.Util.arrayFill(playerScanOffsetsShape, 0x80); // Normal Variations for (var p = 0; p < 13; ++p) { // Apply delays for Reset start signal var v = p - delays[p]; playerCopyOffsetsReset[0*160 + p] = v; playerCopyOffsetsReset[1*160 + p] = v; playerCopyOffsetsReset[1*160 + p + 16] = v; playerCopyOffsetsReset[2*160 + p] = v; playerCopyOffsetsReset[2*160 + p + 32] = v; playerCopyOffsetsReset[3*160 + p] = v; playerCopyOffsetsReset[3*160 + p + 16] = v; playerCopyOffsetsReset[3*160 + p + 32] = v; playerCopyOffsetsReset[4*160 + p] = v; playerCopyOffsetsReset[4*160 + p + 64] = v; playerCopyOffsetsReset[6*160 + p] = v; playerCopyOffsetsReset[6*160 + p + 32] = v; playerCopyOffsetsReset[6*160 + p + 64] = v; // Start signal and pixel scan info v = p < 5 ? p | 0x40 : p - 5; playerScanOffsetsShape[0*160 + p] = v; playerScanOffsetsShape[1*160 + p] = v; playerScanOffsetsShape[1*160 + p + 16] = v; playerScanOffsetsShape[2*160 + p] = v; playerScanOffsetsShape[2*160 + p + 32] = v; playerScanOffsetsShape[3*160 + p] = v; playerScanOffsetsShape[3*160 + p + 16] = v; playerScanOffsetsShape[3*160 + p + 32] = v; playerScanOffsetsShape[4*160 + p] = v; playerScanOffsetsShape[4*160 + p + 64] = v; playerScanOffsetsShape[6*160 + p] = v; playerScanOffsetsShape[6*160 + p + 32] = v; playerScanOffsetsShape[6*160 + p + 64] = v; } // Double Variation for (p = 0; p < 22; p++) { v = p - delays[p]; playerCopyOffsetsReset[5 * 160 + p] = v; v = p < 6 ? p | 0x40 : (p - 6) >> 1; playerScanOffsetsShape[5 * 160 + p] = v; } // Quad Variation for (p = 0; p < 38; p++) { v = p - delays[p]; playerCopyOffsetsReset[7 * 160 + p] = v; v = p < 6 ? p | 0x40 : (p - 6) >> 2; playerScanOffsetsShape[7 * 160 + p] = v; } // Missiles jt.Util.arrayFill(missileCopyOffsetsReset, 0x80); jt.Util.arrayFill(missileScanOffsetsShape, 0x80); // All Size * Variations for (var s = 0; s <= 3; ++s) { var d = 4 + (1 << s); for (p = 0; p < d; ++p) { v = p - delays[p]; missileCopyOffsetsReset[s*8*160 + 0*160 + p] = v; missileCopyOffsetsReset[s*8*160 + 1*160 + p] = v; missileCopyOffsetsReset[s*8 + 1*160 + p + 16] = v; missileCopyOffsetsReset[s*8*160 + 2*160 + p] = v; missileCopyOffsetsReset[s*8 + 2*160 + p + 32] = v; missileCopyOffsetsReset[s*8*160 + 3*160 + p] = v; missileCopyOffsetsReset[s*8 + 3*160 + p + 16] = v; missileCopyOffsetsReset[s*8*160 + 3*160 + p + 32] = v; missileCopyOffsetsReset[s*8*160 + 4*160 + p] = v; missileCopyOffsetsReset[s*8 + 4*160 + p + 64] = v; missileCopyOffsetsReset[s*8*160 + 5*160 + p] = v; missileCopyOffsetsReset[s*8*160 + 6*160 + p] = v; missileCopyOffsetsReset[s*8 + 6*160 + p + 32] = v; missileCopyOffsetsReset[s*8*160 + 6*160 + p + 64] = v; missileCopyOffsetsReset[s*8*160 + 7*160 + p] = v; v = p < 4 ? p | 0x40 : (p - 4) >> s; missileScanOffsetsShape[s*8*160 + 0*160 + p] = v; missileScanOffsetsShape[s*8*160 + 1*160 + p] = v; missileScanOffsetsShape[s*8 + 1*160 + p + 16] = v; missileScanOffsetsShape[s*8*160 + 2*160 + p] = v; missileScanOffsetsShape[s*8 + 2*160 + p + 32] = v; missileScanOffsetsShape[s*8*160 + 3*160 + p] = v; missileScanOffsetsShape[s*8 + 3*160 + p + 16] = v; missileScanOffsetsShape[s*8*160 + 3*160 + p + 32] = v; missileScanOffsetsShape[s*8*160 + 4*160 + p] = v; missileScanOffsetsShape[s*8 + 4*160 + p + 64] = v; missileScanOffsetsShape[s*8*160 + 5*160 + p] = v; missileScanOffsetsShape[s*8*160 + 6*160 + p] = v; missileScanOffsetsShape[s*8 + 6*160 + p + 32] = v; missileScanOffsetsShape[s*8*160 + 6*160 + p + 64] = v; missileScanOffsetsShape[s*8*160 + 7*160 + p] = v; } } } // Controls interface ----------------------------------- var controls = jt.ConsoleControls; this.controlStateChanged = function(control, state) { switch (control) { case controls.JOY0_BUTTON: if (state) { controlsJOY0ButtonPressed = true; INPT4 &= 0x7f; } else { controlsJOY0ButtonPressed = false; if (!controlsButtonsLatched) // Does not lift the button if Latched Mode is on INPT4 |= 0x80; } return; case controls.JOY1_BUTTON: if (state) { controlsJOY1ButtonPressed = true; INPT5 &= 0x7f; } else { controlsJOY1ButtonPressed = false; if (!controlsButtonsLatched) // Does not lift the button if Latched Mode is on INPT5 |= 0x80; } return; } // Toggles if (!state) return; switch (control) { case controls.DEBUG: self.debug(debugLevel + 1); self.showDebugMessage(); return; case controls.SHOW_INFO: videoSignal.toggleShowInfo(); return; case controls.NO_COLLISIONS: self.debugNoCollisions(!debugNoCollisions); videoSignal.showOSD(debugNoCollisions ? "No Collisions: ON" : "No Collisions: OFF", true); } }; this.controlValueChanged = function(control, position) { switch (control) { case controls.PADDLE0_POSITION: paddle0Position = position; return; case controls.PADDLE1_POSITION: paddle1Position = position; return; } }; // Savestate ------------------------------------------------ this.saveState = function(extended) { var s = { ccp: changeClockPrevLine, lpx: jt.Util.storeInt32BitArrayToStringBase64(linePixels), vs: vSyncOn, vb: vBlankOn, pfe: playfieldEnabled, pfl: playfieldPatternL, pfr: playfieldPatternR, pfc: playfieldColor, pflc: playfieldLeftColor, pfrc: playfieldRightColor, pfb: playfieldBackground, pfrl: playfieldReflected, pfsc: playfieldScoreMode, pfp: playfieldPriority, be: ballEnabled, bx: ballPixel, blp: ballLineSpritePointer, bc: ballColor, p0e: player0Enabled, p0x: player0Pixel, p0lp: player0LineSpritePointer, p0a: player0Alt, p0af: player0AltFrom, p0al: player0AltLength, p0ao: player0AltCopyOffset, p0c: player0Color, p1e: player1Enabled, p1x: player1Pixel, p1lp: player1LineSpritePointer, p1a: player1Alt, p1af: player1AltFrom, p1al: player1AltLength, p1ao: player1AltCopyOffset, p1c: player1Color, m0e: missile0Enabled, m0x: missile0Pixel, m0lp: missile0LineSpritePointer, m0a: missile0Alt, m0af: missile0AltFrom, m0al: missile0AltLength, m0ao: missile0AltCopyOffset, m0c: missile0Color, m1e: missile1Enabled, m1x: missile1Pixel, m1lp: missile1LineSpritePointer, m1a: missile1Alt, m1af: missile1AltFrom, m1al: missile1AltLength, m1ao: missile1AltCopyOffset, m1c: missile1Color, hmh: hMoveHitBlank, hmc: hMoveHitClock, hmlh: hMoveLateHit, hmlb: hMoveLateHitBlank, co: collisions, cop: collisionsPossible, cod: debugNoCollisions, cbl: controlsButtonsLatched, j0p: controlsJOY0ButtonPressed, j1p: controlsJOY1ButtonPressed, pcg: paddleCapacitorsGrounded, pd0: paddle0Position, pd0c: paddle0CapacitorCharge, pd1: paddle1Position, pd1c: paddle1CapacitorCharge, CTRLPF: CTRLPF, COLUPF: COLUPF, COLUBK: COLUBK, PF0: PF0, PF1: PF1, PF2: PF2, ENABL: ENABL, ENABLd: ENABLd, VDELBL: VDELBL, NUSIZ0: NUSIZ0, COLUP0: COLUP0, REFP0: REFP0, GRP0: GRP0, GRP0d: GRP0d, VDELP0: VDELP0, NUSIZ1: NUSIZ1, COLUP1: COLUP1, REFP1: REFP1, GRP1: GRP1, GRP1d: GRP1d, VDELP1: VDELP1, ENAM0: ENAM0, RESMP0: RESMP0, ENAM1: ENAM1, RESMP1: RESMP1, HMP0: HMP0, HMP1: HMP1, HMM0: HMM0, HMM1: HMM1, HMBL: HMBL, AUDC0: AUDC0, AUDC1: AUDC1, AUDF0: AUDF0, AUDF1: AUDF1, AUDV0: AUDV0, AUDV1: AUDV1 }; if (extended) s.dl = debugLevel; return s; }; this.loadState = function(s) { changeClockPrevLine = s.ccp; jt.Util.restoreStringBase64ToInt32BitArray(s.lpx, linePixels); vSyncOn = s.vs; vBlankOn = s.vb; playfieldEnabled = s.pfe; playfieldPatternL = s.pfl | 0; playfieldPatternR = s.pfr | 0; playfieldColor = s.pfc | 0; playfieldLeftColor = s.pflc | 0; playfieldRightColor = s.pfrc | 0; playfieldBackground = s.pfb | 0; playfieldReflected = s.pfrl; playfieldScoreMode = s.pfsc; playfieldPriority = s.pfp; ballEnabled = s.be; ballPixel = s.bx | 0; ballLineSpritePointer = s.blp | 0; ballColor = s.bc | 0; player0Enabled = s.p0e; player0Pixel = s.p0x | 0; player0LineSpritePointer = s.p0lp | 0; player0Alt = s.p0a | 0; player0AltFrom = s.p0af | 0; player0AltLength = s.p0al | 0; player0AltCopyOffset = s.p0ao | 0; jt.Util.arrayFill(player0AltControl, 0); player0Color = s.p0c | 0; player1Enabled = s.p1e; player1Pixel = s.p1x | 0; player1LineSpritePointer = s.p1lp | 0; player1Alt = s.p1a | 0; player1AltFrom = s.p1af | 0; player1AltLength = s.p1al | 0; player1AltCopyOffset = s.p1ao | 0; jt.Util.arrayFill(player1AltControl, 0); player1Color = s.p1c | 0; missile0Enabled = s.m0e; missile0Pixel = s.m0x | 0; missile0LineSpritePointer = s.m0lp | 0; missile0Alt = s.m0a | 0; missile0AltFrom = s.m0af | 0; missile0AltLength = s.m0al | 0; missile0AltCopyOffset = s.m0ao | 0; jt.Util.arrayFill(missile0AltControl, 0); missile0Color = s.m0c | 0; missile1Enabled = s.m1e; missile1Pixel = s.m1x | 0; missile1LineSpritePointer = s.m1lp | 0; missile1Alt = s.m1a | 0; missile1AltFrom = s.m1af | 0; missile1AltLength = s.m1al | 0; missile1AltCopyOffset = s.m1ao | 0; jt.Util.arrayFill(missile1AltControl, 0); missile1Color = s.m1c | 0; hMoveHitBlank = s.hmh; hMoveHitClock = s.hmc | 0; hMoveLateHit = s.hmlh; hMoveLateHitBlank = s.hmlb; collisions = s.co | 0; collisionsPossible = s.cop | 0; if (s.cod !== undefined) debugNoCollisions = s.cod; if (s.cbl !== undefined) { // backward compatibility controlsButtonsLatched = s.cbl; controlsJOY0ButtonPressed = s.j0p; controlsJOY1ButtonPressed = s.j1p; paddleCapacitorsGrounded = s.pcg; paddle0Position = s.pd0; paddle0CapacitorCharge = s.pd0c; paddle1Position = s.pd1; paddle1CapacitorCharge = s.pd1c; } CTRLPF = s.CTRLPF | 0; COLUPF = s.COLUPF | 0; COLUBK = s.COLUBK | 0; PF0 = s.PF0 | 0; PF1 = s.PF1 | 0; PF2 = s.PF2 | 0; ENABL = s.ENABL | 0; ENABLd = s.ENABLd | 0; VDELBL = s.VDELBL | 0; NUSIZ0 = s.NUSIZ0 | 0; COLUP0 = s.COLUP0 | 0; REFP0 = s.REFP0 | 0; GRP0 = s.GRP0 | 0; GRP0d = s.GRP0d | 0; VDELP0 = s.VDELP0 | 0; NUSIZ1 = s.NUSIZ1 | 0; COLUP1 = s.COLUP1 | 0; REFP1 = s.REFP1 | 0; GRP1 = s.GRP1 | 0; GRP1d = s.GRP1d | 0; VDELP1 = s.VDELP1 | 0; ENAM0 = s.ENAM0 | 0; RESMP0 = s.RESMP0 | 0; ENAM1 = s.ENAM1 | 0; RESMP1 = s.RESMP1 | 0; HMP0 = s.HMP0 | 0; HMP1 = s.HMP1 | 0; HMM0 = s.HMM0 | 0; HMM1 = s.HMM1 | 0; HMBL = s.HMBL | 0; AUDC0 = s.AUDC0 | 0; audioSignal.getChannel0().setControl(AUDC0 & 0x0f); // Also update the Audio Generator AUDC1 = s.AUDC1 | 0; audioSignal.getChannel1().setControl(AUDC1 & 0x0f); AUDF0 = s.AUDF0 | 0; audioSignal.getChannel0().setDivider((AUDF0 & 0x1f) + 1); AUDF1 = s.AUDF1 | 0; audioSignal.getChannel1().setDivider((AUDF1 & 0x1f) + 1); AUDV0 = s.AUDV0 | 0; audioSignal.getChannel0().setVolume(AUDV0 & 0x0f); AUDV1 = s.AUDV1 | 0; audioSignal.getChannel1().setVolume(AUDV1 & 0x0f); if (s.dl !== undefined) this.debug(s.dl); else if (debug) debugSetColors(); }; // Constants ------------------------------------------------ var HBLANK_DURATION = 68; var LINE_WIDTH = 228; var VBLANK_COLOR = 0xff000000; // CHECK: Full transparency needed for CRT emulation modes var HBLANK_COLOR = 0xfe000000; // Alpha of 0xfe used to detect extended HBLANK (alpha is unnoticeable) var VSYNC_COLOR = 0xffdddddd; var DEBUG_P0_COLOR = 0xff0000ff; var DEBUG_P0_RES_COLOR = 0xff2222bb; var DEBUG_P0_GR_COLOR = 0xff111177; var DEBUG_P1_COLOR = 0xffff0000; var DEBUG_P1_RES_COLOR = 0xffbb2222; var DEBUG_P1_GR_COLOR = 0xff771111; var DEBUG_M0_COLOR = 0xff6666ff; var DEBUG_M1_COLOR = 0xffff6666; var DEBUG_PF_COLOR = 0xff448844; var DEBUG_PF_GR_COLOR = 0xff33dd33; var DEBUG_BK_COLOR = 0xff334433; var DEBUG_BL_COLOR = 0xff00ffff; var DEBUG_MARKS_COLOR = 0xff202020; var DEBUG_HBLANK_COLOR = 0xff444444; var DEBUG_VBLANK_COLOR = 0xff2a2a2a; var DEBUG_WSYNC_COLOR = 0xff880088; var DEBUG_HMOVE_COLOR = 0xffffffff; var DEBUG_ALT_COLOR = 0xffaaaa00; var READ_ADDRESS_MASK = 0x000f; var WRITE_ADDRESS_MASK = 0x003f; // Collision bit patterns: P0P1, P0M0, P0M1, P0PF, P0BL, P1M0, P1M1, P1PF, P1BL, M0M1, M0PF, M0BL, M1PF, M1BL, PFBL, none var P0C = ~0xf800; // 1111 1000 0000 0000 var P1C = ~0x8780; // 1000 0111 1000 0000 var M0C = ~0x4470; // 0100 0100 0111 0000 var M1C = ~0x224c; // 0010 0010 0100 1100 var PFC = ~0x112a; // 0001 0001 0010 1010 var BLC = ~0x0896; // 0000 1000 1001 0110 // Variables --------------------------------------------------- var cpu = pCpu; var pia = pPia; var bus; var powerOn = false; var clock, changeClock, changeClockPrevLine, renderClock; var linePixels = new Uint32Array(LINE_WIDTH); var vSyncOn = false; var vBlankOn = false; var vBlankColor = VBLANK_COLOR; var hBlankColor = HBLANK_COLOR; var playfieldEnabled = false, playfieldPatternL = 0, playfieldPatternR = 0; var playfieldColor = 0xff000000, playfieldLeftColor = 0xff000000, playfieldRightColor = 0xff000000; var playfieldBackground = 0xff000000; var playfieldReflected = false; var playfieldScoreMode = false; var playfieldPriority = false; var ballEnabled = false, ballPixel = 0, ballLineSpritePointer = 0; var ballColor = 0xff000000; var player0Enabled = false, player0Pixel = 0, player0LineSpritePointer = 0; var player0Alt = 0, player0AltFrom = 0, player0AltLength = 0, player0AltCopyOffset = 0; var player0AltControl = new Uint32Array(2 * 256 * 8); var player0Color = 0xff000000; var player1Enabled = false, player1Pixel = 0, player1LineSpritePointer = 0; var player1Alt = 0, player1AltFrom = 0, player1AltLength = 0, player1AltCopyOffset = 0; var player1AltControl = new Uint32Array(2 * 256 * 8); var player1Color = 0xff000000; var missile0Enabled = false, missile0Pixel = 0, missile0LineSpritePointer = 0; var missile0Alt = 0, missile0AltFrom = 0, missile0AltLength = 0, missile0AltCopyOffset = 0; var missile0AltControl = new Uint32Array(4 * 8); var missile0Color = 0xff000000; var missile1Enabled = false, missile1Pixel = 0, missile1LineSpritePointer = 0; var missile1Alt = 0, missile1AltFrom = 0, missile1AltLength = 0, missile1AltCopyOffset = 0; var missile1AltControl = new Uint32Array(4 * 8); var missile1Color = 0xff000000; var hMoveHitBlank = false; var hMoveHitClock = 0; var hMoveLateHit = false; var hMoveLateHitBlank = false; var collisions = 0, collisionsPossible = 0; var controlsButtonsLatched = false; var controlsJOY0ButtonPressed = false; var controlsJOY1ButtonPressed = false; var paddleCapacitorsGrounded = false; var paddle0Position = -1; // 380 = Left, 190 = Middle, 0 = Right. -1 = disconnected, won't charge POTs var paddle0CapacitorCharge = 0; var paddle1Position = -1; var paddle1CapacitorCharge = 0; var debug = false; var debugLevel = 0; var debugNoCollisions = false; var debugPixels = new Uint32Array(LINE_WIDTH); var playerLineSprites = new Uint8Array(2 * 256 * 8 * 64); // 2 Mirrors * 256 Patterns * 8 Variations * (1 base + 2 alts) * 20 8Bits line data specifying 1bit pixels + 4 bytes spare var missileBallLineSprites = new Uint8Array(4 * 8 * 64); // 4 Sizes * 8 Variations * (1 base + 2 alts) * 20 8Bits line data specifying 1bit pixels + 4 bytes spare var playerCopyLengthPerShape = new Uint8Array([13, 13, 13, 13, 13, 22, 13, 38]); var playerScanStartPerShape = new Uint8Array([5, 5, 5, 5, 5, 6, 5, 6]); var playerPixelSizePerShape = new Uint8Array([1, 1, 1, 1, 1, 2, 1, 4]); var playerCopyOffsetsReset = new Uint8Array(8 * 160); // 8 Variations * 160 1 byte data with copy pixel position var playerScanOffsetsShape = new Uint8Array(8 * 160); // 8 Variations * 160 1 byte data with copy pixel position var missileCopyOffsetsReset = new Uint8Array(4 * 8 * 160); // 4 Sizes * 8 Variations * 160 1 byte data with copy pixel position var missileScanOffsetsShape = new Uint8Array(4 * 8 * 160); // 4 Sizes * 8 Variations * 160 1 byte data with copy pixel position var objectsLineSpritePointerDeltaToSingleCopy = new Uint16Array([0 * 64, 1 * 64, 2 * 64, 3 * 64, 4 * 64, 0 * 64, 6 * 64, 0 * 64]); var missileCenterOffsetsPerPlayerSize = new Uint8Array([ 5, 5, 5, 5, 5, 10, 5, 18 ]); var videoSignal = new jt.VideoSignal(); var palette; var audioSignal = new jt.TiaAudio(audioSocket); // Read registers ------------------------------------------- var INPT0 = 0; // Paddle0 Left pot port var INPT1 = 0; // Paddle0 Right pot port var INPT2 = 0; // Paddle1 Left pot port var INPT3 = 0; // Paddle1 Right pot port var INPT4 = 0; // input (Joy0 button) var INPT5 = 0; // input (Joy1 button) // Write registers ------------------------------------------ var CTRLPF = 0; // ..11.111 control playfield ball size & collisions var COLUPF = 0; // 11111111 playfield and ball color var COLUBK = 0; // 11111111 playfield background color var PF0 = 0; // 1111.... playfield register byte 0 var PF1 = 0; // 11111111 playfield register byte 1 var PF2 = 0; // 11111111 playfield register byte 2 var ENABL = 0; // ......1. graphics (enable) ball var ENABLd = 0; // ......1. graphics (enable) ball var VDELBL = 0; // .......1 vertical delay ball var NUSIZ0 = 0; // ..111111 number-size player-missile 0 var COLUP0 = 0; // 11111111 color-lum player 0 and missile 0 var REFP0 = 0; // ....1... reflect player 0 (>> 3) var GRP0 = 0; // 11111111 graphics player 0 var GRP0d = 0; // 11111111 graphics player 0 (delayed) var VDELP0 = 0; // .......1 vertical delay player 0 var NUSIZ1 = 0; // ..111111 number-size player-missile 1 var COLUP1 = 0; // 11111111 color-lum player 1 and missile 1 var REFP1 = 0; // ....1... reflect player 1 (>> 3) var GRP1 = 0; // 11111111 graphics player 1 var GRP1d = 0; // 11111111 graphics player 1 (delayed) var VDELP1 = 0; // .......1 vertical delay player 1 var ENAM0 = 0; // ......1. graphics (enable) missile 0 var RESMP0 = 0; // ......1. reset missile 0 to player 0 var ENAM1 = 0; // ......1. graphics (enable) missile 1 var RESMP1 = 0; // ......1. reset missile 1 to player 1 var HMP0 = 0; // 1111.... horizontal motion player 0 var HMP1 = 0; // 1111.... horizontal motion player 1 var HMM0 = 0; // 1111.... horizontal motion missile 0 var HMM1 = 0; // 1111.... horizontal motion missile 1 var HMBL = 0; // 1111.... horizontal motion ball var AUDC0 = 0; // ....1111 audio control 0 var AUDC1 = 0; // ....1111 audio control 1 var AUDF0 = 0; // ...11111 audio frequency 0 var AUDF1 = 0; // ...11111 audio frequency 1 var AUDV0 = 0; // ....1111 audio volume 0 var AUDV1 = 0; // ....1111 audio volume 1 init(); self.eval = function(code) { return eval(code); } }; ================================================ FILE: src/main/atari/tia/TiaAudio.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.TiaAudio = function() { "use strict"; var self = this; this.connectAudioSocket = function(pAudioSocket) { audioSocket = pAudioSocket; }; this.cartridgeInserted = function(pCartridge) { if (pCartridge && pCartridge.needsAudioClock()) cartridgeNeedsAudioClock = pCartridge; else cartridgeNeedsAudioClock = null; }; this.audioClockPulse = function() { audioSocket.audioClockPulse(); }; this.getChannel0 = function() { return channel0; }; this.getChannel1 = function() { return channel1; }; this.powerOn = function() { this.reset(); connectAudio(); }; this.powerOff = function() { disconnectAudio(); }; this.reset = function() { channel0.setVolume(0); channel1.setVolume(0); lastSample = 0; }; this.nextSample = function() { if (cartridgeNeedsAudioClock) cartridgeNeedsAudioClock.audioClockPulse(); var mixedSample = channel0.nextSample() - channel1.nextSample(); // Add a little damper effect to round the edges of the square wave if (mixedSample !== lastSample) { mixedSample = (mixedSample * 9 + lastSample) / 10; lastSample = mixedSample; } return mixedSample; }; function connectAudio() { if (!audioSignal) audioSignal = new jt.AudioSignal("TiaAudio", self, SAMPLE_RATE, VOLUME); audioSocket.connectAudioSignal(audioSignal); } function disconnectAudio() { if (audioSignal) audioSocket.disconnectAudioSignal(audioSignal); } var audioSocket; var audioSignal; var cartridgeNeedsAudioClock; var lastSample = 0; var channel0 = new jt.TiaAudioChannel(); var channel1 = new jt.TiaAudioChannel(); var VOLUME = 0.4; var SAMPLE_RATE = 31440; }; ================================================ FILE: src/main/atari/tia/TiaAudioChannel.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.TiaAudioChannel = function() { "use strict"; this.nextSample = function() { // Range 0 - 1 if (--dividerCountdown <= 0) { dividerCountdown += divider; currentSample = nextSampleForControl(); } return currentSample === 1 ? volume : 0; }; this.setVolume = function(newVolume) { volume = newVolume / MAX_VOLUME; }; this.setDivider = function(newDivider) { if (divider === newDivider) return; dividerCountdown = (dividerCountdown / divider) * newDivider; divider = newDivider; }; this.setControl = function(newControl) { if (control === newControl) return; control = newControl; if (newControl === 0x00 || newControl === 0x0b) nextSampleForControl = nextSilence; // Silence ("set to 1" per specification) else if (newControl === 0x01) nextSampleForControl = nextPoly4; // 4 bit poly else if (newControl === 0x02) nextSampleForControl = nextDiv15Poly4; // div 15 > 4 bit poly else if (newControl === 0x03) nextSampleForControl = nextPoly5Poly4; // 5 bit poly > 4 bit poly else if (newControl === 0x04 || newControl === 0x05) nextSampleForControl = nextTone2; // div 2 pure tone else if (newControl === 0x06 || newControl === 0x0a) nextSampleForControl = nextTone31; // div 31 pure tone (18 high, 13 low) else if (newControl === 0x07 || newControl === 0x09) nextSampleForControl = nextPoly5; // 5 bit poly else if (newControl === 0x08) nextSampleForControl = nextPoly9; // 9 bit poly else if (newControl === 0x0c || newControl === 0x0d) nextSampleForControl = nextTone6; // div 6 pure tone (3 high, 3 low) else if (newControl === 0x0e) nextSampleForControl = nextDiv93; // div 93 pure tone (31 tone each 3) else if (newControl === 0x0f) nextSampleForControl = nextPoly5Div6; // 5 bit poly div 6 (poly 5 each 3) else nextSampleForControl = nextSilence; // default }; var nextSilence = function() { return 1; }; var currentPoly4 = function() { return POLY4_STREAM[poly4Count]; }; var nextPoly4 = function() { if (++poly4Count === 15) poly4Count = 0; return POLY4_STREAM[poly4Count]; }; var nextPoly5 = function() { if (++poly5Count === 31) poly5Count = 0; return POLY5_STREAM[poly5Count]; }; var nextPoly9 = function() { var carry = poly9 & 0x01; // bit 0 var push = ((poly9 >> 4) ^ carry) & 0x01; // bit 4 XOR bit 0 poly9 = poly9 >>> 1; // shift right if (push === 0) // set bit 8 = push poly9 &= 0x0ff; else poly9 |= 0x100; return carry; }; var nextTone2 = function() { if (divider === 1) // Divider 1 and Tone2 should never produce sound return 1; else return tone2 = tone2 ? 0 : 1; }; var currentTone6 = function() { return tone6; }; var nextTone6 = function() { if (--tone6Countdown === 0) { tone6Countdown = 3; tone6 = tone6 ? 0 : 1; } return tone6; }; var currentTone31 = function() { return TONE31_STREAM[tone31Count]; }; var nextTone31 = function() { if (++tone31Count === 31) tone31Count = 0; return TONE31_STREAM[tone31Count]; }; var nextDiv15Poly4 = function() { return currentTone31() !== nextTone31() ? nextPoly4() : currentPoly4(); }; var nextPoly5Poly4 = function() { return nextPoly5() ? nextPoly4() : currentPoly4(); }; var nextDiv93 = function() { return currentTone31() != nextTone31() ? nextTone6() : currentTone6(); }; var nextPoly5Div6 = function() { return nextPoly5() ? nextTone6() : currentTone6(); }; var nextSampleForControl = nextSilence; var volume = 0; // 0 - 1 var control = 0; // 0-f var divider = 1; // Changes to dividers will only be reflected at the next countdown cycle var dividerCountdown = 1; var currentSample = 0; var tone2 = 1; var tone6 = 1; var tone6Countdown = 3; var poly9 = 0x1ff; var poly4Count = 14; var POLY4_STREAM = [1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0 ]; var poly5Count = 30; var POLY5_STREAM = [1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0]; var tone31Count = 30; var TONE31_STREAM = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; var MAX_VOLUME = 15; }; ================================================ FILE: src/main/atari/tia/TiaPalettes.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. (function() { "use strict"; var ntscRGB = [ 0x000000, // 00 0x404040, // 02 0x6c6c6c, // 04 0x909090, // 06 0xb0b0b0, // 08 0xc8c8c8, // 0A 0xdcdcdc, // 0C 0xf4f4f4, // 0E 0x004444, // 10 0x106464, // 12 0x248484, // 14 0x34a0a0, // 16 0x40b8b8, // 18 0x50d0d0, // 1A 0x5ce8e8, // 1C 0x68fcfc, // 1E 0x002870, // 20 0x144484, // 22 0x285c98, // 24 0x3c78ac, // 26 0x4c8cbc, // 28 0x5ca0cc, // 2A 0x68b4dc, // 2C 0x78c8ec, // 2E 0x001884, // 30 0x183498, // 32 0x3050ac, // 34 0x4868c0, // 36 0x5c80d0, // 38 0x7094e0, // 3A 0x80a8ec, // 3C 0x94bcfc, // 3E 0x000088, // 40 0x20209c, // 42 0x3c3cb0, // 44 0x5858c0, // 46 0x7070d0, // 48 0x8888e0, // 4A 0xa0a0ec, // 4C 0xb4b4fc, // 4E 0x5c0078, // 50 0x74208c, // 52 0x883ca0, // 54 0x9c58b0, // 56 0xb070c0, // 58 0xc084d0, // 5A 0xd09cdc, // 5C 0xe0b0ec, // 5E 0x780048, // 60 0x902060, // 62 0xa43c78, // 64 0xb8588c, // 66 0xcc70a0, // 68 0xdc84b4, // 6A 0xec9cc4, // 6C 0xfcb0d4, // 6E 0x840014, // 70 0x982030, // 72 0xac3c4c, // 74 0xc05868, // 76 0xd0707c, // 78 0xe08894, // 7A 0xeca0a8, // 7C 0xfcb4bc, // 7E 0x880000, // 80 0x9c201c, // 82 0xb04038, // 84 0xc05c50, // 86 0xd07468, // 88 0xe08c7c, // 8A 0xeca490, // 8C 0xfcb8a4, // 8E 0x7c1800, // 90 0x90381c, // 92 0xa85438, // 94 0xbc7050, // 96 0xcc8868, // 98 0xdc9c7c, // 9A 0xecb490, // 9C 0xfcc8a4, // 9E 0x5c2c00, // A0 0x784c1c, // A2 0x906838, // A4 0xac8450, // A6 0xc09c68, // A8 0xd4b47c, // AA 0xe8cc90, // AC 0xfce0a4, // AE 0x2c3c00, // B0 0x485c1c, // B2 0x647c38, // B4 0x809c50, // B6 0x94b468, // B8 0xacd07c, // BA 0xc0e490, // BC 0xd4fca4, // BE 0x003c00, // C0 0x205c20, // C2 0x407c40, // C4 0x5c9c5c, // C6 0x74b474, // C8 0x8cd08c, // CA 0xa4e4a4, // CC 0xb8fcb8, // CE 0x003814, // D0 0x1c5c34, // D2 0x387c50, // D4 0x50986c, // D6 0x68b484, // D8 0x7ccc9c, // DA 0x90e4b4, // DC 0xa4fcc8, // DE 0x00302c, // E0 0x1c504c, // E2 0x347068, // E4 0x4c8c84, // E6 0x64a89c, // E8 0x78c0b4, // EA 0x88d4cc, // EC 0x9cece0, // EE 0x002844, // F0 0x184864, // F2 0x306884, // F4 0x4484a0, // F6 0x589cb8, // F8 0x6cb4d0, // FA 0x7ccce8, // FC 0x8ce0fc // FE ]; var palRGB = [ 0x000000, // 00 0x282828, // 02 0x505050, // 04 0x747474, // 06 0x949494, // 08 0xb4b4b4, // 0A 0xd0d0d0, // 0C 0xf1f1f1, // 0E 0x000000, // 10 0x282828, // 12 0x505050, // 14 0x747474, // 16 0x949494, // 18 0xb4b4b4, // 1A 0xd0d0d0, // 1C 0xf1f1f1, // 1E 0x005880, // 20 0x207094, // 22 0x3c84a8, // 24 0x589cbc, // 26 0x70accc, // 28 0x84c0dc, // 2A 0x9cd0ec, // 2C 0xb0e0fc, // 2E 0x005c44, // 30 0x20785c, // 32 0x3c9074, // 34 0x58ac8c, // 36 0x70c0a0, // 38 0x84d4b0, // 3A 0x9ce8c4, // 3C 0xb0fcd4, // 3E 0x003470, // 40 0x205088, // 42 0x3C68A0, // 44 0x5884B4, // 46 0x7098C8, // 48 0x84ACDC, // 4A 0x9CC0EC, // 4C 0xB0D4FC, // 4E 0x146400, // 50 0x348020, // 52 0x50983C, // 54 0x6CB058, // 56 0x84C470, // 58 0x9CD884, // 5A 0xB4E89C, // 5C 0xC8FCB0, // 5E 0x140070, // 60 0x342088, // 62 0x503CA0, // 64 0x6C58B4, // 66 0x8470C8, // 68 0x9C84DC, // 6A 0xB49CEC, // 6C 0xC8B0FC, // 6E 0x5C5C00, // 70 0x747420, // 72 0x8C8C3C, // 74 0xA4A458, // 76 0xB8B870, // 78 0xC8C884, // 7A 0xDCDC9C, // 7C 0xECECB0, // 7E 0x5C0070, // 80 0x742084, // 82 0x883C94, // 84 0x9C58A8, // 86 0xB070B4, // 88 0xC084C4, // 8A 0xD09CD0, // 8C 0xE0B0E0, // 8E 0x703C00, // 90 0x88581C, // 92 0xA07438, // 94 0xB48C50, // 96 0xC8A468, // 98 0xDCB87C, // 9A 0xECCC90, // 9C 0xFCE0A4, // 9E 0x700058, // A0 0x88206C, // A2 0xA03C80, // A4 0xB45894, // A6 0xC870A4, // A8 0xDC84B4, // AA 0xEC9CC4, // AC 0xFCB0D4, // AE 0x702000, // B0 0x883C1C, // B2 0xA05838, // B4 0xB47450, // B6 0xC88868, // B8 0xDCA07C, // BA 0xECB490, // BC 0xFCC8A4, // BE 0x80003C, // C0 0x942054, // C2 0xA83C6C, // C4 0xBC5880, // C6 0xCC7094, // C8 0xDC84A8, // CA 0xEC9CB8, // CC 0xFCB0C8, // CE 0x880000, // D0 0x9C2020, // D2 0xB03C3C, // D4 0xC05858, // D6 0xD07070, // D8 0xE08484, // DA 0xEC9C9C, // DC 0xFCB0B0, // DE 0x000000, // E0 0x282828, // E2 0x505050, // E4 0x747474, // E6 0x949494, // E8 0xB4B4B4, // EA 0xD0D0D0, // EC 0xF1F1F1, // EE 0x000000, // F0 0x282828, // F2 0x505050, // F4 0x747474, // F6 0x949494, // F8 0xB4B4B4, // FA 0xD0D0D0, // FC 0xF1F1F1 // FE ]; var ntscPalette = new Uint32Array(256); var palPalette = new Uint32Array(256); for (var i = 0, len = ntscRGB.length; i < len; i++) { // Adds 100% alpha for ARGB use ntscPalette[i*2] = ntscPalette[i*2+1] = ntscRGB[i] + 0xff000000; palPalette[i*2] = palPalette[i*2+1] = palRGB[i] + 0xff000000; } // ntscPalette[0] = ntscPalette[1] = palPalette[0] = palPalette[1] = 0; // Full transparency for blacks. Needed for CRT emulation modes // Clean up ntscRGB = palRGB = undefined; jt.TiaPalettes = { NTSC: ntscPalette, PAL: palPalette }; })(); ================================================ FILE: src/main/atari/video/VideoSignal.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.VideoSignal = function() { "use strict"; this.connectMonitor = function(pMonitor) { this.monitor = pMonitor; }; this.setVideoStandard = function(standard) { if (this.monitor) this.monitor.setVideoStandard(standard); }; this.nextLine = function(pixels, vSynch) { return this.monitor.nextLine(pixels, vSynch); }; this.finishFrame = function() { this.monitor.refresh(); }; this.signalOff = function() { if (this.monitor) this.monitor.videoSignalOff(); }; this.showOSD = function(message, overlap, error) { if (this.monitor) this.monitor.showOSD(message, overlap, error); }; this.toggleShowInfo = function() { this.monitor.toggleShowInfo(); }; this.monitor = null; }; ================================================ FILE: src/main/atari/video/VideoStandard.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.VideoStandard = { NTSC: { name: "NTSC", desc: "NTSC 60Hz", totalWidth: 228, totalHeight: 262, defaultOriginYPct: 10.8, // Percentage of height defaultHeightPct: 85.2, targetFPS: 60, pulldowns: { 60: { // Host at 60Hz standard: "NTSC", frequency: 60, divider: 1, cadence: [ 1 ], steps: 1 }, 120: { // Host at 120Hz, clock / 2 standard: "NTSC", frequency: 120, divider: 2, cadence: [ 1 ], steps: 1 }, "120s": { // Host at 120Hz standard: "NTSC", frequency: 120, divider: 1, cadence: [ 0, 1 ], steps: 2 }, 50: { // Host at 50Hz standard: "NTSC", frequency: 50, divider: 1, cadence: [ 1, 1, 1, 1, 2 ], steps: 5 }, 100: { // Host at 100Hz, clock / 2 standard: "NTSC", frequency: 100, divider: 2, cadence: [ 1, 1, 1, 1, 2 ], steps: 5 }, "100s": { // Host at 100Hz standard: "NTSC", frequency: 100, divider: 1, cadence: [ 0, 1, 0, 1, 1, 0, 1, 0, 1, 1 ], steps: 10 }, TIMER: { // Host frequency not detected or V-synch disabled, use a normal interval timer standard: "NTSC", frequency: 62.5, divider: 1, cadence: [ 1 ], steps: 1 } } }, PAL: { name: "PAL", desc: "PAL 50Hz", totalWidth: 228, totalHeight: 312, defaultOriginYPct: 13.5, // Percentage of height defaultHeightPct: 77.3, targetFPS: 50, // Original is 50.22364217252396, or 50.3846153846153847 pulldowns: { 50: { // Host at 50Hz standard: "PAL", frequency: 50, divider: 1, cadence: [ 1 ], steps: 1 }, 100: { // Host at 100Hz, clock / 2 standard: "PAL", frequency: 100, divider: 2, cadence: [ 1 ], steps: 1 }, "100s": { // Host at 100Hz standard: "PAL", frequency: 100, divider: 1, cadence: [ 0, 1 ], steps: 2 }, 60: { // Host at 60Hz standard: "PAL", frequency: 60, divider: 1, cadence: [ 0, 1, 1, 1, 1, 1 ], steps: 6 }, 120: { // Host at 120Hz, clock / 2 standard: "PAL", frequency: 120, divider: 2, cadence: [ 0, 1, 1, 1, 1, 1 ], steps: 6 }, "120s": { // Host at 120Hz standard: "PAL", frequency: 120, divider: 1, cadence: [ 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1 ], steps: 12 }, TIMER: { // Host frequency not detected or V-synch disabled, use a normal interval timer standard: "PAL", frequency: 50, divider: 1, cadence: [ 1 ], steps: 1 } } } }; ================================================ FILE: src/main/images/Images.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Images = { embedded: false, count: 5, urls: { logo: Javatari.IMAGES_PATH + "logo.png", loading: Javatari.IMAGES_PATH + "loading.gif", mouseCursor: Javatari.IMAGES_PATH + "mouse-cursor.png", panel: Javatari.IMAGES_PATH + "panel.jpg", panelSprites: Javatari.IMAGES_PATH + "panel-sprites.jpg", controllers: Javatari.IMAGES_PATH + "controllers.jpg", iconSprites: Javatari.IMAGES_PATH + "icon-sprites.png" } }; ================================================ FILE: src/main/room/Room.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Room = function(screenElement, consoleStartPowerOn) { "use strict"; var self = this; function init() { buildMainClock(); buildPeripherals(); buildAndPlugConsole(); Javatari.userROMFormats.init(); } this.powerOn = function() { self.screen.powerOn(); self.speaker.powerOn(); self.consoleControls.powerOn(); self.setLoading(true); self.enterStandaloneMode(); roomPowerOnTime = Date.now(); }; this.powerOff = function() { self.console.powerOff(); self.consoleControls.powerOff(); self.speaker.powerOff(); self.screen.powerOff(); }; this.getNetServer = function() { if (!this.netServer) this.netServer = new jt.NetServer(this); return this.netServer; }; this.getNetClient = function() { if (!this.netClient) this.netClient = new jt.NetClient(this); return this.netClient; }; this.setLoading = function(boo) { if (this.isLoading === boo) return; this.isLoading = boo; this.console.setLoading(this.isLoading); this.screen.setLoading(this.isLoading); }; this.start = function(startAction) { this.mainVideoClock.detectHostNativeFPSAndCallback(function(nativeFPS) { self.console.vSynchSetSupported(nativeFPS > 0); afterPowerONDelay(function () { self.setLoading(false); self.screen.start(startAction || consolePowerOnStartAction); }); }); }; this.showOSD = function(message, overlap, error) { this.console.showOSD(message, overlap, error); }; this.mainVideoClockPulse = function() { if (self.console.isSystemPaused()) return; if (self.netController) self.netController.netVideoClockPulse(); else { self.console.getConsoleControlsSocket().controlsClockPulse(); self.console.videoClockPulse(); } }; this.enterStandaloneMode = function() { var oldMode = this.netPlayMode; this.netPlayMode = 0; this.netController = undefined; self.mainVideoClock.go(); // Local Clock // Restore state from before NetPlay if any if (this.netPlayStateBeforeClientMode) { this.console.loadState(this.netPlayStateBeforeClientMode); // extended this.consoleControls.setP1ControlsAndPaddleMode(this.netPlayControlsModeBeforeClientMode.p1, this.netPlayControlsModeBeforeClientMode.pd); this.netPlayStateBeforeClientMode = undefined; } if (oldMode !== this.netPlayMode) this.screen.roomNetPlayStatusChangeUpdate(oldMode); }; this.enterNetServerMode = function(netServer) { var oldMode = this.netPlayMode; this.netPlayMode = 1; this.netController = netServer; self.mainVideoClock.go(); // Local Clock, also sent to Client if (oldMode !== this.netPlayMode) this.screen.roomNetPlayStatusChangeUpdate(oldMode); }; this.enterNetClientMode = function(netClient) { var oldMode = this.netPlayMode; this.netPlayMode = 2; this.netController = netClient; self.mainVideoClock.pause(); // Clock comes from Server // Save state from before NetPlay, to be restored when session is over this.netPlayStateBeforeClientMode = this.console.saveState(true); // extended this.netPlayControlsModeBeforeClientMode = { p1: this.consoleControls.isP1ControlsMode(), pd: this.consoleControls.isPaddleMode() }; if (oldMode !== this.netPlayMode) this.screen.roomNetPlayStatusChangeUpdate(oldMode); }; this.enterNetPendingMode = function(netController) { var oldMode = this.netPlayMode; this.netPlayMode = netController === this.netServer ? -1 : -2; this.netController = undefined; self.mainVideoClock.go(); // Local Clock continued if (oldMode !== this.netPlayMode) this.screen.roomNetPlayStatusChangeUpdate(oldMode); }; function afterPowerONDelay(func) { var wait = Javatari.AUTO_POWER_ON_DELAY; if (wait >= 0 && JavatariFullScreenSetup.shouldStartInFullScreen()) wait += 1400; // Wait a bit more wait -= (Date.now() - roomPowerOnTime); if (wait < 1) wait = 1; setTimeout(func, wait); } function consolePowerOnStartAction() { if (!consoleStartPowerOn) return; if (self.console.getCartridgeSocket().inserted()) self.console.userPowerOn(); else if (Javatari.CARTRIDGE_SHOW_RECENT && !Javatari.CARTRIDGE_CHANGE_DISABLED) self.screen.openCartridgeChooserDialog(true); // Show even if no recent ROMs present } function buildMainClock() { // Clock frequency will be changed directly by the Console self.mainVideoClock = new jt.Clock(self.mainVideoClockPulse); } function buildPeripherals() { self.peripheralControls = new jt.DOMPeripheralControls(self); self.consoleControls = new jt.DOMConsoleControls(self, self.peripheralControls); self.fileDownloader = new jt.FileDownloader(); self.stateMedia = new jt.LocalStorageSaveStateMedia(self); self.recentROMs = new jt.RecentStoredROMs(); self.fileLoader = new jt.FileLoader(self, self.recentROMs, self.peripheralControls); self.speaker = new jt.WebAudioSpeaker(screenElement); self.screen = new jt.CanvasDisplay(self, screenElement); self.fileDownloader.connectPeripherals(self.screen); self.screen.connectPeripherals(self.recentROMs, self.fileLoader, self.fileDownloader, self.consoleControls, self.peripheralControls, self.stateMedia); self.speaker.connectPeripherals(self.screen); self.consoleControls.connectPeripherals(self.screen); self.stateMedia.connectPeripherals(self.fileDownloader); self.peripheralControls.connectPeripherals(self.screen, self.speaker, self.consoleControls, self.fileLoader); } function buildAndPlugConsole() { self.console = new jt.AtariConsole(); self.mainVideoClock.connect(self.console.getVideoClockSocket()); self.stateMedia.connect(self.console.getSavestateSocket()); self.fileLoader.connect(self.console); self.screen.connect(self.console); self.speaker.connect(self.console.getAudioSocket()); self.consoleControls.connect(self.console.getConsoleControlsSocket()); self.peripheralControls.connect(self.console.getCartridgeSocket()); self.console.socketsConnected(); } this.mainVideoClock = null; this.console = null; this.screen = null; this.speaker = null; this.consoleControls = null; this.fileDownloader = null; this.stateMedia = null; this.recentROMs = null; this.fileLoader = null; this.peripheralControls = null; this.netPlayMode = 0; // -1 = pending, 0 = standalone, 1 = server, 2 = client this.netController = undefined; this.netServer = undefined; this.netClient = undefined; this.netPlayStateBeforeClientMode = undefined; this.netPlayControlsModeBeforeClientMode = undefined; this.isLoading = false; var roomPowerOnTime; // Debug methods ------------------------------------------------------ this.runFramesAtTopSpeed = function(frames) { this.mainVideoClock.pause(); var start = jt.Util.performanceNow(); for (var i = 0; i < frames; i++) { //var pulseTime = jt.Util.performanceNow(); self.mainVideoClockPulse(); //console.log(jt.Util.performanceNow() - pulseTime); } var duration = jt.Util.performanceNow() - start; jt.Util.log("Done running " + frames + " frames in " + (duration | 0) + " ms"); jt.Util.log((frames / (duration/1000)).toFixed(2) + " frames/sec"); this.mainVideoClock.go(); }; init(); }; ================================================ FILE: src/main/room/clock/Clock.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Clock Pulse generator. Intended to be synchronized with Host machine Video Frequency whenever possible jt.Clock = function(clockPulse) { "use strict"; this.connect = function(clockSocket) { clockSocket.connectClock(this); }; this.go = function() { if (!running) { //lastPulseTime = jt.Util.performanceNow(); //timeMeasures = []; useRequestAnimationFrame = vSynch && (cyclesPerSecond === this.getVSynchNativeFrequency()); // console.log("Clock at " + cyclesPerSecond + " / " + divider + " using RequestAnimationFrame: " + useRequestAnimationFrame); running = true; if (useRequestAnimationFrame) animationFrame = requestAnimationFrame(pulse); else interval = setInterval(pulse, cycleTimeMs); } }; this.pause = function() { running = false; if (animationFrame) { cancelAnimationFrame(animationFrame); animationFrame = null; } if (interval) { clearInterval(interval); interval = null; } }; this.setFrequency = function(freq, div) { if (running) { this.pause(); internalSetFrequency(freq, div); this.go(); } else { internalSetFrequency(freq, div); } }; this.setVSynch = function(state) { if (running) { this.pause(); vSynch = state; this.go(); } else { vSynch = state; } }; this.getVSynchNativeFrequency = function() { return vSynchAltNativeFrequency || vSynchNativeFrequency; }; this.setVSynchAltNativeFrequency = function(freq) { vSynchAltNativeFrequency = freq; }; var internalSetFrequency = function(freq, div) { cyclesPerSecond = freq; cycleTimeMs = 1000 / freq; divider = div >= 1 ? div : 1; if (dividerCounter > divider) dividerCounter = divider; }; var pulse = function() { //var pulseTime = jt.Util.performanceNow(); //timeMeasures[timeMeasures.length] = pulseTime - lastPulseTime; //lastPulseTime = pulseTime; animationFrame = null; if (divider > 1) { if (--dividerCounter <= 0) { dividerCounter = divider; clockPulse(); } } else clockPulse(); if (useRequestAnimationFrame && !animationFrame) animationFrame = requestAnimationFrame(pulse); //console.log(jt.Util.performanceNow() - pulseTime); }; //this.getMeasures = function() { // return timeMeasures; //}; this.detectHostNativeFPSAndCallback = function(callback) { if (Javatari.SCREEN_VSYNCH_MODE === -1) { jt.Util.warning("Video native V-Synch disabled in configuration"); if (callback) callback(vSynchNativeFrequency); return; } if (Javatari.SCREEN_FORCE_HOST_NATIVE_FPS !== -1) { jt.Util.warning("Host video frequency forced in configuration: " + Javatari.SCREEN_FORCE_HOST_NATIVE_FPS); if (callback) callback(vSynchNativeFrequency); return; } // Start detection if (!window.requestAnimationFrame) return giveUp(); var tries = 0; // var samples = []; var lastTime = 0; var good60 = 0, good50 = 0, good120 = 0, good100 = 0; var tolerance = 0.06; var nativeFPSSampler = function() { // Detected? if (good60 >= 12 || good50 >= 18 || good120 >= 14 || good100 >= 18) { vSynchNativeFrequency = good60 >= 12 ? 60 : good50 >= 18 ? 50 : good120 >= 14 ? 120 : 100; jt.Util.log("Video native frequency detected: " + vSynchNativeFrequency + "Hz"); if (callback) callback(vSynchNativeFrequency); // console.log(samples); return; } tries++; if (tries <= 70) { var currentTime = jt.Util.performanceNow(); var sample = 1000 / (currentTime - lastTime); // samples[samples.length] = sample; lastTime = currentTime; if (sample >= 47 && sample <= 53) good50++; if (sample >= 56.4 && sample <= 63.6) good60++; if (sample >= 112.8 && sample <= 127.2) good120++; if (sample >= 94 && sample <= 106) good100++; requestAnimationFrame(nativeFPSSampler); } else return giveUp(); }; function giveUp() { vSynchNativeFrequency = -1; jt.Util.error("Could not detect video native frequency. V-Synch DISABLED!"); // console.log(samples); if (callback) callback(vSynchNativeFrequency); } nativeFPSSampler(); }; this.eval = function(str) { return eval(str); }; var running = false; var cyclesPerSecond = 1; var cycleTimeMs = 1000; var divider = 1; var dividerCounter = 1; var useRequestAnimationFrame; var animationFrame = null; var interval = null; var vSynch = true; var vSynchNativeFrequency = Javatari.SCREEN_VSYNCH_MODE === -1 ? -1 : Javatari.SCREEN_FORCE_HOST_NATIVE_FPS; // -1 = Unknown or not detected var vSynchAltNativeFrequency = undefined; // undefined = deactivated. Used by NetPlay to force the same frequency as the Server //var timeMeasures = []; //var lastPulseTime = 0; }; ================================================ FILE: src/main/room/controls/DOMConsoleControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.DOMConsoleControls = function(room, keyForwardControls) { "use strict"; var self = this; function init() { gamepadControls = new jt.GamepadConsoleControls(self); touchControls = new jt.DOMTouchControls(self); self.applyPreferences(); } this.connect = function(pControlsSocket) { consoleControlsSocket = pControlsSocket; consoleControlsSocket.connectControls(this); gamepadControls.connect(pControlsSocket); touchControls.connect(pControlsSocket); }; this.connectPeripherals = function(pScreen) { screen = pScreen; gamepadControls.connectScreen(pScreen); touchControls.connectScreen(pScreen); }; this.addKeyInputElement = function(element) { element.addEventListener("keydown", this.keyDown); element.addEventListener("keyup", this.keyUp); }; this.setupTouchControlsIfNeeded = function(mainElement) { touchControls.setupTouchControlsIfNeeded(mainElement) }; this.powerOn = function() { preventIEHelp(); gamepadControls.powerOn(); touchControls.powerOn(); if (PADDLES_MODE === 0) setPaddleMode(false, false); else if (PADDLES_MODE === 1) setPaddleMode(true, false); }; this.powerOff = function() { setPaddleMode(false, false); gamepadControls.powerOff(); touchControls.powerOff(); }; this.releaseControllers = function() { for (var c in keyStateMap) if (keyStateMap[c]) { processControlState(c, false); keyStateMap[c] = false; } paddle0MovingLeft = paddle0MovingRight = paddle1MovingLeft = paddle1MovingRight = false; turboControlState[cc.JOY0_BUTTON] = turboControlState[cc.JOY1_BUTTON] = false; touchControls.releaseControllers(); }; this.getTouchControls = function() { return touchControls; }; this.toggleP1ControlsMode = function() { this.setP1ControlsMode(!p1ControlsMode); showModeOSD(); fireModeStateUpdate(); }; this.setP1ControlsMode = function(state) { p1ControlsMode = state; gamepadControls.setP1ControlsMode(state); touchControls.setP1ControlsMode(state); this.releaseControllers(); initKeys(); }; this.isP1ControlsMode = function() { return p1ControlsMode; }; this.togglePaddleMode = function() { setPaddleMode(!paddleMode, true); fireModeStateUpdate(); }; this.isPaddleMode = function() { return paddleMode; }; this.setP1ControlsAndPaddleMode = function(p1, paddle) { this.setP1ControlsMode(p1); setPaddleMode(paddle, false); fireModeStateUpdate(); }; this.toggleGamepadMode = function() { gamepadControls.toggleMode(); fireModeStateUpdate(); }; this.getGamepadModeDesc = function() { return gamepadControls.getModeDesc(); }; this.toggleTouchControlsMode = function() { touchControls.toggleMode(); fireModeStateUpdate(); }; this.toggleTouchDirBig = function() { touchControls.toggleTouchDirBig(); }; this.toggleTurboFireSpeed = function() { setTurboFireSpeed((turboFireSpeed + 1) % 11); screen.showOSD("Turbo Fire" + (turboFireSpeed ? " speed: " + this.getTurboFireSpeedDesc() : ": OFF"), true); // Persist prefs.turboFireSpeed = turboFireSpeed; Javatari.userPreferences.setDirty(); Javatari.userPreferences.save(); }; function setTurboFireSpeed(speed) { turboFireSpeed = speed; turboFireClocks = turboFireSpeed ? (60 / turboFirePerSecond[turboFireSpeed]) | 0 : 0; turboFireFlipClock = (turboFireClocks / 2) | 0; turboFireClockCount = 0; } this.getTurboFireSpeedDesc = function() { return turboFireSpeed ? turboFireSpeed + "x" : "OFF"; }; this.getControlReport = function(control) { switch (control) { case jt.PeripheralControls.P1_CONTROLS_TOGGLE: return { label: p1ControlsMode ? "ON" : "OFF", active: p1ControlsMode }; case jt.PeripheralControls.PADDLES_TOGGLE_MODE: return { label: paddleMode ? "ON" : "OFF", active: paddleMode }; case jt.PeripheralControls.TOUCH_TOGGLE_DIR_BIG: return { label: touchControls.isDirBig() ? "ON" : "OFF", active: touchControls.isDirBig() }; case jt.PeripheralControls.HAPTIC_FEEDBACK_TOGGLE_MODE: return { label: hapticFeedbackEnabled ? "ON" : "OFF", active: !!hapticFeedbackEnabled }; case jt.PeripheralControls.TURBO_FIRE_TOGGLE: return { label: this.getTurboFireSpeedDesc(), active: !!turboFireSpeed }; } return { label: "Unknown", active: false }; }; this.consolePowerAndUserPauseStateUpdate = function(power, paused) { touchControls.consolePowerAndUserPauseStateUpdate(power, paused); }; this.keyDown = function(e) { return processKeyEvent(e, true); }; this.keyUp = function(e) { return processKeyEvent(e, false); }; this.controlsClockPulse = function() { // Turbo fire if (turboFireClocks) { --turboFireClockCount; // State flipped? if (turboFireClockCount === turboFireFlipClock || turboFireClockCount === 0) { var state = turboFireClockCount > 0; if (turboControlState[cc.JOY0_BUTTON]) processControlState(cc.JOY0_BUTTON, state); if (turboControlState[cc.JOY1_BUTTON]) processControlState(cc.JOY1_BUTTON, state); } if (turboFireClockCount <= 0) turboFireClockCount = turboFireClocks; // restart cycle } gamepadControls.controlsClockPulse(); // Update paddles position as time passes if (paddleMode) { if (paddle0MovingRight) { if (!paddle0MovingLeft) { paddle0Position -= paddle0Speed; if (paddle0Position < 0) paddle0Position = 0; processControlValue(cc.PADDLE0_POSITION, paddle0Position); } } else if (paddle0MovingLeft) { paddle0Position += paddle0Speed; if (paddle0Position > 380) paddle0Position = 380; processControlValue(cc.PADDLE0_POSITION, paddle0Position); } if (paddle1MovingRight) { if (!paddle1MovingLeft) { paddle1Position -= paddle1Speed; if (paddle1Position < 0) paddle1Position = 0; processControlValue(cc.PADDLE1_POSITION, paddle1Position); } } else if (paddle1MovingLeft) { paddle1Position += paddle1Speed; if (paddle1Position > 380) paddle1Position = 380; processControlValue(cc.PADDLE1_POSITION, paddle1Position); } } }; this.toggleHapticFeedback = function() { if (hapticFeedbackCapable) { hapticFeedbackEnabled = !hapticFeedbackEnabled; prefs.hapticFeedback = hapticFeedbackEnabled; Javatari.userPreferences.setDirty(); } else screen.showOSD("Haptic Feedback not available", true, true); }; this.hapticFeedback = function() { if (hapticFeedbackEnabled) navigator.vibrate(8); }; this.hapticFeedbackOnTouch = function(e) { if (hapticFeedbackEnabled && (e.type === "touchstart" || e.type === "touchend" || e.type === "touchmove")) navigator.vibrate(8); }; this.cartridgeInserted = function(cartridge) { if (!cartridge || PADDLES_MODE >= 0) return; // Does not interfere if Paddle Mode is forced var usePaddles = cartridge.rom.info.p === 1; if (paddleMode !== usePaddles) setPaddleMode(usePaddles, false); }; function processKeyEvent(e, press) { e.returnValue = false; // IE e.preventDefault(); e.stopPropagation(); var code = jt.DOMKeys.codeForKeyboardEvent(e); self.processKey(code, press); return false; } this.processKey = function(code, press) { // Check Turbo Fire buttons var control = turboKeyCodeMap[code]; if (control) { if (press === turboControlState[control]) return; if (press) turboFireClockCount = turboFireFlipClock; // Ensure correct timing for press/release cycle (TODO affects both controllers!) turboControlState[control] = press; } else { // Normal controls control = keyCodeMap[code]; if (!control) return keyForwardControls.processKey(code, press); // Next in chain if (press === keyStateMap[control]) return; keyStateMap[control] = press; } processControlState(control, press); }; this.applyPreferences = function() { initKeys(); setTurboFireSpeed(prefs.turboFireSpeed); touchControls.applyPreferences(); gamepadControls.applyPreferences(); }; function processControlState(control, press) { // Paddles first if (paddleMode) { control = translatePaddleModeButtons(control); if (tryPaddleControl(control, press)) return; } // Check for NetPlay blocked controls if (room.netPlayMode === 2 && netServerLocalOnlyControls.has(control)) return room.showOSD("Function not available in NetPlay Client mode", true, true); // Store changes to be sent to peers if (!(room.netPlayMode === 1 && netServerLocalOnlyControls.has(control))) netControlsToSend.push((control << 4) | press ); // binary encoded // Do not apply control now if Client if (room.netPlayMode === 2) return; applyControlState(control, press); } this.processControlState = processControlState; function applyControlState(control, press) { consoleControlsSocket.controlStateChanged(control, press); } function processControlValue(control, value) { // Store changes to be sent to peers netControlsToSend.push(control + (value + 10)); // always > 16000 // Do not apply control now if Client if (room.netPlayMode === 2) return; applyControlValue(control, value); } this.processControlValue = processControlValue; function applyControlValue(control, value) { consoleControlsSocket.controlValueChanged(control, value); } var preventIEHelp = function() { window.onhelp = function () { return false; }; }; var translatePaddleModeButtons = function(control) { switch (control) { case cc.JOY0_BUTTON: return cc.PADDLE0_BUTTON; case cc.JOY1_BUTTON: return cc.PADDLE1_BUTTON; default: return control; } }; var tryPaddleControl = function(control, press) { if (press) { switch(control) { case cc.JOY0_LEFT: paddle0MovingLeft = true; return true; case cc.JOY0_RIGHT: paddle0MovingRight = true; return true; case cc.JOY0_UP: if (paddle0Speed < 10) paddle0Speed++; screen.showOSD("P1 Paddle speed: " + paddle0Speed, true); return true; case cc.JOY0_DOWN: if (paddle0Speed > 1) paddle0Speed--; screen.showOSD("P1 Paddle speed: " + paddle0Speed, true); return true; case cc.JOY1_LEFT: paddle1MovingLeft = true; return true; case cc.JOY1_RIGHT: paddle1MovingRight = true; return true; case cc.JOY1_UP: if (paddle1Speed < 10) paddle1Speed++; screen.showOSD("P2 Paddle speed: " + paddle1Speed, true); return true; case cc.JOY1_DOWN: if (paddle1Speed > 1) paddle1Speed--; screen.showOSD("P2 Paddle speed: " + paddle1Speed, true); return true; } } else { switch(control) { case cc.JOY0_LEFT: paddle0MovingLeft = false; return true; case cc.JOY0_RIGHT: paddle0MovingRight = false; return true; case cc.JOY1_LEFT: paddle1MovingLeft = false; return true; case cc.JOY1_RIGHT: paddle1MovingRight = false; return true; } } return false; }; var setPaddleMode = function(mode, showOSD) { if (paddleMode !== mode) self.releaseControllers(); paddleMode = mode; paddle0Speed = paddle1Speed = 2; paddle0Position = paddle1Position = (paddleMode ? 190 : -1); // -1 = disconnected, won't charge POTs // Only send Paddles connection reset when not in NetPlay Client mode if (room.netPlayMode !== 2) { processControlValue(cc.PADDLE0_POSITION, paddle0Position); processControlValue(cc.PADDLE1_POSITION, paddle1Position); } gamepadControls.setPaddleMode(paddleMode); if (showOSD) showModeOSD(); }; var showModeOSD = function() { screen.showOSD("Controllers: " + (paddleMode ? "Paddles" : "Joysticks") + (p1ControlsMode ? ", Swapped" : ""), true); }; function fireModeStateUpdate() { screen.controlsModeStateUpdate(); } var initKeys = function() { var k = jt.DOMKeys; keyCodeMap = {}; keyStateMap = {}; turboKeyCodeMap = {}; // Fixed keys keyCodeMap[KEY_POWER] = cc.POWER; keyCodeMap[KEY_POWER | k.ALT] = cc.POWER; keyCodeMap[KEY_POWER | k.SHIFT] = cc.POWER_FRY; keyCodeMap[KEY_POWER | k.SHIFT | k.ALT] = cc.POWER_FRY; keyCodeMap[KEY_BW] = cc.BLACK_WHITE; keyCodeMap[KEY_BW | k.ALT] = cc.BLACK_WHITE; keyCodeMap[KEY_SELECT] = cc.SELECT; keyCodeMap[KEY_SELECT | k.ALT] = cc.SELECT; keyCodeMap[KEY_RESET] = cc.RESET; keyCodeMap[KEY_RESET | k.ALT] = cc.RESET; keyCodeMap[KEY_DIFF_0] = cc.DIFFICULTY0; keyCodeMap[KEY_DIFF_0 | k.ALT] = cc.DIFFICULTY0; keyCodeMap[KEY_DIFF_1] = cc.DIFFICULTY1; keyCodeMap[KEY_DIFF_1 | k.ALT] = cc.DIFFICULTY1; keyCodeMap[KEY_SPEED] = cc.FAST_SPEED; keyCodeMap[KEY_SPEED | k.ALT] = cc.FAST_SPEED; keyCodeMap[KEY_SPEED | k.SHIFT] = cc.SLOW_SPEED; keyCodeMap[KEY_SPEED | k.SHIFT | k.ALT] = cc.SLOW_SPEED; keyCodeMap[KEY_INC_SPEED | k.SHIFT | k.ALT] = cc.INC_SPEED; keyCodeMap[KEY_DEC_SPEED | k.SHIFT | k.ALT] = cc.DEC_SPEED; keyCodeMap[KEY_NORMAL_SPEED | k.SHIFT | k.ALT] = cc.NORMAL_SPEED; keyCodeMap[KEY_MIN_SPEED | k.SHIFT | k.ALT] = cc.MIN_SPEED; keyCodeMap[KEY_PAUSE | k.ALT] = cc.PAUSE; keyCodeMap[KEY_PAUSE | k.SHIFT | k.ALT] = cc.PAUSE_AUDIO_ON; keyCodeMap[KEY_FRAME | k.ALT] = cc.FRAME; keyCodeMap[KEY_FRAMEa | k.ALT] = cc.FRAME; keyCodeMap[KEY_TRACE | k.ALT] = cc.TRACE; keyCodeMap[KEY_INFO | k.ALT] = cc.SHOW_INFO; keyCodeMap[KEY_DEBUG | k.ALT] = cc.DEBUG; keyCodeMap[KEY_NO_COLLISIONS | k.ALT] = cc.NO_COLLISIONS; keyCodeMap[KEY_VIDEO_STANDARD | k.ALT] = cc.VIDEO_STANDARD; keyCodeMap[KEY_VIDEO_STANDARD2 | k.ALT] = cc.VIDEO_STANDARD; keyCodeMap[KEY_VSYNCH | k.ALT] = cc.VSYNCH; keyCodeMap[KEY_STATE_0 | k.CONTROL] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0a | k.CONTROL] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0 | k.CONTROL | k.ALT] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0a | k.CONTROL | k.ALT] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_1 | k.CONTROL] = cc.SAVE_STATE_1; keyCodeMap[KEY_STATE_1 | k.CONTROL | k.ALT] = cc.SAVE_STATE_1; keyCodeMap[KEY_STATE_2 | k.CONTROL] = cc.SAVE_STATE_2; keyCodeMap[KEY_STATE_2 | k.CONTROL | k.ALT] = cc.SAVE_STATE_2; keyCodeMap[KEY_STATE_3 | k.CONTROL] = cc.SAVE_STATE_3; keyCodeMap[KEY_STATE_3 | k.CONTROL | k.ALT] = cc.SAVE_STATE_3; keyCodeMap[KEY_STATE_4 | k.CONTROL] = cc.SAVE_STATE_4; keyCodeMap[KEY_STATE_4 | k.CONTROL | k.ALT] = cc.SAVE_STATE_4; keyCodeMap[KEY_STATE_5 | k.CONTROL] = cc.SAVE_STATE_5; keyCodeMap[KEY_STATE_5 | k.CONTROL | k.ALT] = cc.SAVE_STATE_5; keyCodeMap[KEY_STATE_6 | k.CONTROL] = cc.SAVE_STATE_6; keyCodeMap[KEY_STATE_6 | k.CONTROL | k.ALT] = cc.SAVE_STATE_6; keyCodeMap[KEY_STATE_7 | k.CONTROL] = cc.SAVE_STATE_7; keyCodeMap[KEY_STATE_7 | k.CONTROL | k.ALT] = cc.SAVE_STATE_7; keyCodeMap[KEY_STATE_8 | k.CONTROL] = cc.SAVE_STATE_8; keyCodeMap[KEY_STATE_8 | k.CONTROL | k.ALT] = cc.SAVE_STATE_8; keyCodeMap[KEY_STATE_9 | k.CONTROL] = cc.SAVE_STATE_9; keyCodeMap[KEY_STATE_9 | k.CONTROL | k.ALT] = cc.SAVE_STATE_9; keyCodeMap[KEY_STATE_10 | k.CONTROL] = cc.SAVE_STATE_10; keyCodeMap[KEY_STATE_10 | k.CONTROL | k.ALT] = cc.SAVE_STATE_10; keyCodeMap[KEY_STATE_11 | k.CONTROL] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11a | k.CONTROL] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11 | k.CONTROL | k.ALT] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11a | k.CONTROL | k.ALT] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_12 | k.CONTROL] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12a | k.CONTROL] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12 | k.CONTROL | k.ALT] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12a | k.CONTROL | k.ALT] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_0 | k.ALT] = cc.LOAD_STATE_0; keyCodeMap[KEY_STATE_0a | k.ALT] = cc.LOAD_STATE_0; keyCodeMap[KEY_STATE_1 | k.ALT] = cc.LOAD_STATE_1; keyCodeMap[KEY_STATE_2 | k.ALT] = cc.LOAD_STATE_2; keyCodeMap[KEY_STATE_3 | k.ALT] = cc.LOAD_STATE_3; keyCodeMap[KEY_STATE_4 | k.ALT] = cc.LOAD_STATE_4; keyCodeMap[KEY_STATE_5 | k.ALT] = cc.LOAD_STATE_5; keyCodeMap[KEY_STATE_6 | k.ALT] = cc.LOAD_STATE_6; keyCodeMap[KEY_STATE_7 | k.ALT] = cc.LOAD_STATE_7; keyCodeMap[KEY_STATE_8 | k.ALT] = cc.LOAD_STATE_8; keyCodeMap[KEY_STATE_9 | k.ALT] = cc.LOAD_STATE_9; keyCodeMap[KEY_STATE_10 | k.ALT] = cc.LOAD_STATE_10; keyCodeMap[KEY_STATE_11 | k.ALT] = cc.LOAD_STATE_11; keyCodeMap[KEY_STATE_11a | k.ALT] = cc.LOAD_STATE_11; keyCodeMap[KEY_STATE_12 | k.ALT] = cc.LOAD_STATE_12; keyCodeMap[KEY_STATE_12a | k.ALT] = cc.LOAD_STATE_12; // Alternate Savetates controls with SHIFT pressed keyCodeMap[KEY_STATE_0 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0a | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_0a | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_0; keyCodeMap[KEY_STATE_1 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_1; keyCodeMap[KEY_STATE_1 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_1; keyCodeMap[KEY_STATE_2 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_2; keyCodeMap[KEY_STATE_2 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_2; keyCodeMap[KEY_STATE_3 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_3; keyCodeMap[KEY_STATE_3 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_3; keyCodeMap[KEY_STATE_4 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_4; keyCodeMap[KEY_STATE_4 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_4; keyCodeMap[KEY_STATE_5 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_5; keyCodeMap[KEY_STATE_5 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_5; keyCodeMap[KEY_STATE_6 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_6; keyCodeMap[KEY_STATE_6 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_6; keyCodeMap[KEY_STATE_7 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_7; keyCodeMap[KEY_STATE_7 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_7; keyCodeMap[KEY_STATE_8 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_8; keyCodeMap[KEY_STATE_8 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_8; keyCodeMap[KEY_STATE_9 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_9; keyCodeMap[KEY_STATE_9 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_9; keyCodeMap[KEY_STATE_10 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_10; keyCodeMap[KEY_STATE_10 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_10; keyCodeMap[KEY_STATE_11 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11a | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_11a | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_11; keyCodeMap[KEY_STATE_12 | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12a | k.SHIFT | k.CONTROL] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12 | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_12a | k.SHIFT | k.CONTROL | k.ALT] = cc.SAVE_STATE_12; keyCodeMap[KEY_STATE_0 | k.SHIFT | k.ALT] = cc.LOAD_STATE_0; keyCodeMap[KEY_STATE_0a | k.SHIFT | k.ALT] = cc.LOAD_STATE_0; keyCodeMap[KEY_STATE_1 | k.SHIFT | k.ALT] = cc.LOAD_STATE_1; keyCodeMap[KEY_STATE_2 | k.SHIFT | k.ALT] = cc.LOAD_STATE_2; keyCodeMap[KEY_STATE_3 | k.SHIFT | k.ALT] = cc.LOAD_STATE_3; keyCodeMap[KEY_STATE_4 | k.SHIFT | k.ALT] = cc.LOAD_STATE_4; keyCodeMap[KEY_STATE_5 | k.SHIFT | k.ALT] = cc.LOAD_STATE_5; keyCodeMap[KEY_STATE_6 | k.SHIFT | k.ALT] = cc.LOAD_STATE_6; keyCodeMap[KEY_STATE_7 | k.SHIFT | k.ALT] = cc.LOAD_STATE_7; keyCodeMap[KEY_STATE_8 | k.SHIFT | k.ALT] = cc.LOAD_STATE_8; keyCodeMap[KEY_STATE_9 | k.SHIFT | k.ALT] = cc.LOAD_STATE_9; keyCodeMap[KEY_STATE_10 | k.SHIFT | k.ALT] = cc.LOAD_STATE_10; keyCodeMap[KEY_STATE_11 | k.SHIFT | k.ALT] = cc.LOAD_STATE_11; keyCodeMap[KEY_STATE_11a | k.SHIFT | k.ALT] = cc.LOAD_STATE_11; keyCodeMap[KEY_STATE_12 | k.SHIFT | k.ALT] = cc.LOAD_STATE_12; keyCodeMap[KEY_STATE_12a | k.SHIFT | k.ALT] = cc.LOAD_STATE_12; // Configurable in preferences var a = p1ControlsMode ? 1 : 0; var b = p1ControlsMode ? 0 : 1; keyCodeMap[prefs.joystickKeys[a].left.c] = cc.JOY0_LEFT; keyCodeMap[prefs.joystickKeys[a].up.c] = cc.JOY0_UP; keyCodeMap[prefs.joystickKeys[a].right.c] = cc.JOY0_RIGHT; keyCodeMap[prefs.joystickKeys[a].down.c] = cc.JOY0_DOWN; keyCodeMap[prefs.joystickKeys[a].button.c] = cc.JOY0_BUTTON; keyCodeMap[prefs.joystickKeys[b].left.c] = cc.JOY1_LEFT; keyCodeMap[prefs.joystickKeys[b].up.c] = cc.JOY1_UP; keyCodeMap[prefs.joystickKeys[b].right.c] = cc.JOY1_RIGHT; keyCodeMap[prefs.joystickKeys[b].down.c] = cc.JOY1_DOWN; keyCodeMap[prefs.joystickKeys[b].button.c] = cc.JOY1_BUTTON; turboKeyCodeMap[prefs.joystickKeys[a].buttonT.c] = cc.JOY0_BUTTON; turboKeyCodeMap[prefs.joystickKeys[b].buttonT.c] = cc.JOY1_BUTTON; }; // NetPlay ------------------------------------------- this.netGetControlsToSend = function() { return netControlsToSend.length ? netControlsToSend : undefined; }; this.netClearControlsToSend = function() { netControlsToSend.length = 0; }; this.netServerProcessControlsChanges = function(changes) { for (var i = 0, len = changes.length; i < len; ++i) { var change = changes[i]; if (change < 16000) { // Store changes to be sent to Clients? if (!netServerLocalOnlyControls.has(change >> 4)) netControlsToSend.push(change); applyControlState(change >> 4, change & 0x01); // binary encoded } else applyControlValue(change & ~0x3fff, (change & 0x3fff) - 10); } }; this.netClientApplyControlsChanges = function(changes) { for (var i = 0, len = changes.length; i < len; ++i) { var change = changes[i]; if (change < 16000) applyControlState(change >> 4, change & 0x01); // binary encoded else applyControlValue(change & ~0x3fff, (change & 0x3fff) - 10); } }; var cc = jt.ConsoleControls; var consoleControlsSocket; var screen; var keyCodeMap; var keyStateMap; var turboKeyCodeMap; var turboControlState = {}; var prefs = Javatari.userPreferences.current; var p1ControlsMode = false; var paddleMode = false; var hapticFeedbackCapable = !!navigator.vibrate; var hapticFeedbackEnabled = hapticFeedbackCapable && !!prefs.hapticFeedback; var turboFireSpeed = 0, turboFireClocks = 0, turboFireClockCount = 0, turboFireFlipClock = 0; var turboFirePerSecond = [ 0, 1, 2, 2.4, 3, 4, 5, 6, 7.5, 10, 12 ]; var paddle0Position = 0; // 380 = LEFT, 190 = MIDDLE, 0 = RIGHT var paddle0Speed = 3; // 1 to 10 var paddle0MovingLeft = false; var paddle0MovingRight = false; var paddle1Position = 0; var paddle1Speed = 3; var paddle1MovingLeft = false; var paddle1MovingRight = false; var gamepadControls; var touchControls; var netControlsToSend = new Array(100); netControlsToSend.length = 0; // pre allocate empty Array var PADDLES_MODE = Javatari.PADDLES_MODE; // Default Key Values var KEY_POWER = jt.DOMKeys.VK_F1.c; var KEY_BW = jt.DOMKeys.VK_F2.c; var KEY_SELECT = jt.DOMKeys.VK_F11.c; var KEY_RESET = jt.DOMKeys.VK_F12.c; var KEY_DIFF_0 = jt.DOMKeys.VK_F4.c; var KEY_DIFF_1 = jt.DOMKeys.VK_F9.c; var KEY_SPEED = jt.DOMKeys.VK_TAB.c; var KEY_INC_SPEED = jt.DOMKeys.VK_UP.c; var KEY_DEC_SPEED = jt.DOMKeys.VK_DOWN.c; var KEY_NORMAL_SPEED = jt.DOMKeys.VK_RIGHT.c; var KEY_MIN_SPEED = jt.DOMKeys.VK_LEFT.c; var KEY_PAUSE = jt.DOMKeys.VK_P.c; var KEY_FRAME = jt.DOMKeys.VK_O.c; var KEY_FRAMEa = jt.DOMKeys.VK_F.c; var KEY_DEBUG = jt.DOMKeys.VK_D.c; var KEY_TRACE = jt.DOMKeys.VK_VOID; var KEY_INFO = jt.DOMKeys.VK_I.c; var KEY_NO_COLLISIONS = jt.DOMKeys.VK_C.c; var KEY_VIDEO_STANDARD = jt.DOMKeys.VK_V.c; var KEY_VIDEO_STANDARD2 = jt.DOMKeys.VK_Q.c; var KEY_VSYNCH = jt.DOMKeys.VK_W.c; var KEY_STATE_0 = jt.DOMKeys.VK_QUOTE.c; var KEY_STATE_0a = jt.DOMKeys.VK_BACKQUOTE.c; var KEY_STATE_1 = jt.DOMKeys.VK_1.c; var KEY_STATE_2 = jt.DOMKeys.VK_2.c; var KEY_STATE_3 = jt.DOMKeys.VK_3.c; var KEY_STATE_4 = jt.DOMKeys.VK_4.c; var KEY_STATE_5 = jt.DOMKeys.VK_5.c; var KEY_STATE_6 = jt.DOMKeys.VK_6.c; var KEY_STATE_7 = jt.DOMKeys.VK_7.c; var KEY_STATE_8 = jt.DOMKeys.VK_8.c; var KEY_STATE_9 = jt.DOMKeys.VK_9.c; var KEY_STATE_10 = jt.DOMKeys.VK_0.c; var KEY_STATE_11 = jt.DOMKeys.VK_MINUS.c; var KEY_STATE_11a = jt.DOMKeys.VK_FF_MINUS.c; var KEY_STATE_12 = jt.DOMKeys.VK_EQUALS.c; var KEY_STATE_12a = jt.DOMKeys.VK_FF_EQUALS.c; var netServerLocalOnlyControls = new Set([ cc.SAVE_STATE_0, cc.SAVE_STATE_1, cc.SAVE_STATE_2, cc.SAVE_STATE_3, cc.SAVE_STATE_4, cc.SAVE_STATE_5, cc.SAVE_STATE_6, cc.SAVE_STATE_7, cc.SAVE_STATE_8, cc.SAVE_STATE_9, cc.SAVE_STATE_10, cc.SAVE_STATE_11, cc.SAVE_STATE_12, cc.SAVE_STATE_FILE, cc.LOAD_STATE_0, cc.LOAD_STATE_1, cc.LOAD_STATE_2, cc.LOAD_STATE_3, cc.LOAD_STATE_4, cc.LOAD_STATE_5, cc.LOAD_STATE_6, cc.LOAD_STATE_7, cc.LOAD_STATE_8, cc.LOAD_STATE_9, cc.LOAD_STATE_10, cc.LOAD_STATE_11, cc.LOAD_STATE_12, cc.POWER_FRY, cc.VSYNCH, cc.TRACE, cc.CARTRIDGE_FORMAT ]); init(); jt.DOMConsoleControls.hapticFeedback = this.hapticFeedback; jt.DOMConsoleControls.hapticFeedbackOnTouch = this.hapticFeedbackOnTouch; }; ================================================ FILE: src/main/room/controls/DOMKeys.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // General, immutable info about host keys on different browsers and keyboard languages/layouts jt.DOMKeys = {}; jt.DOMKeys.MOD_SHIFT = 16; jt.DOMKeys.LOC_SHIFT = 24; jt.DOMKeys.SHIFT = 0x10000; jt.DOMKeys.CONTROL = 0x20000; jt.DOMKeys.ALT = 0x40000; jt.DOMKeys.META = 0x80000; jt.DOMKeys.LOCNONE = 0x0000000; jt.DOMKeys.LOCLEFT = 0x1000000; jt.DOMKeys.LOCRIGHT = 0x2000000; jt.DOMKeys.LOCNUM = 0x3000000; jt.DOMKeys.IGNORE_ALL_MODIFIERS_MASK = ~(jt.DOMKeys.SHIFT | jt.DOMKeys.CONTROL | jt.DOMKeys.ALT | jt.DOMKeys.META); (function(k, left, right, num) { // Common keys (US) k.VK_F1 = {c: 112, n: "F1" }; k.VK_F2 = {c: 113, n: "F2" }; k.VK_F3 = {c: 114, n: "F3" }; k.VK_F4 = {c: 115, n: "F4" }; k.VK_F5 = {c: 116, n: "F5" }; k.VK_F6 = {c: 117, n: "F6" }; k.VK_F7 = {c: 118, n: "F7" }; k.VK_F8 = {c: 119, n: "F8" }; k.VK_F9 = {c: 120, n: "F9" }; k.VK_F10 = {c: 121, n: "F10" }; k.VK_F11 = {c: 122, n: "F11" }; k.VK_F12 = {c: 123, n: "F12" }; k.VK_1 = {c: 49, n: "1" }; k.VK_2 = {c: 50, n: "2" }; k.VK_3 = {c: 51, n: "3" }; k.VK_4 = {c: 52, n: "4" }; k.VK_5 = {c: 53, n: "5" }; k.VK_6 = {c: 54, n: "6" }; k.VK_7 = {c: 55, n: "7" }; k.VK_8 = {c: 56, n: "8" }; k.VK_9 = {c: 57, n: "9" }; k.VK_0 = {c: 48, n: "0" }; k.VK_Q = {c: 81, n: "Q" }; k.VK_W = {c: 87, n: "W" }; k.VK_E = {c: 69, n: "E" }; k.VK_R = {c: 82, n: "R" }; k.VK_T = {c: 84, n: "T" }; k.VK_Y = {c: 89, n: "Y" }; k.VK_U = {c: 85, n: "U" }; k.VK_I = {c: 73, n: "I" }; k.VK_O = {c: 79, n: "O" }; k.VK_P = {c: 80, n: "P" }; k.VK_A = {c: 65, n: "A" }; k.VK_S = {c: 83, n: "S" }; k.VK_D = {c: 68, n: "D" }; k.VK_F = {c: 70, n: "F" }; k.VK_G = {c: 71, n: "G" }; k.VK_H = {c: 72, n: "H" }; k.VK_J = {c: 74, n: "J" }; k.VK_K = {c: 75, n: "K" }; k.VK_L = {c: 76, n: "L" }; k.VK_Z = {c: 90, n: "Z" }; k.VK_X = {c: 88, n: "X" }; k.VK_C = {c: 67, n: "C" }; k.VK_V = {c: 86, n: "V" }; k.VK_B = {c: 66, n: "B" }; k.VK_N = {c: 78, n: "N" }; k.VK_M = {c: 77, n: "M" }; k.VK_ESCAPE = {c: 27, n: "Esc" }; k.VK_ENTER = {c: 13, n: "Enter" }; k.VK_SPACE = {c: 32, n: "Space" }; k.VK_TAB = {c: 9, n: "Tab" }; k.VK_BACKSPACE = {c: 8, n: "BackSpc" }; k.VK_CONTEXT = {c: 93, n: "Context" }; k.VK_LSHIFT = {c: 16 | left, n: "L-Shift" }; k.VK_LCONTROL = {c: 17 | left, n: "L-Control" }; k.VK_LALT = {c: 18 | left, n: "L-Alt" }; k.VK_LMETA = {c: 91 | left, n: "L-Meta" }; k.VK_RSHIFT = {c: 16 | right, n: "R-Shift" }; k.VK_RCONTROL = {c: 17 | right, n: "R-Control" }; k.VK_RALT = {c: 18 | right, n: "R-Alt" }; k.VK_RMETA = {c: 91 | right, n: "R-Meta" }; k.VK_CAPS_LOCK = {c: 20, n: "CapsLock" }; k.VK_PRINT_SCREEN = {c: 44, n: "PrtScr" }; k.VK_SCROLL_LOCK = {c: 145, n: "ScrLck" }; k.VK_PAUSE = {c: 19, n: "Pause" }; k.VK_BREAK = {c: 3, n: "Break" }; k.VK_INSERT = {c: 45, n: "Ins" }; k.VK_DELETE = {c: 46, n: "Del" }; k.VK_HOME = {c: 36, n: "Home" }; k.VK_END = {c: 35, n: "End" }; k.VK_PAGE_UP = {c: 33, n: "PgUp" }; k.VK_PAGE_DOWN = {c: 34, n: "PgDown" }; k.VK_NUM_INSERT = {c: 45 | num, n: "Num Ins" }; k.VK_NUM_DELETE = {c: 46 | num, n: "Num Del" }; k.VK_NUM_HOME = {c: 36 | num, n: "Num Home" }; k.VK_NUM_END = {c: 35 | num, n: "Num End" }; k.VK_NUM_PAGE_UP = {c: 33 | num, n: "Num PgUp" }; k.VK_NUM_PAGE_DOWN = {c: 34 | num, n: "Num PgDown" }; k.VK_UP = {c: 38, n: "Up" }; k.VK_DOWN = {c: 40, n: "Down" }; k.VK_LEFT = {c: 37, n: "Left" }; k.VK_RIGHT = {c: 39, n: "Right" }; k.VK_NUM_UP = {c: 38 | num, n: "Num Up" }; k.VK_NUM_DOWN = {c: 40 | num, n: "Num Down" }; k.VK_NUM_LEFT = {c: 37 | num, n: "Num Left" }; k.VK_NUM_RIGHT = {c: 39 | num, n: "Num Right" }; k.VK_NUMLOCK = {c: 144, n: "NumLock" }; k.VK_NUM_COMMA = {c: 110 | num, n: "Num ," }; k.VK_NUM_DIVIDE = {c: 111 | num, n: "Num /" }; k.VK_NUM_MULTIPLY = {c: 106 | num, n: "Num *" }; k.VK_NUM_MINUS = {c: 109 | num, n: "Num -" }; k.VK_NUM_PLUS = {c: 107 | num, n: "Num +" }; k.VK_NUM_PERIOD = {c: 194 | num, n: "Num ." }; k.VK_NUM_0 = {c: 96 | num, n: "Num 0" }; k.VK_NUM_1 = {c: 97 | num, n: "Num 1" }; k.VK_NUM_2 = {c: 98 | num, n: "Num 2" }; k.VK_NUM_3 = {c: 99 | num, n: "Num 3" }; k.VK_NUM_4 = {c: 100 | num, n: "Num 4" }; k.VK_NUM_5 = {c: 101 | num, n: "Num 5" }; k.VK_NUM_6 = {c: 102 | num, n: "Num 6" }; k.VK_NUM_7 = {c: 103 | num, n: "Num 7" }; k.VK_NUM_8 = {c: 104 | num, n: "Num 8" }; k.VK_NUM_9 = {c: 105 | num, n: "Num 9" }; k.VK_NUM_CLEAR = {c: 12 | num, n: "Num Clear" }; k.VK_NUM_ENTER = {c: 13 | num, n: "Num Enter" }; k.VK_QUOTE = {c: 222, n: "'" }; k.VK_BACKQUOTE = {c: 192, n: "`" }; k.VK_MINUS = {c: 189, n: "-" }; k.VK_EQUALS = {c: 187, n: "=" }; k.VK_OPEN_BRACKET = {c: 219, n: "[" }; k.VK_CLOSE_BRACKET = {c: 221, n: "]" }; k.VK_COMMA = {c: 188, n: "," }; k.VK_PERIOD = {c: 190, n: "." }; k.VK_SEMICOLON = {c: 186, n: ";" }; k.VK_SLASH = {c: 191, n: "/" }; k.VK_BACKSLASH = {c: 220, n: "\\" }; k.VK_ALTERNATE_ESC = { c: k.VK_F1.c | jt.DOMKeys.ALT, n: [ "Alt", "F1" ] }; // Alternate codes for FF k.VK_FF_MINUS = {c: 173, n: "-" }; k.VK_FF_EQUALS = {c: 61, n: "=" }; k.VK_FF_SEMICOLON = {c: 59, n: ";" }; // BR alternate codes k.VK_BR_QUOTE = {c: 192, n: "'" }; k.VK_BR_OPEN_BRACKET = {c: 221, n: "[" }; k.VK_BR_CLOSE_BRACKET = {c: 220, n: "]" }; k.VK_BR_SEMICOLON = {c: 191, n: ";" }; k.VK_BR_SLASH = {c: 193, n: "/" }; k.VK_BR_BACKSLASH = {c: 226, n: "\\" }; // BR additional keys k.VK_BR_CEDILLA = {c: 186, n: "Ç" }; k.VK_BR_TILDE = {c: 222, n: "~" }; k.VK_BR_ACUTE = {c: 219, n: "´" }; k.VK_FF_BR_TILDE = {c: 176, n: "~" }; //k.VK_FF_BR_CEDILLA = {c: 0, n: "Ç" }; k.VK_VOID = {c: -1, n: ""} })(jt.DOMKeys, jt.DOMKeys.LOCLEFT, jt.DOMKeys.LOCRIGHT, jt.DOMKeys.LOCNUM); jt.DOMKeys.forcedNames = { 27: "Esc", 13: "Enter", 32: "Space", 9: "Tab", 8: "BkSpc", 16: "Shift", 17: "Ctrl", 18: "Alt", 91: "Meta", 93: "Context", 20: "Caps", 44: "PrtScr", 145: "ScrLck", 19: "Pause", 3: "Break", 45: "Ins", 46: "Del", 36: "Home", 35: "End", 33: "PgUp", 34: "PgDown", 38: "Up", 40: "Down", 37: "Left", 39: "Right" }; jt.DOMKeys.isModifierKeyCode = function(keyCode) { return keyCode === 16 || keyCode === 17 || keyCode === 18 || keyCode === 91; }; jt.DOMKeys.codeForKeyboardEvent = function(e) { var code = e.keyCode; // Ignore modifiers for modifier keys SHIFT, CONTROL, ALT, META if (this.isModifierKeyCode(code)) return (code & this.IGNORE_ALL_MODIFIERS_MASK) | (e.location << this.LOC_SHIFT); return code | (e.location << this.LOC_SHIFT) | (e.shiftKey ? this.SHIFT : 0) | (e.ctrlKey ? this.CONTROL : 0) | (e.altKey ? this.ALT : 0) | (e.metaKey ? this.META : 0); }; jt.DOMKeys.nameForKeyboardEvent = function(e) { var keyCode = e.keyCode; var name = this.forcedNames[keyCode] || e.key; var nameUp = name && name.toUpperCase(); if (!nameUp || nameUp === "UNIDENTIFIED" || nameUp === "UNDEFINED" || nameUp === "UNKNOWN") name = "#" + keyCode; else if (nameUp === "DEAD") name = "Dead#" + keyCode; if (name.length === 1) name = name.toUpperCase(); // For normal letters else if (name.length > 12) name = name.substr(0, 12); // Limit size // Add location info switch(e.location) { case 1: name = "L-" + name; break; case 2: name = "R-" + name; break; case 3: name = "Num " + name; } if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey) { name = [ name ]; // Add modifiers info if (e.metaKey) name.unshift("Meta"); if (e.altKey) name.unshift("Alt"); if (e.ctrlKey) name.unshift("Ctrl"); if (e.shiftKey) name.unshift("Shift"); } return name; }; jt.DOMKeys.nameForKeyboardEventSingle = function(e) { var keyCode = e.keyCode; var name = this.forcedNames[keyCode] || e.key; var nameUp = name && name.toUpperCase(); if (!nameUp || nameUp === "UNIDENTIFIED" || nameUp === "UNDEFINED" || nameUp === "UNKNOWN") name = "#" + keyCode; else if (nameUp === "DEAD") name = "Dead#" + keyCode; if (name.length === 1) name = name.toUpperCase(); // For normal letters else if (name.length > 12) name = name.substr(0, 12); // Limit size // Add location info switch(e.location) { case 1: name = "L-" + name; break; case 2: name = "R-" + name; break; case 3: name = "Num " + name; } return name; }; ================================================ FILE: src/main/room/controls/DOMPeripheralControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.DOMPeripheralControls = function(room) { "use strict"; var self = this; function init() { initKeys(); } this.connect = function(pCartridgeSocket) { cartridgeSocket = pCartridgeSocket; }; this.connectPeripherals = function(pScreen, pSpeaker, pConsoleControls, pFileLoader) { screen = pScreen; speaker = pSpeaker; monitor = pScreen.getMonitor(); consoleControls = pConsoleControls; fileLoader = pFileLoader; }; this.getControlReport = function(control) { switch (control) { case pc.PADDLES_TOGGLE_MODE: case pc.P1_CONTROLS_TOGGLE: case pc.TURBO_FIRE_TOGGLE: case pc.TOUCH_TOGGLE_DIR_BIG: case pc.HAPTIC_FEEDBACK_TOGGLE_MODE: return consoleControls.getControlReport(control); case pc.SCREEN_CRT_FILTER: return screen.getControlReport(control); case pc.SPEAKER_BUFFER_TOGGLE: return speaker.getControlReport(control); } return { label: "Unknown", active: false }; }; this.processKey = function(code, press) { if (!press) return false; var control = keyCodeMap[code] || keyCodeMap[code & EXCLUDE_SHIFT_MASK]; if (!control) return false; self.controlActivated(control, !!(code & INCLUDE_SHIFT_MASK), false); // Never secPort return true; }; this.controlActivated = function(control, altPower, secPort) { // Never secPort // Check for NetPlay blocked controls if (room.netPlayMode === 2 && netClientDisabledControls.has(control)) return room.showOSD("Function not available in NetPlay Client mode", true, true); // All controls are Press-only and repeatable switch(control) { case pc.CONSOLE_POWER_TOGGLE: consoleControls.processControlState(jt.ConsoleControls.POWER, true); break; case pc.CONSOLE_POWER_FRY: consoleControls.processControlState(jt.ConsoleControls.POWER_FRY, true); break; case pc.CONSOLE_LOAD_STATE_FILE: fileLoader.openFileChooserDialog(OPEN_TYPE.STATE, false, false, false); break; case pc.CONSOLE_SAVE_STATE_FILE: consoleControls.processControlState(jt.ConsoleControls.SAVE_STATE_FILE, true); break; case pc.CONSOLE_LOAD_STATE_MENU: screen.openSaveStateDialog(false); break; case pc.CONSOLE_SAVE_STATE_MENU: screen.openSaveStateDialog(true); break; case pc.CARTRIDGE_LOAD_RECENT: if (!mediaChangeDisabledWarning()) screen.openCartridgeChooserDialog(false, altPower, secPort); break; case pc.CARTRIDGE_LOAD_FILE: if (!mediaChangeDisabledWarning()) fileLoader.openFileChooserDialog(OPEN_TYPE.ROM, altPower, secPort, false); break; case pc.CARTRIDGE_LOAD_URL: if (!mediaChangeDisabledWarning()) fileLoader.openURLChooserDialog(OPEN_TYPE.ROM, altPower, secPort); break; case pc.CARTRIDGE_REMOVE: if (!mediaChangeDisabledWarning()) cartridgeSocket.insert(null, false); break; case pc.CARTRIDGE_LOAD_DATA_FILE: //if (cartridgeSocket.dataOperationNotSupportedMessage(secPort ? 1 : 0, false, false)) break; //fileLoader.openFileChooserDialog(OPEN_TYPE.CART_DATA, altPower, secPort, false); break; case pc.CARTRIDGE_SAVE_DATA_FILE: //cartridgeSocket.saveCartridgeDataFile(secPort ? 1 : 0); break; case pc.CARTRIDGE_CHOOSE_FORMAT: if (!mediaChangeDisabledWarning()) screen.openCartridgeFormatDialog(altPower); break; case pc.AUTO_LOAD_FILE: if (!mediaChangeDisabledWarning()) fileLoader.openFileChooserDialog(OPEN_TYPE.AUTO, altPower, secPort, false); break; case pc.AUTO_LOAD_URL: if (!mediaChangeDisabledWarning()) fileLoader.openURLChooserDialog(OPEN_TYPE.AUTO, altPower, secPort, false); break; case pc.SCREEN_CRT_MODE: monitor.crtModeToggle(); break; case pc.SCREEN_CRT_FILTER: monitor.crtFilterToggle(); break; case pc.SCREEN_FULLSCREEN: monitor.fullscreenToggle(); break; case pc.SCREEN_DEFAULTS: consoleControls.processControlState(jt.ConsoleControls.DEFAULTS, true); monitor.setDefaults(); break; case pc.SCREEN_TOGGLE_MENU: screen.toggleMenuByKey(); break; case pc.SCREEN_OPEN_HELP: screen.openHelp(); break; case pc.SCREEN_OPEN_ABOUT: screen.openAbout(); break; case pc.SCREEN_OPEN_SETTINGS: if (altPower) return this.controlActivated(pc.SCREEN_DEFAULTS); screen.openSettings(); break; case pc.SCREEN_OPEN_QUICK_OPTIONS: screen.openQuickOptionsDialog(); break; case pc.SCREEN_CONSOLE_PANEL_TOGGLE: screen.toggleConsolePanel(); break; case pc.SCREEN_OPEN_NETPLAY: screen.openNetPlayDialog(); break; case pc.P1_CONTROLS_TOGGLE: consoleControls.toggleP1ControlsMode(); break; case pc.JOYSTICKS_TOGGLE_MODE: consoleControls.toggleGamepadMode(); break; case pc.PADDLES_TOGGLE_MODE: consoleControls.togglePaddleMode(); break; case pc.TOUCH_TOGGLE_MODE: consoleControls.toggleTouchControlsMode(); break; case pc.TOUCH_TOGGLE_DIR_BIG: consoleControls.toggleTouchDirBig(); break; case pc.TURBO_FIRE_TOGGLE: consoleControls.toggleTurboFireSpeed(); break; case pc.HAPTIC_FEEDBACK_TOGGLE_MODE: consoleControls.toggleHapticFeedback(); break; case pc.CAPTURE_SCREEN: screen.saveScreenCapture(); break; case pc.SPEAKER_BUFFER_TOGGLE: speaker.toggleBufferBaseSize(); break; case pc.VIEWPORT_ORIGIN_MINUS: monitor.viewportOriginDecrease(); break; case pc.VIEWPORT_ORIGIN_PLUS: monitor.viewportOriginIncrease(); break; } if (SCREEN_FIXED_SIZE) return; switch(control) { case pc.SCREEN_ASPECT_MINUS: monitor.displayAspectDecrease(); break; case pc.SCREEN_ASPECT_PLUS: monitor.displayAspectIncrease(); break; case pc.SCREEN_SCALE_MINUS: monitor.displayScaleDecrease(); break; case pc.SCREEN_SCALE_PLUS: monitor.displayScaleIncrease(); break; case pc.VIEWPORT_SIZE_MINUS: monitor.viewportSizeDecrease(); break; case pc.VIEWPORT_SIZE_PLUS: monitor.viewportSizeIncrease(); break; } }; var mediaChangeDisabledWarning = function() { if (Javatari.CARTRIDGE_CHANGE_DISABLED) { monitor.showOSD("Cartridge change is disabled!", true, true); return true; } if (room.netPlayMode === 2) { monitor.showOSD("Cartridge change is disabled in NetPlay Client mode!", true, true); return true; } return false; }; this.mediaChangeDisabledWarning = mediaChangeDisabledWarning; var initKeys = function() { var k = jt.DOMKeys; keyCodeMap[KEY_LOAD_RECENT] = pc.CARTRIDGE_LOAD_RECENT; keyCodeMap[KEY_LOAD_RECENT | k.ALT] = pc.CARTRIDGE_LOAD_RECENT; keyCodeMap[KEY_LOAD_URL] = pc.AUTO_LOAD_URL; keyCodeMap[KEY_LOAD_URL | k.ALT] = pc.AUTO_LOAD_URL; keyCodeMap[KEY_CART_REMOVE] = pc.CARTRIDGE_REMOVE; keyCodeMap[KEY_CART_REMOVE | k.ALT] = pc.CARTRIDGE_REMOVE; keyCodeMap[KEY_STATE_FILE] = pc.CONSOLE_SAVE_STATE_FILE; keyCodeMap[KEY_STATE_FILE | k.ALT] = pc.CONSOLE_SAVE_STATE_FILE; keyCodeMap[KEY_P1_CONTROLS_TOGGLE | k.ALT] = pc.P1_CONTROLS_TOGGLE; keyCodeMap[KEY_PADDLES_TOGGLE | k.ALT] = pc.PADDLES_TOGGLE_MODE; keyCodeMap[KEY_JOYSTICKS_TOGGLE | k.ALT] = pc.JOYSTICKS_TOGGLE_MODE; keyCodeMap[KEY_TOUCH_TOGGLE | k.ALT] = pc.TOUCH_TOGGLE_MODE; keyCodeMap[KEY_TURBO_FIRE_TOGGLE | k.ALT] = pc.TURBO_FIRE_TOGGLE; keyCodeMap[KEY_CRT_FILTER | k.ALT] = pc.SCREEN_CRT_FILTER; keyCodeMap[KEY_CRT_MODE | k.ALT] = pc.SCREEN_CRT_MODE; keyCodeMap[KEY_SETTINGS | k.ALT] = pc.SCREEN_OPEN_SETTINGS; keyCodeMap[KEY_QUICK_OPTIONS | k.ALT] = pc.SCREEN_OPEN_QUICK_OPTIONS; keyCodeMap[KEY_CONSOLE_PANEL | k.ALT] = pc.SCREEN_CONSOLE_PANEL_TOGGLE; keyCodeMap[KEY_FULLSCREEN | k.ALT] = pc.SCREEN_FULLSCREEN; keyCodeMap[KEY_UP | k.CONTROL | k.ALT] = pc.SCREEN_SCALE_MINUS; keyCodeMap[KEY_DOWN | k.CONTROL | k.ALT] = pc.SCREEN_SCALE_PLUS; keyCodeMap[KEY_LEFT | k.CONTROL | k.ALT] = pc.SCREEN_ASPECT_MINUS; keyCodeMap[KEY_RIGHT | k.CONTROL | k.ALT] = pc.SCREEN_ASPECT_PLUS; keyCodeMap[KEY_UP | k.SHIFT | k.CONTROL] = pc.VIEWPORT_ORIGIN_MINUS; keyCodeMap[KEY_DOWN | k.SHIFT | k.CONTROL] = pc.VIEWPORT_ORIGIN_PLUS; keyCodeMap[KEY_LEFT | k.SHIFT | k.CONTROL] = pc.VIEWPORT_SIZE_MINUS; keyCodeMap[KEY_RIGHT | k.SHIFT | k.CONTROL] = pc.VIEWPORT_SIZE_PLUS; keyCodeMap[KEY_MENU] = pc.SCREEN_TOGGLE_MENU; keyCodeMap[KEY_DEFAULTS] = pc.SCREEN_DEFAULTS; keyCodeMap[KEY_DEFAULTS | k.ALT] = pc.SCREEN_DEFAULTS; keyCodeMap[KEY_CAPTURE_SCREEN | k.ALT] = pc.CAPTURE_SCREEN; keyCodeMap[KEY_SPEAKER_BUFFER | k.ALT] = pc.SPEAKER_BUFFER_TOGGLE; }; var pc = jt.PeripheralControls; var screen; var monitor; var speaker; var consoleControls; var fileLoader; var cartridgeSocket; var keyCodeMap = {}; // SHIFT is considered differently var EXCLUDE_SHIFT_MASK = ~jt.DOMKeys.SHIFT; var INCLUDE_SHIFT_MASK = jt.DOMKeys.SHIFT; var OPEN_TYPE = jt.FileLoader.OPEN_TYPE; var KEY_LEFT = jt.DOMKeys.VK_LEFT.c; var KEY_UP = jt.DOMKeys.VK_UP.c; var KEY_RIGHT = jt.DOMKeys.VK_RIGHT.c; var KEY_DOWN = jt.DOMKeys.VK_DOWN.c; var KEY_MENU = jt.DOMKeys.VK_CONTEXT.c; var KEY_DEFAULTS = jt.DOMKeys.VK_BACKSPACE.c; var KEY_CAPTURE_SCREEN = jt.DOMKeys.VK_G.c; var KEY_SPEAKER_BUFFER = jt.DOMKeys.VK_A.c; var KEY_LOAD_RECENT = jt.DOMKeys.VK_F5.c; var KEY_LOAD_URL = jt.DOMKeys.VK_F6.c; var KEY_CART_REMOVE = jt.DOMKeys.VK_F7.c; var KEY_P1_CONTROLS_TOGGLE = jt.DOMKeys.VK_K.c; var KEY_JOYSTICKS_TOGGLE = jt.DOMKeys.VK_J.c; var KEY_PADDLES_TOGGLE = jt.DOMKeys.VK_L.c; var KEY_TOUCH_TOGGLE = jt.DOMKeys.VK_N.c; var KEY_TURBO_FIRE_TOGGLE = jt.DOMKeys.VK_H.c; var KEY_CRT_MODE = jt.DOMKeys.VK_R.c; var KEY_CRT_FILTER = jt.DOMKeys.VK_T.c; var KEY_SETTINGS = jt.DOMKeys.VK_Y.c; var KEY_QUICK_OPTIONS = jt.DOMKeys.VK_U.c; var KEY_CONSOLE_PANEL = jt.DOMKeys.VK_S.c; var KEY_FULLSCREEN = jt.DOMKeys.VK_ENTER.c; var KEY_MACHINE_POWER = jt.DOMKeys.VK_F1.c; var KEY_STATE_FILE = jt.DOMKeys.VK_F8.c; var SCREEN_FIXED_SIZE = Javatari.SCREEN_RESIZE_DISABLED; var netClientDisabledControls = new Set([ pc.CONSOLE_POWER_FRY, pc.CONSOLE_LOAD_STATE_FILE, pc.CONSOLE_SAVE_STATE_FILE, pc.CONSOLE_LOAD_STATE_MENU, pc.CONSOLE_SAVE_STATE_MENU, pc.CARTRIDGE_LOAD_RECENT, pc.CARTRIDGE_LOAD_FILE, pc.CARTRIDGE_LOAD_URL, pc.CARTRIDGE_REMOVE, pc.CARTRIDGE_LOAD_DATA_FILE, pc.CARTRIDGE_SAVE_DATA_FILE, pc.AUTO_LOAD_FILE, pc.AUTO_LOAD_URL ]); init(); }; ================================================ FILE: src/main/room/controls/DOMTouchControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.DOMTouchControls = function(consoleControls) { "use strict"; var self = this; this.connect = function(pConsoleControlsSocket) { consoleControlsSocket = pConsoleControlsSocket; }; this.connectScreen = function(pScreen) { screen = pScreen; }; this.powerOn = function() { this.applyPreferences(); resetStates(); updateVisuals(); }; this.powerOff = function() { }; this.releaseControllers = function() { resetStates(); }; this.updateConsolePanelSize = function(screenWidth, width, height, isFullscreen, isLandscape) { if (!speedControls || !isFullscreen) return; var center = !isLandscape && ((screenWidth - width - 10) / 2) < SPEED_CONTROLS_WIDTH; speedControls.classList.toggle("jt-center", center); if (center) speedControls.style.bottom = "" + (jt.ScreenGUI.BAR_HEIGHT + height + 3) + "px"; else speedControls.style.removeProperty("bottom"); }; this.toggleMode = function() { if (!isTouchDevice) { screen.showOSD("Touch Controls unavailable. Not a touch device!", true, true); return; } mode++; if (mode > 2) mode = 0; // AUTO mode not selectable resetStates(); this.applyPreferences(); updateVisuals(); screen.showOSD("Touch Controls " + this.getModeDesc(), true); }; this.setP1ControlsMode = function(state) { p1ControlsMode = state; this.applyPreferences(); }; this.getModeDesc = function() { switch (mode) { case -1: return "AUTO"; case 0: return "DISABLED"; case 1: return "ENABLED"; case 2: return "ENABLED (swapped)"; } }; this.toggleTouchDirBig = function() { dirBig = !dirBig; prefs.touch.directionalBig = dirBig; Javatari.userPreferences.setDirty(); updateVisuals(); }; this.isDirBig = function() { return dirBig; }; this.setupTouchControlsIfNeeded = function(mainElement) { if (dirElement || mode <= 0) return; speedControls = document.createElement('div'); speedControls.id = "jt-touch-speed"; var pause = document.createElement('div'); pause.id = "jt-touch-pause"; pause.addEventListener("touchstart", pauseTouchStart); pause.addEventListener("touchend", pauseTouchEnd); speedControls.appendChild(pause); var ff = document.createElement('div'); ff.id = "jt-touch-fast"; ff.addEventListener("touchstart", fastTouchStart); ff.addEventListener("touchend", fastTouchEnd); speedControls.appendChild(ff); mainElement.appendChild(speedControls); var group = document.createElement('div'); group.id = "jt-touch-left"; dirElement = createDirectional(); dirElement.addEventListener("touchstart", dirTouchStart); dirElement.addEventListener("touchmove", dirTouchMove); dirElement.addEventListener("touchend", dirTouchEnd); dirElement.addEventListener("touchcancel", dirTouchEnd); group.appendChild(dirElement); mainElement.appendChild(group); group = document.createElement('div'); group.id = "jt-touch-right"; createButton(group, "buttonT"); // Landscape top-down order createButton(group, "button"); mainElement.appendChild(group); updateSpeedControls(); function createDirectional() { var elem = document.createElement('div'); elem.classList.add("jt-touch-dir"); elem.classList.add("jt-touch-dir-joy"); createArrowKey("left"); createArrowKey("right"); createArrowKey("up"); createArrowKey("down"); return elem; function createArrowKey(dir) { var key = document.createElement('div'); key.classList.add("jt-touch-dir-" + dir); elem.appendChild(key); var arr = document.createElement('div'); arr.classList.add("jt-arrow-" + dir); elem.appendChild(arr); } } function createButton(group, name) { var but = document.createElement('div'); but.id = "jt-touch-" + name; but.classList.add("jt-touch-button"); but.classList.add("jt-touch-button-joy"); but.classList.add("jt-touch-button-joy-" + name); but.jtControl = name; but.addEventListener("touchstart", buttonTouchStart); but.addEventListener("touchmove", jt.Util.blockEvent); but.addEventListener("touchend", buttonTouchEnd); but.addEventListener("touchcancel", buttonTouchEnd); but.addEventListener("mousedown", buttonTouchStart); but.addEventListener("mouseup", buttonTouchEnd); buttonElements[name] = but; group.appendChild(but); } }; this.consolePowerAndUserPauseStateUpdate = function(power, paused) { consolePower = power; consolePaused = paused; if (speedControls) updateSpeedControls(); }; function updateSpeedControls() { speedControls.classList.toggle("jt-poweroff", !consolePower); speedControls.classList.toggle("jt-paused", consolePaused); } function updateVisuals() { var active = mode > 0; document.documentElement.classList.toggle("jt-touch-active", active); document.documentElement.classList.toggle("jt-dir-big", dirBig); screen.touchControlsActiveUpdate(active, dirBig); } function dirTouchStart(e) { jt.Util.blockEvent(e); if (dirTouchID !== null) return; if (dirTouchCenterX === undefined) setDirTouchCenter(); var touch = e.changedTouches[0]; dirTouchID = touch.identifier; updateDirMovement(touch.pageX, touch.pageY); } function dirTouchEnd(e) { jt.Util.blockEvent(e); if (dirTouchID !== null) { dirTouchID = null; setCurrentDirection(-1); } } function dirTouchMove(e) { jt.Util.blockEvent(e); if (dirTouchID === null) return; var changed = e.changedTouches; for (var i = 0; i < changed.length; ++i) { if (changed[i].identifier === dirTouchID) { updateDirMovement(changed[i].pageX, changed[i].pageY); return; } } } function updateDirMovement(newX, newY) { var dir = -1; var x = newX - dirTouchCenterX, y = newY - dirTouchCenterY; var dist = Math.sqrt(x*x + y*y); if (dist > dirDeadZone) { dir = (1 - Math.atan2(x, y) / Math.PI) / 2; dir += 1 / 16; if (dir >= 1) dir -= 1; dir = (dir * 8) | 0; } setCurrentDirection(dir); } function setCurrentDirection(newDir) { if (dirCurrentDir === newDir) return; if (newDir >= 0) consoleControls.hapticFeedback(); var newUp = false, newRight = false, newDown = false, newLeft = false; switch (newDir) { case 0: newUp = true; break; case 1: newUp = newRight = true; break; case 2: newRight = true; break; case 3: newDown = newRight = true; break; case 4: newDown = true; break; case 5: newDown = newLeft = true; break; case 6: newLeft = true; break; case 7: newUp = newLeft = true; break; } consoleControls.processKey(joyKeys.up.c, newUp); consoleControls.processKey(joyKeys.right.c, newRight); consoleControls.processKey(joyKeys.down.c, newDown); consoleControls.processKey(joyKeys.left.c, newLeft); dirCurrentDir = newDir; } function setDirTouchCenter() { var rec = dirElement.getBoundingClientRect(); dirDeadZone = ((rec.right - rec.left) * 0.14) | 0; // 14% deadzone each direction dirTouchCenterX = (((rec.left + rec.right) / 2) | 0) + window.pageXOffset; dirTouchCenterY = (((rec.top + rec.bottom) / 2) | 0) + window.pageYOffset; } function buttonTouchStart(e) { jt.Util.blockEvent(e); processButtonTouch(e.target.jtControl, true); } function buttonTouchEnd(e) { jt.Util.blockEvent(e); processButtonTouch(e.target.jtControl, false); } function processButtonTouch(control, press) { if (!control) return; if (press) consoleControls.hapticFeedback(); consoleControls.processKey(joyKeys[control].c, press); } function pauseTouchStart(e) { jt.Util.blockEvent(e); consoleControls.hapticFeedback(); consoleControls.processControlState(!consolePower ? jt.ConsoleControls.POWER : jt.ConsoleControls.PAUSE, true); } function pauseTouchEnd(e) { jt.Util.blockEvent(e); consoleControls.processControlState(!consolePower ? jt.ConsoleControls.POWER : jt.ConsoleControls.PAUSE, false); } function fastTouchStart(e) { jt.Util.blockEvent(e); consoleControls.processControlState(consolePaused ? jt.ConsoleControls.FRAME : jt.ConsoleControls.FAST_SPEED, true); } function fastTouchEnd(e) { jt.Util.blockEvent(e); consoleControls.processControlState(consolePaused ? jt.ConsoleControls.FRAME : jt.ConsoleControls.FAST_SPEED, false); } function resetStates() { joyState.reset(); dirTouchCenterX = dirTouchCenterY = undefined; dirTouchID = null; setCurrentDirection(-1); } this.applyPreferences = function() { dirBig = !!prefs.touch.directionalBig; var p = mode === 2 ? 1 : 0; joyKeys = prefs.joystickKeys[p]; }; var consoleControlsSocket; var screen; var isTouchDevice = jt.Util.isTouchDevice(); var isMobileDevice = jt.Util.isMobileDevice(); var mode = Javatari.TOUCH_MODE >= 0 ? Javatari.TOUCH_MODE : isTouchDevice && isMobileDevice ? 1 : 0; // -1: auto, 0: disabled, 1: enabled, 2: enabled (swapped) var p1ControlsMode = false; var dirBig = false; var dirElement = null, dirTouchID = null, dirTouchCenterX, dirTouchCenterY, dirCurrentDir = -1, dirDeadZone = 0; var buttonElements = { }; var speedControls; var joyKeys; var joyState = new JoystickState(); var consolePower = false, consolePaused = false; var prefs = Javatari.userPreferences.current; var SPEED_CONTROLS_WIDTH = 84; function JoystickState() { this.reset = function() { this.portValue = 0x3f; // All switches off }; this.reset(); } // Savestate ------------------------------------------- this.saveState = function() { return { }; }; this.loadState = function(s) { resetStates(); }; }; ================================================ FILE: src/main/room/controls/GamepadButtons.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // General, immutable info about host Gamepad Buttons jt.GamepadButtons = { GB_1: { b: 0, n: "1" }, GB_2: { b: 1, n: "2" }, GB_3: { b: 2, n: "3" }, GB_4: { b: 3, n: "4" }, GB_L1: { b: 4, n: "L1" }, GB_R1: { b: 5, n: "R1" }, GB_L2: { b: 6, n: "L2" }, GB_R2: { b: 7, n: "R2" }, GB_BACK: { b: 8, n: "BACK" }, GB_START: { b: 9, n: "START" }, GB_S1: { b: 10, n: "S1" }, GB_S2: { b: 11, n: "S2" }, GB_UP: { b: 12, n: "▲" }, GB_DOWN: { b: 13, n: "▼" }, GB_LEFT: { b: 14, n: "◄" }, GB_RIGHT: { b: 15, n: "►" }, GB_LOGO: { b: 16, n: "LOGO" }, GB_VOID: { b: -1, n: "Unbound" } }; ================================================ FILE: src/main/room/controls/GamepadConsoleControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.GamepadConsoleControls = function(consoleControls) { "use strict"; this.connect = function(pConsoleControlsSocket) { consoleControlsSocket = pConsoleControlsSocket; }; this.connectScreen = function(pScreen) { screen = pScreen; }; this.powerOn = function() { supported = !!navigator.getGamepads; if (!supported) return; this.applyPreferences(); resetStates(); }; this.powerOff = function() { supported = false; }; this.toggleMode = function() { if (!supported) { screen.showOSD("Joysticks unavailable (not supported by browser)", true, true); return; } ++mode; if (mode > 0) mode = -2; if (mode === -2) { joystick0 = joystick1 = null; } else if (mode === -1) { gamepadsDetectionDelay = 60; this.controlsClockPulse(); } swappedMode = mode === 0; this.applyPreferences(); resetStates(); screen.showOSD("Gamepads " + this.getModeDesc(), true); }; this.setPaddleMode = function(state) { if (!supported) return; paddleMode = state; joy0State.xPosition = joy1State.xPosition = -1; }; this.setP1ControlsMode = function(state) { p1ControlsMode = state; this.applyPreferences(); }; this.controlsClockPulse = function() { if (!supported || mode === -2) return; // Try to avoid polling at gamepads if none are present, as it may be expensive // Only try to detect connected gamepads once each 60 clocks (frames) if (++gamepadsDetectionDelay >= 60) gamepadsDetectionDelay = 0; if (!joystick0 && !joystick1 && gamepadsDetectionDelay !== 0) return; var gamepads = navigator.getGamepads(); // Just one poll per clock here then use it several times if (joystick0) { if (joystick0.update(gamepads)) { if (joystick0.hasMoved()) update(joystick0, joy0State, joy0Prefs, joy0Keys); } else { joystick0 = null; joystickConnectionMessage(true, false); } } else { if (gamepadsDetectionDelay === 0) { joystick0 = detectNewJoystick(joy0Prefs, joy1Prefs, gamepads); if (joystick0) joystickConnectionMessage(true, true); } } if (joystick1) { if (joystick1.update(gamepads)) { if (joystick1.hasMoved()) update(joystick1, joy1State, joy1Prefs, joy1Keys); } else { joystick1 = null; joystickConnectionMessage(false, false); } } else { if (gamepadsDetectionDelay === 0) { joystick1 = detectNewJoystick(joy1Prefs, joy0Prefs, gamepads); if (joystick1) joystickConnectionMessage(false, true); } } }; var joystickConnectionMessage = function (joy0, conn) { screen.showOSD((joy0 ^ p1ControlsMode ^ swappedMode ? "P1" : "P2") + " Gamepad " + (conn ? "connected" : "disconnected"), joy0); }; var detectNewJoystick = function(prefs, notPrefs, gamepads) { if (!gamepads || gamepads.length === 0) return; // Fixed index detection. Also allow the same gamepad to control both players var device = prefs.device; if (device >= 0) // pref.device == -1 means "auto" return gamepads[device] && gamepads[device].buttons.length > 0 ? new Joystick(device, prefs) : null; // Auto detection for (var i = 0, len = gamepads.length; i < len; i++) if (gamepads[i] && gamepads[i].buttons.length > 0) if (i !== notPrefs.device && (!joystick0 || joystick0.index !== i) && (!joystick1 || joystick1.index !== i)) // New Joystick found! return new Joystick(i, prefs); }; var resetStates = function() { joy0State = newControllerState(); joy1State = newControllerState(); }; var update = function (joystick, joyState, joyPrefs, joyKeys) { // Paddle Analog if (paddleMode && joyPrefs.paddleSens !== 0) { var newPosition = joystick.getPaddlePosition(); if (newPosition !== joyState.xPosition) { joyState.xPosition = newPosition; consoleControls.processControlValue(joyPrefs.player ? controls.PADDLE1_POSITION : controls.PADDLE0_POSITION, newPosition); } } // Joystick direction (Analog or POV) and Paddle Digital (Analog or POV) var newDirection = joystick.getDPadDirection(); if (newDirection === -1 && (!paddleMode || joyPrefs.paddleSens === 0)) newDirection = joystick.getStickDirection(); if (newDirection !== joyState.direction) { var newUp = false, newRight = false, newDown = false, newLeft = false; switch (newDirection) { case 0: newUp = true; break; case 1: newUp = newRight = true; break; case 2: newRight = true; break; case 3: newDown = newRight = true; break; case 4: newDown = true; break; case 5: newDown = newLeft = true; break; case 6: newLeft = true; break; case 7: newUp = newLeft = true; break; } consoleControls.processKey(joyKeys.up.c, newUp); consoleControls.processKey(joyKeys.right.c, newRight); consoleControls.processKey(joyKeys.down.c, newDown); consoleControls.processKey(joyKeys.left.c, newLeft); joyState.direction = newDirection; } // Joystick Normal Button var newButton = joystick.getButtonDigital(joyPrefs.button); if (newButton !== joyState.button) { consoleControls.processKey(joyKeys.button.c, newButton); joyState.button = newButton; } // Joystick Turbo Button newButton = joystick.getButtonDigital(joyPrefs.buttonT); if (newButton !== joyState.buttonT) { consoleControls.processKey(joyKeys.buttonT.c, newButton); joyState.buttonT = newButton; } // Other Console controls var newSelect = joystick.getButtonDigital(joyPrefs.select); if (newSelect !== joyState.select) { consoleControls.processControlState(controls.SELECT, newSelect); joyState.select = newSelect; } var newReset = joystick.getButtonDigital(joyPrefs.reset); if (newReset !== joyState.reset) { consoleControls.processControlState(controls.RESET, newReset); joyState.reset = newReset; } var newPause = joystick.getButtonDigital(joyPrefs.pause); if (newPause !== joyState.pause) { consoleControls.processControlState(controls.PAUSE, newPause); joyState.pause = newPause; } var newFastSpeed = joystick.getButtonDigital(joyPrefs.fastSpeed); if (newFastSpeed !== joyState.fastSpeed) { consoleControls.processControlState(controls.FAST_SPEED, newFastSpeed); joyState.fastSpeed = newFastSpeed; } var newSlowSpeed = joystick.getButtonDigital(joyPrefs.slowSpeed); if (newSlowSpeed !== joyState.slowSpeed) { consoleControls.processControlState(controls.SLOW_SPEED, newSlowSpeed); joyState.slowSpeed = newSlowSpeed; } }; var newControllerState = function() { return { direction: -1, // CENTER button: false, buttonT: false, select: false, reset: false, fastSpeed: false, pause: false, xPosition: -1 // PADDLE POSITION } }; this.getModeDesc = function() { switch (mode) { case -1: return "AUTO"; case 0: return "AUTO (swapped)"; default: return !supported ? "NOT SUPPORTED" : "DISABLED"; } }; this.applyPreferences = function() { var p0 = swappedMode ? 1 : 0; var p1 = p0 ? 0 : 1; joy0Prefs = prefs.joystickGamepads[p0]; joy0Prefs.player = p1ControlsMode ^ swappedMode? 1 : 0; joy1Prefs = prefs.joystickGamepads[p1]; joy1Prefs.player = p1ControlsMode ^ swappedMode ? 0 : 1; joy0Keys = prefs.joystickKeys[p0]; joy1Keys = prefs.joystickKeys[p1]; }; var supported = false; var gamepadsDetectionDelay = -1; var controls = jt.ConsoleControls; var consoleControlsSocket; var screen; var mode = -1; var paddleMode = false; var swappedMode = false; var p1ControlsMode = false; var joystick0; var joystick1; var joy0State; var joy1State; var joy0Prefs; var joy1Prefs; var joy0Keys; var joy1Keys; var joyButtonDetection = null; var prefs = Javatari.userPreferences.current; function Joystick(index, prefs) { this.index = index; this.update = function(gamepads) { gamepad = gamepads[index]; return !!gamepad; }; this.hasMoved = function() { var newTime = gamepad.timestamp; if (newTime) { if (newTime > lastTimestamp) { lastTimestamp = newTime; return true; } else return false; } else return true; // Always true if the timestamp property is not supported }; this.getButtonDigital = function(butIndex) { var b = gamepad.buttons[butIndex]; if (typeof(b) === "object") return b.pressed || b.value > 0.5; else return b > 0.5; }; this.getDPadDirection = function() { if (this.getButtonDigital(12)) { if (this.getButtonDigital(15)) return 1; // NORTHEAST else if (this.getButtonDigital(14)) return 7; // NORTHWEST else return 0; // NORTH } else if (this.getButtonDigital(13)) { if (this.getButtonDigital(15)) return 3; // SOUTHEAST else if (this.getButtonDigital(14)) return 5; // SOUTHWEST else return 4; // SOUTH } else if (this.getButtonDigital(14)) return 6; // WEST else if (this.getButtonDigital(15)) return 2; // EAST else return -1; // CENTER }; this.getStickDirection = function() { var x = gamepad.axes[xAxis]; var y = gamepad.axes[yAxis]; if ((x < 0 ? -x : x) < deadzone) x = 0; else x *= xAxisSig; if ((y < 0 ? -y : y) < deadzone) y = 0; else y *= yAxisSig; if (x === 0 && y === 0) return -1; var dir = (1 - Math.atan2(x, y) / Math.PI) / 2; dir += 1/16; if (dir >= 1) dir -= 1; return (dir * 8) | 0; }; this.getPaddlePosition = function() { var pos = (gamepad.axes[paddleAxis] * paddleAxisSig * paddleSens + paddleCenter) | 0; if (pos < 0) pos = 0; else if (pos > 380) pos = 380; return pos; }; var gamepad; var xAxis = prefs.xAxis; var yAxis = prefs.yAxis; var xAxisSig = prefs.xAxisSig; var yAxisSig = prefs.yAxisSig; var paddleAxis = prefs.paddleAxis; var paddleAxisSig = prefs.paddleAxisSig; var paddleSens = prefs.paddleSens * -190; var paddleCenter = prefs.paddleCenter * -190 + 190 - 5; var deadzone = prefs.deadzone; var lastTimestamp = Number.MIN_VALUE; } }; ================================================ FILE: src/main/room/controls/PeripheralControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.PeripheralControls = { SCREEN_ASPECT_PLUS: 1, SCREEN_ASPECT_MINUS: 2, SCREEN_SCALE_PLUS: 3, SCREEN_SCALE_MINUS: 4, VIEWPORT_ORIGIN_PLUS: 5, VIEWPORT_ORIGIN_MINUS: 6, VIEWPORT_SIZE_PLUS: 7, VIEWPORT_SIZE_MINUS: 8, SCREEN_FULLSCREEN: 10, SCREEN_CRT_FILTER: 11, SCREEN_CRT_MODE: 12, SCREEN_TOGGLE_MENU: 13, SCREEN_OPEN_HELP: 14, SCREEN_OPEN_ABOUT: 15, SCREEN_OPEN_SETTINGS: 16, SCREEN_OPEN_QUICK_OPTIONS: 17, SCREEN_DEFAULTS: 18, SCREEN_CONSOLE_PANEL_TOGGLE: 19, SPEAKER_BUFFER_TOGGLE: 20, CONSOLE_POWER_TOGGLE: 102, CONSOLE_POWER_FRY: 103, CONSOLE_LOAD_STATE_FILE: 104, CONSOLE_SAVE_STATE_FILE: 105, CONSOLE_LOAD_STATE_MENU: 106, CONSOLE_SAVE_STATE_MENU: 107, P1_CONTROLS_TOGGLE: 201, JOYSTICKS_TOGGLE_MODE: 202, PADDLES_TOGGLE_MODE: 203, TOUCH_TOGGLE_MODE: 204, TOUCH_TOGGLE_DIR_BIG: 205, TURBO_FIRE_TOGGLE: 206, HAPTIC_FEEDBACK_TOGGLE_MODE: 207, CAPTURE_SCREEN: 304, CARTRIDGE_LOAD_RECENT: 40, CARTRIDGE_LOAD_FILE: 41, CARTRIDGE_LOAD_URL: 42, CARTRIDGE_REMOVE: 43, CARTRIDGE_LOAD_DATA_FILE: 44, CARTRIDGE_SAVE_DATA_FILE: 45, CARTRIDGE_CHOOSE_FORMAT: 46, AUTO_LOAD_FILE: 47, AUTO_LOAD_URL: 48, SCREEN_OPEN_NETPLAY: 500 }; ================================================ FILE: src/main/room/controls/TouchControls.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // General, immutable info about host Touch Buttons jt.TouchControls = { buttons: [ "T_B", "T_A" ] // Specific order for vertical in-line placement on the screen }; ================================================ FILE: src/main/room/files/FileDownloader.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.FileDownloader = function() { "use strict"; this.connectPeripherals = function(pScreen) { screen = pScreen; }; this.registerForDownloadElement = function (element) { downloadLinkElementParent = element; }; this.startDownloadBinary = function (fileName, data, desc) { try { if (!saveType) setup(); if (checkNone()) return; var href; if (saveType === "BLOB") { // Release previous URL if (downloadLinkElement.href) (window.URL || window.webkitURL).revokeObjectURL(downloadLinkElement.href); var blob = new Blob([data], {type: "data:application/octet-stream"}); href = (window.URL || window.webkitURL).createObjectURL(blob); } else href = "data:application/octet-stream;base64," + btoa(typeof data === "string" ? data : jt.Util.int8BitArrayToByteString(data)); downloadLinkElement.download = fileName && fileName.trim(); downloadLinkElement.href = href; downloadLinkElement.click(); screen.showOSD(desc + " saved", true); } catch(ex) { screen.showOSD(desc + " save FAILED!", true, true); jt.Util.error(ex); } }; this.startDownloadURL = function (fileName, url, desc) { try { if (!saveType) setup(); if (checkNone()) return; if (saveType === "BLOB") // Release previous URL if (downloadLinkElement.href) (window.URL || window.webkitURL).revokeObjectURL(downloadLinkElement.href); downloadLinkElement.download = fileName && fileName.trim(); downloadLinkElement.href = url; downloadLinkElement.click(); screen.showOSD(desc + " saved", true); } catch(ex) { screen.showOSD(desc + " save FAILED!", true, true); jt.Util.error(ex); } }; function checkNone() { if (saveType === "NONE") { alert("Unfortunately file saving in WebApps is broken in this version of iOS. The file could not be saved. If you really need to save a file, you must run Javatari on the official homepage." ); return true; } } function setup() { saveType = jt.Util.isIOSDevice() ? jt.Util.isBrowserStandaloneMode() ? "NONE" : "DATA" : jt.Util.browserInfo().name === "SAFARI" ? "DATA" : "BLOB"; // No need to create link element if we won't use it if (saveType === "NONE") return; downloadLinkElement = document.createElement('a'); downloadLinkElement.style.display = "none"; downloadLinkElement.target = "_blank"; downloadLinkElement.href = "#"; downloadLinkElementParent.appendChild(downloadLinkElement); } var saveType; var downloadLinkElement; var downloadLinkElementParent; var screen; }; ================================================ FILE: src/main/room/files/FileLoader.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.FileLoader = function(room, recentStoredROMs, peripheralControls) { "use strict"; var self = this; this.connect = function(pConsole) { console = pConsole; cartridgeSocket = console.getCartridgeSocket(); saveStateSocket = console.getSavestateSocket(); }; this.registerForDnD = function (element) { element.addEventListener("dragover", onDragOver, false); element.addEventListener("drop", onDrop, false); }; this.registerForFileInputElement = function (element) { fileInputElementParent = element; }; this.openFileChooserDialog = function (openType, altPower, inSecondaryPort, asExpansion) { if (!fileInputElement) createFileInputElement(); fileInputElement.multiple = INPUT_MULTI[OPEN_TYPE[openType] || OPEN_TYPE.AUTO]; fileInputElement.accept = INPUT_ACCEPT[OPEN_TYPE[openType] || OPEN_TYPE.AUTO]; chooserOpenType = openType; chooserPort = inSecondaryPort ? 1 : 0; chooserAltPower = altPower; chooserAsExpansion = asExpansion; fileInputElement.click(); }; this.openURLChooserDialog = function (openType, altPower, inSecondaryPort, asExpansion) { var port = inSecondaryPort ? 1 : 0; var url; try { url = localStorage && localStorage[LOCAL_STORAGE_LAST_URL_KEY]; } catch (e) { // give up } var wasPaused = console.systemPause(true); url = prompt("Load file from URL:", url || ""); url = url && url.toString().trim(); if (url) { try { localStorage[LOCAL_STORAGE_LAST_URL_KEY] = url; } catch (e) { // give up } this.readFromURL(url, openType, port, altPower, asExpansion, function () { if (!wasPaused) console.systemPause(false); }); } else { if (!wasPaused) console.systemPause(false); } }; this.readFromFile = function (file, openType, port, altPower, asExpansion, then) { // Auto detects type jt.Util.log("Reading file: " + file.name); var reader = new FileReader(); reader.onload = function (event) { var content = new Uint8Array(event.target.result); var aFile = { name: file.name, content: content, lastModifiedDate: file.lastModified ? new Date(file.lastModified) : file.lastModifiedDate }; // lastModifiedDate deprecated? self.loadFromFile(aFile, openType, port, altPower, asExpansion); if (then) then(true); }; reader.onerror = function (event) { showError("File reading error: " + event.target.error.name + DIR_NOT_SUPPORTED_HINT); // Directories not supported if (then) then(false); }; reader.readAsArrayBuffer(file); }; this.readFromURL = function (url, openType, port, altPower, asExpansion, then) { new jt.MultiDownloader( [{ url: url }], function onAllSuccess(urls) { var aFile = { name: url, content: urls[0].content, lastModifiedDate: null }; self.loadFromFile(aFile, openType, port, altPower, asExpansion); if (then) then(true); }, function onAnyError(urls) { showError("URL reading error: " + urls[0].error); if (then) then(false); } ).start(); }; this.readFromFiles = function (files, openType, port, altPower, asExpansion, then) { var reader = new jt.MultiFileReader(files, function onSuccessAll(files) { self.loadFromFiles(files, openType, port, altPower, asExpansion); if (then) then(true); }, function onFirstError(files, error, known) { if (!known) error += DIR_NOT_SUPPORTED_HINT; // Directories not supported showError("File reading error: " + error); if (then) then(false); } ); reader.start(); }; this.loadFromContent = function(name, content, openType, port, altPower, asExpansion, format) { return this.loadFromFile({ name: name, content: content }, openType, port, altPower, asExpansion, format); }; this.loadFromFile = function(file, openType, port, altPower, asExpansion, format) { var zip, mes; zip = jt.Util.checkContentIsZIP(file.content); if (zip) { try { // Try normal loading from files var files = jt.Util.getZIPFilesSorted(zip); if (tryLoadFilesAsMedia(files, openType, port, altPower, asExpansion, format, true)) return; } catch(ez) { jt.Util.error(ez); // Error decompressing files. Abort } } else { // Try normal loading from files if (tryLoadFilesAsMedia([file], openType, port, altPower, asExpansion, format, false)) return; } showError("No valid " + TYPE_DESC[openType] + " found.") }; this.loadFromFiles = function(files, openType, port, altPower, asExpansion) { // Sort files by name files = jt.Util.asNormalArray(files).slice(0); files.sort(function sortFiles(a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; }); if (tryLoadFilesAsMedia(files, openType, port, altPower, asExpansion, null, false)) return; showError("No valid " + TYPE_DESC[openType] + " found.") }; this.loadROM = function(rom, port, altPower, chooserAsExpansion) { var cart = jt.CartridgeCreator.createCartridgeFromRom(rom); if (!cart) return false; cartridgeSocket.insert(cart, !altPower); recentStoredROMs.storeROM(rom); return true; }; function tryLoadFilesAsMedia(files, openType, port, altPower, asExpansion, format, filesFromZIP) { // Try as Single media (first found) for (var i = 0; i < files.length; i++) if (tryLoadFileAsSingleMedia(files[i], openType, port, altPower, asExpansion, format, filesFromZIP)) return true; return false; } function tryLoadFileAsSingleMedia(file, openType, port, altPower, asExpansion, format, fileFromZIP, stopRecursion) { try { if (fileFromZIP && !file.content) file.content = file.asUint8Array(); var content = file.content; if (!stopRecursion) { var zip = jt.Util.checkContentIsZIP(content); if (zip) { var files = jt.Util.getZIPFilesSorted(zip); for (var i = 0; i < files.length; i++) if (tryLoadFileAsSingleMedia(files[i], openType, port, altPower, asExpansion, format, true, true)) return true; return false; } } var gzip = jt.Util.checkContentIsGZIP(content); if (gzip) return tryLoadFileAsSingleMedia({ name: file.name, content: gzip }, openType, port, altPower, asExpansion, format, false, true); } catch (ez) { jt.Util.error(ez); // Error decompressing files. Abort return false; } return tryLoadContentAsSingleMedia(file.name, content, openType, port, altPower, asExpansion, format); } function tryLoadContentAsSingleMedia(name, content, openType, port, altPower, asExpansion, format) { openType = openType || OPEN_TYPE.AUTO; // Try as a SaveState file if (openType === OPEN_TYPE.STATE || openType === OPEN_TYPE.AUTO) if (saveStateSocket.loadStateFile(content)) return true; // Try as Cartridge Data (SRAM, etc) if (openType === OPEN_TYPE.CART_DATA || openType === OPEN_TYPE.AUTO) if (cartridgeSocket.loadCartridgeData(port, name, content)) return true; // Try to load as ROM (Cartridge) if (openType === OPEN_TYPE.ROM || openType === OPEN_TYPE.AUTO) { var rom = new jt.ROM(name, content, null, format); return self.loadROM(rom, port, altPower, asExpansion); } // Not a valid content return false; } function onFileInputChange(e) { e.returnValue = false; // IE e.preventDefault(); e.stopPropagation(); e.target.focus(); if (!this.files || this.files.length === 0) return; // this will have a property "files"! var files = jt.Util.asNormalArray(this.files); // Tries to clear the last selected file so the same file can be chosen try { fileInputElement.value = ""; } catch (ex) { // Ignore } var wasPaused = console.systemPause(true); var resume = function (s) { if (!wasPaused) console.systemPause(false); }; if (files && files.length > 0) { if (files.length === 1) self.readFromFile(files[0], chooserOpenType, chooserPort, chooserAltPower, chooserAsExpansion, resume); else self.readFromFiles(files, chooserOpenType, chooserPort, chooserAltPower, chooserAsExpansion, resume); } return false; } function onDragOver(e) { e.returnValue = false; // IE e.preventDefault(); e.stopPropagation(); if (e.dataTransfer) { if (Javatari.CARTRIDGE_CHANGE_DISABLED) e.dataTransfer.dropEffect = "none"; else if (e.ctrlKey) e.dataTransfer.dropEffect = "copy"; else if (e.altKey) e.dataTransfer.dropEffect = "link"; } dragButtons = e.buttons > 0 ? e.buttons : MOUSE_BUT1_MASK; // If buttons not supported, consider it a left-click } function onDrop(e) { e.returnValue = false; // IE e.preventDefault(); e.stopPropagation(); e.target.focus(); if (!e.dataTransfer) return; if (peripheralControls.mediaChangeDisabledWarning()) return; var wasPaused = console.systemPause(true); var port = e.shiftKey ? 1 : 0; var altPower = dragButtons & MOUSE_BUT2_MASK; var asExpansion = e.ctrlKey; var openType = OPEN_TYPE.AUTO; // Try to get local file/files if present var files = e.dataTransfer && e.dataTransfer.files; var resume = function (s) { if (!wasPaused) console.systemPause(false); }; if (files && files.length > 0) { if (files.length === 1) self.readFromFile(files[0], openType, port, altPower, asExpansion, resume); else self.readFromFiles(files, openType, port, altPower, asExpansion, resume); } else { // If not, try to get URL var url = e.dataTransfer.getData("text"); if (url && url.length > 0) self.readFromURL(url, openType, port, altPower, asExpansion, resume); else resume(); } } function showError(message) { jt.Util.message("Could not load file(s):\n\n" + message + "\n"); } function createFileInputElement() { fileInputElement = document.createElement("input"); fileInputElement.id = "jt-file-loader-input"; fileInputElement.type = "file"; fileInputElement.multiple = true; fileInputElement.accept = INPUT_ACCEPT.AUTO; fileInputElement.style.display = "none"; fileInputElement.addEventListener("change", onFileInputChange); fileInputElementParent.appendChild(fileInputElement); } var console; var cartridgeSocket; var saveStateSocket; var fileInputElement; var fileInputElementParent; var chooserOpenType; var chooserPort = 0; var chooserAltPower = false; var chooserAsExpansion = false; var dragButtons = 1; var MOUSE_BUT1_MASK = 1; var MOUSE_BUT2_MASK = 2; var OPEN_TYPE = jt.FileLoader.OPEN_TYPE; this.OPEN_TYPE = OPEN_TYPE; // For the programatic interface var INPUT_ACCEPT = { ROM: ".bin,.BIN,.rom,.ROM,.a26,.A26,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP", STATE: ".jst,.JST", CART_DATA: ".dat,.DAT,.sram,.SRAM", AUTO: ".bin,.BIN,.rom,.ROM,.a26,.A26,.jst,.JST,.zip,.ZIP,.gz,.GZ,.gzip,.GZIP" }; var INPUT_MULTI = { ROM: false, STATE: false, CART_DATA: false, AUTO: false }; var TYPE_DESC = { ROM: "ROM", STATE: "Savestate", CART_DATA: "Cartridge Data", AUTO: "ROM" }; var LOCAL_STORAGE_LAST_URL_KEY = "javatarilasturl"; var DIR_NOT_SUPPORTED_HINT = '\n\nIMPORTANT: Directories are not supported for loading!'; Javatari.fileLoader = this; }; jt.FileLoader.OPEN_TYPE = { AUTO: "AUTO", ROM: "ROM", STATE: "STATE", CART_DATA: "CART_DATA" }; ================================================ FILE: src/main/room/files/RecentStoredROMs.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.RecentStoredROMs = function() { this.getCatalog = function() { if (!storedList) { try { storedList = JSON.parse(localStorage.javataristoredromsicatalog); } catch (e) { // giveup } if (!storedList) initStore(); } return storedList; }; this.storeROM = function(rom) { this.getCatalog(); var found = storedList.find(function(stored) { return stored && stored.h === rom.info.h; }); if (!found || (found.n != rom.info.l || found.f != rom.info.f)) { getStoredROMs(); if (found) { var oldIdx = storedList.indexOf(found); storedList.splice(oldIdx, 1); storedROMs.splice(oldIdx, 1); } else if (storedList.length >= MAX_ITMES) { storedList = storedList.slice(0, MAX_ITMES - 1); storedROMs = storedROMs.slice(0, MAX_ITMES - 1); } storedList.unshift({ n: rom.info.l, h: rom.info.h, f: rom.info.f }); for (var i = 0; i < storedList.length; ++i) storedList[i].i = i; localStorage.javataristoredromsicatalog = JSON.stringify(storedList); storedROMs.unshift(rom.saveState(true)); // true: include content bytes localStorage.javataristoredromsdata = JSON.stringify(storedROMs); this.lastROMLoadedIndex = 0; jt.Util.log("New ROM stored: " + rom.info.n + ", " + rom.info.h); } else this.lastROMLoadedIndex = storedList.indexOf(found); localStorage.javataristoredromslastindex = this.lastROMLoadedIndex; }; this.getROM = function(index) { this.lastROMLoadedIndex = index; localStorage.javataristoredromslastindex = index; var romState = getStoredROMs()[index]; return romState ? jt.ROM.loadState(romState) : null; }; function getStoredROMs() { if (!storedROMs) { try { storedROMs = JSON.parse(localStorage.javataristoredromsdata); } catch (e) { // giveup } if (!storedROMs) initStore(); } return storedROMs; } function initStore() { storedList = []; localStorage.javataristoredromsicatalog = JSON.stringify(storedList); storedROMs = []; localStorage.javataristoredromsdata = JSON.stringify(storedROMs); } var last = localStorage.javataristoredromslastindex; this.lastROMLoadedIndex = last !== undefined ? Number.parseInt(last) : -1; var storedList, storedROMs; var MAX_ITMES = 10; }; ================================================ FILE: src/main/room/netplay/NetClient.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.NetClient = function(room) { "use strict"; var self = this; this.joinSession = function(pSessionID, pNick) { sessionIDToJoin = ("" + pSessionID).trim(); if (!sessionIDToJoin) return room.showOSD("Must enter Session Name for joining NetPlay session", true, true); // Check for wsOnly indicator var wsOnlyAsked; if (sessionIDToJoin[sessionIDToJoin.length - 1] === "@") { sessionIDToJoin = sessionIDToJoin.substr(0, sessionIDToJoin.length -1); wsOnlyAsked = true; } else wsOnlyAsked = false; nickDesired = pNick; wsOnlyDesired = wsOnlyAsked; if (sessionID === sessionIDToJoin && nick === nickDesired && wsOnly === wsOnlyDesired) return; if (sessionID) this.leaveSession(true); room.enterNetPendingMode(this); if (!ws) { ws = new WebSocket("wss://" + Javatari.SERVER_ADDRESS); ws.onmessage = onSessionMessage; ws.onopen = onSessionServerConnected; ws.onclose = onSessionServerDisconnected; } else onSessionServerConnected(); }; this.leaveSession = function(wasError, userMessage) { clearInterval(keepAliveTimer); keepAliveTimer = undefined; sessionID = nick = undefined; wsOnly = false; if (ws) { ws.onopen = ws.onclose = ws.onmessage = undefined; ws.close(); ws = undefined; } if (dataChannel) dataChannel.onopen = dataChannel.onclose = dataChannel.onmessage = undefined; if (rtcConnection) rtcConnection.onicecandidate = rtcConnection.ondatachannel = undefined; dataChannelActive = false; dataChannelFragmentData = ""; if (wasError) stopRTC(); else setTimeout(stopRTC, 300); // Give some time before ending RTC so Session Disconnection can be detected first by Server room.showOSD(userMessage || "NetPlay session ended", true, wasError); (wasError ? jt.Util.error : jt.Util.log) (userMessage || "NetPlay session ended"); room.enterStandaloneMode(); }; this.getSessionID = function() { return sessionID; }; this.netVideoClockPulse = function() { // Client gets clocks from Server at onServerNetUpdate() }; function onSessionServerConnected() { // Setup keep-alive if (keepAliveTimer === undefined) keepAliveTimer = setInterval(keepAlive, 30000); // Join a Session ws.send(JSON.stringify({ sessionControl: "joinSession", sessionType: "javatari", sessionID: sessionIDToJoin, clientNick: nickDesired, wsOnly: wsOnlyDesired, queryVariables: [ "RTC_CONFIG" ] })); } function onSessionServerDisconnected() { self.leaveSession(true, keepAliveTimer ? "NetPlay session ended: Connection lost" : "NetPlay: Connection error"); } function onSessionMessage(event) { var message = JSON.parse(event.data); if (message.javatariUpdate) return onServerNetUpdate(JSON.parse(message.javatariUpdate)); if (message.sessionControl) { switch (message.sessionControl) { case "sessionJoined": onSessionJoined(message); return; case "sessionDestroyed": self.leaveSession(false, 'NetPlay Session "' + sessionID + '" ended'); return; case "joinError": self.leaveSession(true, "NetPlay: " + message.errorMessage); return; } return; } if(message.serverSDP) onServerSDP(message); } function onSessionJoined(message) { sessionID = message.sessionID; nick = message.clientNick; wsOnly = wsOnlyDesired || message.wsOnly; justJoined = true; if (wsOnly) return enterNetClientMode(); try { rtcConnectionConfig = JSON.parse(message.queriedVariables.RTC_CONFIG || "{}"); } catch (e) {} // Start RTC rtcConnection = new RTCPeerConnection(rtcConnectionConfig); // Set up the ICE candidates rtcConnection.onicecandidate = function(e) { if (!e.candidate) ws.send(JSON.stringify({ clientSDP: rtcConnection.localDescription })); }; // Wait for data channel rtcConnection.ondatachannel = function(event) { dataChannel = event.channel; dataChannel.onopen = onDataChannelOpen; dataChannel.onclose = onDataChannelClose; dataChannel.onmessage = onDataChannelMessage; }; } function enterNetClientMode() { room.showOSD('NetPlay Session "' + sessionID + '" joined as "' + nick + '"', true); jt.Util.log('NetPlay Session "' + sessionID + '" joined as "' + nick + '"'); consoleControls.netClearControlsToSend(); room.enterNetClientMode(self); } function onServerSDP(message) { rtcConnection.setRemoteDescription(new RTCSessionDescription(message.serverSDP)) .then(function() { return rtcConnection.createAnswer(); }) .then(function(desc) { return rtcConnection.setLocalDescription(desc); }) .catch(onRTCError); } function onDataChannelOpen(event) { dataChannelActive = true; dataChannelFragmentData = ""; enterNetClientMode(); } function onDataChannelClose(event) { jt.Util.error("NetPlay dataChannel closed"); self.leaveSession(true, "NetPlay session ended: P2P connection lost"); } function onDataChannelMessage(event) { var data = receiveFromDataChannel(event); if (data) onServerNetUpdate(JSON.parse(data)); } function onRTCError(error) { jt.Util.error("NetPlay RTC error:", error); self.leaveSession(true, "NetPlay session ended: P2P connection error"); } function stopRTC() { if (dataChannel) { dataChannel.onopen = dataChannel.onclose = dataChannel.onmessage = undefined; dataChannel.close(); dataChannel = undefined; } if (rtcConnection) { rtcConnection.onicecandidate = rtcConnection.ondatachannel = undefined; rtcConnection.close(); rtcConnection = undefined; } } function onServerNetUpdate(netUpdate) { // console.log(netUpdate); // Full Update? if (netUpdate.s) { atariConsole.loadState(netUpdate.s); // extended if (justJoined) { // Change Controls Mode automatically to adapt to Server room.consoleControls.setP1ControlsAndPaddleMode(!netUpdate.cm.p1, netUpdate.cm.pd); justJoined = false; } } else { // Apply controls changes from Server if (netUpdate.c) consoleControls.netClientApplyControlsChanges(netUpdate.c); // Send local (Client) Machine clock atariConsole.videoClockPulseApplyPulldowns(netUpdate.v); } // Send clock do Controllers atariConsole.getConsoleControlsSocket().controlsClockPulse(); // Send local controls to Server. We always send a message even when empty to keep the channel active var update = { c: consoleControls.netGetControlsToSend() }; // Use DataChannel if available if (dataChannelActive) dataChannel.send(JSON.stringify(update)); // Or fallback to WebSocket relayed through the Session Server (BAD!) else ws.send(JSON.stringify({ javatariUpdate: update })); consoleControls.netClearControlsToSend(); } function keepAlive() { try { ws.send('{ "sessionControl": "keep-alive" }'); } catch (e) { jt.Util.error("NetPlay error sending keep-alive"); self.leaveSession(true, "NetPlay session ended: Connection error"); } } // Automatically reconstructs message fragments as needed. Data must be a String function receiveFromDataChannel(event) { var data = event.data; var fragFlag = data.substr(0, 8); if (fragFlag === DATA_CHANNEL_FRAG_PART || fragFlag === DATA_CHANNEL_FRAG_END) { dataChannelFragmentData += data.substr(8); if (fragFlag === DATA_CHANNEL_FRAG_END) { data = dataChannelFragmentData; // console.log("Fragmented message received: " + data.length + ", fragments: " + ((data.length / DATA_CHANNEL_FRAG_SIZE - 0.0001) | 0 + 1)); dataChannelFragmentData = ""; return data; } } else { dataChannelFragmentData = ""; return data; } } var atariConsole = room.console; var consoleControls = room.consoleControls; var ws; var sessionID; var sessionIDToJoin; var nick; var nickDesired; var wsOnlyDesired = false; var justJoined = false; var keepAliveTimer; var rtcConnectionConfig; var wsOnly = false; var rtcConnection; var dataChannel; var dataChannelActive = false; var dataChannelFragmentData = ""; var DATA_CHANNEL_FRAG_SIZE = 16200; var DATA_CHANNEL_FRAG_PART = "#@FrgS@#"; var DATA_CHANNEL_FRAG_END = "#@FrgE@#"; }; jt.NetClient.initKeepAlive = function() { if (Javatari.SERVER_ADDRESS && Javatari.SERVER_KEEPALIVE) jt.NetClient.sendKeepAlive(); }; jt.NetClient.sendKeepAlive = function() { fetch("https://" + Javatari.SERVER_ADDRESS + "/keepalive", { mode: "no-cors" }) .catch(function(e) { jt.Util.error("Sending KeepAlive: ", e); }) .finally(function() { if (Javatari.SERVER_KEEPALIVE > 0) setTimeout(jt.NetClient.sendKeepAlive, Javatari.SERVER_KEEPALIVE); }); }; ================================================ FILE: src/main/room/netplay/NetServer.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.NetServer = function(room) { "use strict"; var self = this; this.startSession = function(pSessionID) { sessionIDToCreate = pSessionID ? ("" + pSessionID).trim() : undefined; // Check for wsOnly indicator var wsOnlyAsked; if (sessionIDToCreate && sessionIDToCreate[sessionIDToCreate.length - 1] === "@") { sessionIDToCreate = sessionIDToCreate.substr(0, sessionIDToCreate.length -1); wsOnlyAsked = true; } else wsOnlyAsked = false; if (sessionIDToCreate && (sessionID === sessionIDToCreate) && (wsOnly === wsOnlyAsked)) return; if (sessionID) this.stopSession(true); room.enterNetPendingMode(this); wsOnly = wsOnlyAsked; if (!ws) { ws = new WebSocket("wss://" + Javatari.SERVER_ADDRESS); ws.onmessage = onSessionMessage; ws.onopen = onSessionServerConnected; ws.onclose = onSessionServerDisconnected; } else onSessionServerConnected(); }; this.stopSession = function(wasError, userMessage) { clearInterval(keepAliveTimer); keepAliveTimer = undefined; if (ws) { ws.onmessage = ws.onopen = ws.onclose = undefined; ws.close(); ws = undefined; } if (wasError) dropAllClients(); else setTimeout(dropAllClients, 300); // Give some time before ending RTC so Session ending can be detected first by Clients room.showOSD(userMessage || 'NetPlay Session "' + sessionID + '" stopped', true, wasError); (wasError ? jt.Util.error : jt.Util.log) (userMessage || 'NetPlay Session "' + sessionID + '" stopped'); sessionID = undefined; room.enterStandaloneMode(); }; this.getSessionID = function() { return sessionID; }; this.netVideoClockPulse = function() { // Send clock do Controllers atariConsole.getConsoleControlsSocket().controlsClockPulse(); // Send local (Server) Machine clock var videoPulls = atariConsole.videoClockPulseGetNextPulldowns(); atariConsole.videoClockPulseApplyPulldowns(videoPulls); // Send net clock update to all Clients var data, dataFull, dataNormal; for (var cNick in clients) { var client = clients[cNick]; if (!client.wsOnly && !client.dataChannelActive) continue; if (client.justJoined || nextUpdateFull) { client.justJoined = false; if (!dataFull) { var netUpdateFull = { s: atariConsole.saveState(true), // extended cm: { p1: room.consoleControls.isP1ControlsMode(), pd: room.consoleControls.isPaddleMode() } }; dataFull = JSON.stringify(netUpdateFull); } data = dataFull; } else { if (!dataNormal) { netUpdate.c = consoleControls.netGetControlsToSend(); netUpdate.v = videoPulls; dataNormal = JSON.stringify(netUpdate); } data = dataNormal; } try { // Use DataChannel if available if (client.dataChannelActive) sendToDataChannel(client.dataChannel, data); // Or fallback to WebSocket relayed through the Session Server (BAD!) else ws.send(JSON.stringify({ toClientNick: client.nick, javatariUpdate: data })); } catch (e) { dropClient(client, true, true, 'NetPlay client "' + client.nick + '" dropped: P2P error sending data'); } } nextUpdateFull = false; consoleControls.netClearControlsToSend(); }; this.processExternalStateChange = function() { nextUpdateFull = true; }; function onSessionServerConnected() { // Setup keep-alive if (keepAliveTimer === undefined) keepAliveTimer = setInterval(keepAlive, 30000); // Start a new Session var command = { sessionControl: "createSession", sessionType: "javatari", wsOnly: wsOnly, queryVariables: [ "RTC_CONFIG", "RTC_DATA_CHANNEL_CONFIG" ] }; if (sessionIDToCreate) command.sessionID = sessionIDToCreate; ws.send(JSON.stringify(command)); } function onSessionServerDisconnected() { self.stopSession(true, keepAliveTimer ? "NetPlay Session stopped: Connection lost" : "NetPlay: Connection error"); } function onSessionMessage(event) { var message = JSON.parse(event.data); if (message.javatariUpdate) return onClientNetUpdate(message.javatariUpdate); if (message.sessionControl) { switch (message.sessionControl) { case "sessionCreated": onSessionCreated(message); return; case "clientJoined": onClientJoined(message); return; case "clientLeft": onClientLeft(message); return; case "createError": self.stopSession(true, "NetPlay: " + message.errorMessage); return; } return; } if(message.clientSDP) onClientSDP(message); } function onSessionCreated(message) { try { rtcConnectionConfig = JSON.parse(message.queriedVariables.RTC_CONFIG || "{}"); } catch (e) {} try { dataChannelConfig = JSON.parse(message.queriedVariables.RTC_DATA_CHANNEL_CONFIG || "{}"); } catch (e) {} sessionID = message.sessionID; consoleControls.netClearControlsToSend(); room.enterNetServerMode(self); room.showOSD('NetPlay session "' + message.sessionID + '" started', true); jt.Util.log('NetPlay session "' + message.sessionID + '" started'); } function onClientJoined(message) { var client = { nick: message.clientNick, justJoined: true, wsOnly: wsOnly || !!message.wsOnly }; clients[client.nick] = client; room.showOSD('NetPlay client "' + client.nick + '" joined', true); jt.Util.log('NetPlay client "' + client.nick + '" joined'); // Use RTC? if (client.wsOnly) return; // Start RTC var rtcConnection = new RTCPeerConnection(rtcConnectionConfig); client.rtcConnection = rtcConnection; rtcConnection.onicecandidate = function(e) { if (!e.candidate) { jt.Util.log("Server SDP for client " + client.nick + ":", rtcConnection.localDescription); ws.send(JSON.stringify({toClientNick: client.nick, serverSDP: rtcConnection.localDescription})); } }; var dataChannel = rtcConnection.createDataChannel("dataChannel", dataChannelConfig ); client.dataChannel = dataChannel; dataChannel.onopen = function(event) { onDataChannelOpen(client, event) }; dataChannel.onclose = function(event) { onDataChannelClose(client, event) }; dataChannel.onmessage = function(event) { onDataChannelMessage(client, event) }; // Create an offer to connect rtcConnection.createOffer() .then(function(desc) { return rtcConnection.setLocalDescription(desc); }) .catch( function(error) { onRTCError(client, error); }); } function onClientLeft(message) { var client = clients[message.clientNick]; if (!client) return; dropClient(client, true, false, 'NetPlay client "' + client.nick + '" left'); } function onClientSDP(message) { var client = clients[message.fromClientNick]; if (!client) return; jt.Util.log("Client SDP from client " + client.nick + ":", message.clientSDP); client.rtcConnection.setRemoteDescription(new RTCSessionDescription(message.clientSDP)) .catch(onRTCError); } function onDataChannelOpen(client, event) { jt.Util.log("Client " + client.nick + " dataChannel open"); client.dataChannelActive = true; } function onDataChannelClose(client, event) { jt.Util.error("NetPlay Client " + client.nick + " dataChannel closed"); dropClient(client, true, true, 'NetPlay client "' + client.nick + '" dropped: P2P connection lost'); } function onDataChannelMessage(client, event) { onClientNetUpdate(JSON.parse(event.data)); } function onRTCError(client, error) { jt.Util.error("NetPlay Client " + client.nick + " RTC error:", error); dropClient(client, true, true, 'NetPlay client "' + client.nick + '" dropped: P2P connection error'); } function dropAllClients() { for (var cID in clients) dropClient(clients[cID], false); } function dropClient(client, showMessage, wasError, userMessage) { if (showMessage) { room.showOSD(userMessage || 'NetPlay client "' + client.nick + '" left', true, wasError); (wasError ? jt.Util.error : jt.Util.log) (userMessage || 'NetPlay client "' + client.nick + '" left'); } if (client.dataChannel) { client.dataChannel.onopen = client.dataChannel.onclose = client.dataChannel.onmessage = undefined; client.dataChannel.close(); } if (client.rtcConnection) { client.rtcConnection.onicecandidate = undefined; client.rtcConnection.close(); } delete clients[client.nick]; } function onClientNetUpdate(netUpdate) { // console.log(netUpdate); // client.lastUpdate = netUpdate; // Process Controls changes as if they were local controls immediately if (netUpdate.c) consoleControls.netServerProcessControlsChanges(netUpdate.c); } function keepAlive() { try { ws.send('{ "sessionControl": "keep-alive" }'); } catch (e) { jt.Util.error("NetPlay error sending keep-alive"); self.stopSession(true, "NetPlay Session stopped: connection error"); } } // Automatically fragments message if needed. Data must be a String function sendToDataChannel(dataChannel, data) { var len = data.length; if (len < MAX_DATA_CHANNEL_SIZE) return dataChannel.send(data); var c = 0; var p = 0; while (true) { var frag = data.substr(p, DATA_CHANNEL_FRAG_SIZE); p += DATA_CHANNEL_FRAG_SIZE; c++; if (p < len) dataChannel.send(DATA_CHANNEL_FRAG_PART + frag); else { dataChannel.send(DATA_CHANNEL_FRAG_END + frag); // console.log("Fragmented message sent: " + data.length, + ", fragments: " + c); return; } } } var atariConsole = room.console; var consoleControls = room.consoleControls; var netUpdate = { v: 0, c: undefined }; var nextUpdateFull = false; var ws; var sessionID; var sessionIDToCreate; var keepAliveTimer; var clients = {}; var wsOnly = false; var rtcConnectionConfig; var dataChannelConfig; var MAX_DATA_CHANNEL_SIZE = 16300; var DATA_CHANNEL_FRAG_SIZE = 16200; var DATA_CHANNEL_FRAG_PART = "#@FrgS@#"; var DATA_CHANNEL_FRAG_END = "#@FrgE@#"; }; ================================================ FILE: src/main/room/savestate/LocalStorageSaveStateMedia.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.LocalStorageSaveStateMedia = function(room) { "use strict"; this.connect = function(socket) { socket.connectMedia(this); }; this.connectPeripherals = function(pFileDownloader) { fileDownloader = pFileDownloader; }; this.isSlotUsed = function(slot) { return localStorage["javatarisave" + slot] !== undefined; }; this.saveState = function(slot, state) { var data = buildDataFromState(state); return data && saveToLocalStorage("save" + slot, data); }; this.loadState = function(slot) { var data = loadFromLocalStorage("save" + slot); return buildStateFromData(data); }; this.saveStateFile = function(fileName, state) { if (checkDenyNetPlayOperation()) return; var data = buildDataFromState(state); if (data) fileDownloader.startDownloadBinary((fileName || "Javatari SaveState") + SAVE_STATE_FILE_EXTENSION, data, "System State file"); }; this.loadStateFile = function(data) { if (checkDenyNetPlayOperation()) return; return buildStateFromData(data); }; this.saveResource = function(entry, data) { try { var res = data && JSON.stringify(data); return saveToLocalStorage("res" + entry, res); } catch(ex) { // give up } }; this.loadResource = function(entry) { try { var res = loadFromLocalStorage("res" + entry); return res && JSON.parse(res); } catch(ex) { // give up } }; this.externalStateChange = function() { // Let the NetPlay Server know if (room.netPlayMode === 1) room.netController.processExternalStateChange(); }; var saveToLocalStorage = function(entry, data) { if (checkDenyNetPlayOperation()) return true; try { localStorage["javatari" + entry] = data; return true; } catch (ex) { jt.Util.error(ex); return false; } }; var loadFromLocalStorage = function(entry) { if (checkDenyNetPlayOperation()) return; try { return localStorage["javatari" + entry]; } catch (ex) { jt.Util.warning(ex); // give up } }; var buildDataFromState = function(state) { try { return SAVE_STATE_IDENTIFIER + JSON.stringify(state); } catch(ex) { jt.Util.error(ex); // give up } }; var buildStateFromData = function (data) { try { var id; if (typeof data == "string") id = data.substr(0, SAVE_STATE_IDENTIFIER.length); else id = jt.Util.int8BitArrayToByteString(data, 0, SAVE_STATE_IDENTIFIER.length); // Check for the identifier if (id !== SAVE_STATE_IDENTIFIER && id !== SAVE_STATE_IDENTIFIER_OLD) return; var stateData; if (typeof data == "string") stateData = data.slice(SAVE_STATE_IDENTIFIER.length); else stateData = jt.Util.int8BitArrayToByteString(data, SAVE_STATE_IDENTIFIER.length); return stateData && JSON.parse(stateData); } catch(ex) { jt.Util.error(ex); } }; function checkDenyNetPlayOperation() { // Do not perform operation during NetPlay Client mode return room.netPlayMode === 2; } var fileDownloader; var SAVE_STATE_IDENTIFIER = String.fromCharCode(0, 0) + "javataristate!"; // char 0 so browsers like Safari think the file is binary... :-( var SAVE_STATE_IDENTIFIER_OLD = "javatarijsstate!"; var SAVE_STATE_FILE_EXTENSION = ".jst"; }; ================================================ FILE: src/main/room/screen/CanvasDisplay.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // TODO Remove "Center" rounding problems as possible. Main screen element centering still remaining // TODO Possible to use hotkeys and bypass logo messages jt.CanvasDisplay = function(room, mainElement) { "use strict"; var self = this; function init() { jt.Util.insertCSS(jt.ScreenGUI.css()); delete jt.ScreenGUI.css; setupMain(); setupBar(); setupFullscreen(); consolePanel = new jt.ConsolePanel(self, consolePanelElement); monitor = new jt.Monitor(self); } this.connect = function(pConsole) { atariConsole = pConsole; monitor.connect(atariConsole.getVideoOutput()); consoleControlsSocket = atariConsole.getConsoleControlsSocket(); cartridgeSocket = atariConsole.getCartridgeSocket(); consolePanel.connect(consoleControlsSocket); }; this.connectPeripherals = function(pRecentROMs, pFileLoader, pFileDownloader, pConsoleControls, pPeripheralControls, pStateMedia) { recentROMs = pRecentROMs; fileLoader = pFileLoader; pFileLoader.registerForDnD(fsElement); pFileLoader.registerForFileInputElement(fsElement); fileDownloader = pFileDownloader; fileDownloader.registerForDownloadElement(fsElement); peripheralControls = pPeripheralControls; consoleControls = pConsoleControls; consoleControls.addKeyInputElement(fsElement); stateMedia = pStateMedia; consolePanel.connectPeripherals(pFileLoader, consoleControls, peripheralControls); }; this.powerOn = function() { monitor.setDefaults(); updateLogo(); document.documentElement.classList.add("jt-started"); setPageVisibilityHandling(); this.focus(); if (JavatariFullScreenSetup.shouldStartInFullScreen()) { setFullscreenState(true); setEnterFullscreenByAPIOnFirstTouch(); } }; this.powerOff = function() { document.documentElement.classList.remove("jt-started"); }; this.start = function(startAction) { // Show mobile messages or start automatically if (isMobileDevice && !isBrowserStandalone && !isFullscreen) { // Install as App message if (jt.Util.isOfficialHomepage()) showLogoMessage('For ' + (fullscreenAPIEnterMethod ? 'the best' : 'a full-screen') + ' experience, use
the "Add to Home Screen" function
then launch from the Installed App', "NICE!", false, startActionInFullScreen); // Go fullscreen message else showLogoMessage('For the best experience,
Javatari will go full-screen', "GO!", true, startActionInFullScreen); } else startAction(); function startActionInFullScreen() { self.setFullscreen(true); startAction(); } }; this.refresh = function(image, sourceWidth, sourceHeight) { // Hide mouse cursor if not moving for some time if (cursorHideFrameCountdown > 0) if (--cursorHideFrameCountdown <= 0) hideCursorAndBar(); // If needed, turn signal on and hide logo if (!signalIsOn) { signalIsOn = true; updateLogo(); } // Update frame if (!canvasContext) createCanvasContext(); canvasContext.drawImage( image, 0, 0, canvas.width, canvas.height ); //console.log("" + sourceWidth + "x" + sourceHeight + " > " + targetWidth + "x" + targetHeight); }; this.videoSignalOff = function() { signalIsOn = false; showCursorAndBar(); updateLogo(); }; this.mousePointerLocked = function(state) { mousePointerLocked = state; if (mousePointerLocked) hideCursorAndBar(); else showCursorAndBar(); }; this.openHelp = function() { self.openSettings("GENERAL"); return false; }; this.openAbout = function() { self.openSettings("ABOUT"); return false; }; this.openSettings = function(page) { closeAllOverlays(); if (!settingsDialog) settingsDialog = new jt.SettingsDialog(fsElementCenter, consoleControls); settingsDialog.show(page); }; this.openSaveStateDialog = function(save) { closeAllOverlays(); if (!saveStateDialog) saveStateDialog = new jt.SaveStateDialog(fsElementCenter, consoleControls, peripheralControls, stateMedia); saveStateDialog.show(save); }; this.openQuickOptionsDialog = function() { closeAllOverlays(); if (!quickOtionsDialog) quickOtionsDialog = new jt.QuickOptionsDialog(fsElementCenter, consoleControls, consoleControlsSocket, peripheralControls); quickOtionsDialog.show(); }; this.openNetPlayDialog = function() { closeAllOverlays(); if (!netPlayDialog) netPlayDialog = new jt.NetPlayDialog(room, fsElementCenter); netPlayDialog.show(); }; this.openCartridgeFormatDialog = function(altPower) { closeAllOverlays(); if (!cartFormatDialog) cartFormatDialog = new jt.CartridgeFormatDialog(this, fsElementCenter, atariConsole, cartridgeSocket); cartFormatDialog.show(altPower); }; this.openLoadFileDialog = function(altPower, secPort) { fileLoader.openFileChooserDialog(jt.FileLoader.OPEN_TYPE.AUTO, altPower, secPort, false); }; this.openRecentROMsDialog = function () { closeAllOverlays(); if (!recentROMsDialog) recentROMsDialog = new jt.RecentROMsDialog(fsElementCenter, this, recentROMs, fileLoader); recentROMsDialog.show(); }; this.openCartridgeChooserDialog = function (force, altPower, secPort) { if (logoMessageActive) self.closeLogoMessage(); // May be invoked directly from outside! if (!force && recentROMs.getCatalog().length === 0) this.openLoadFileDialog(altPower, secPort); else this.openRecentROMsDialog(); }; this.toggleConsolePanel = function() { if (isFullscreen && isLandscape) consolePanelActiveLandscape = !consolePanelActiveLandscape; else consolePanelActivePortrait = !consolePanelActivePortrait; consolePanelUpdateForOrientation(); }; this.getControlReport = function(control) { // Only CRT Filter for now return { label: crtFilter === -2 ? "Browser" : crtFilter === -1 ? "Auto" : crtFilter === 0 ? "OFF" : "Level " + crtFilter, active: crtFilter >= 0 }; }; function consolePanelUpdateForOrientation() { setConsolePanelActive(isFullscreen && isLandscape ? consolePanelActiveLandscape : consolePanelActivePortrait); } function setConsolePanelActive(active) { if (consolePanelActive === active) return; consolePanelActive = active; consolePanel.setActive(consolePanelActive); updateScale(); if (consolePanelActive) showBar(); else cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; } this.toggleMenuByKey = function() { if (barMenuActive) hideBarMenu(); else { closeAllOverlays(); showBarMenu(barMenuSystem, true); } }; this.getScreenCapture = function() { if (!signalIsOn) return; return canvas.toDataURL('image/png'); }; this.saveScreenCapture = function() { var cap = this.getScreenCapture(); if (cap) fileDownloader.startDownloadURL("Javatari Screen", cap, "Screen Capture"); }; this.displayMetrics = function (pTargetWidth, pTargetHeight) { // No need to resize display if target size is unchanged if (targetWidth === pTargetWidth && targetHeight === pTargetHeight) return; targetWidth = pTargetWidth; targetHeight = pTargetHeight; updateCanvasContentSize(); if (isFullscreen) this.requestReadjust(true); else updateScale(); }; this.displayScale = function(pAspectX, pScaleY) { aspectX = pAspectX; scaleY = pScaleY; updateScale(); }; this.getMonitor = function() { return monitor; }; this.showOSD = function(message, overlap, error) { if (osdTimeout) clearTimeout(osdTimeout); if (!message) { osd.style.transition = "all 0.15s linear"; osd.style.top = "-29px"; osd.style.opacity = 0; osdShowing = false; return; } if (overlap || !osdShowing) { osd.innerHTML = message; osd.style.color = error ? "rgb(255, 60, 40)" : "rgb(0, 255, 0)"; } osd.style.transition = "none"; osd.style.top = "15px"; osd.style.opacity = 1; osdShowing = true; var availWidth = canvasOuter.clientWidth - 30; // message width - borders var width = osd.clientWidth; var scale = width < availWidth ? 1 : availWidth / width; osd.style.transform = "scale(" + scale.toFixed(4) + ")"; osdTimeout = setTimeout(hideOSD, OSD_TIME); }; this.displayDefaultScale = function() { if (Javatari.SCREEN_DEFAULT_SCALE > 0) return Javatari.SCREEN_DEFAULT_SCALE; var maxWidth = Number.parseFloat(window.getComputedStyle(mainElement.parentElement).width); //atariConsole.error(">>> Parent width: " + maxWidth); return maxWidth >= 640 ? 2.0 : maxWidth >= 540 ? 1.65 : maxWidth >= 420 ? 1.25 : maxWidth >= 355 ? 1.05 : maxWidth >= 340 ? 1 : maxWidth >= 300 ? 0.9 : 0.8; }; function hideOSD() { osd.style.transition = "all 0.15s linear"; osd.style.top = "-29px"; osd.style.opacity = 0; osdShowing = false; } this.setDebugMode = function(boo) { debugMode = !!boo; canvasContext = null; }; this.crtFilterToggle = function() { var newLevel = crtFilter + 1; if (newLevel > 3) newLevel = -2; setCRTFilter(newLevel); var levelDesc = crtFilterEffective === null ? "browser default" : crtFilterEffective < 1 ? "OFF" : "level " + crtFilterEffective; this.showOSD("CRT filter: " + (crtFilter === -1 ? "AUTO (" + levelDesc + ")" : levelDesc), true); // Persist if (Javatari.userPreferences.current.crtFilter !== crtFilter) { Javatari.userPreferences.current.crtFilter = crtFilter; Javatari.userPreferences.setDirty(); Javatari.userPreferences.save(); } }; this.crtFilterSetDefault = function() { var user = Javatari.userPreferences.current.crtFilter; setCRTFilter(Javatari.SCREEN_FILTER_MODE !== -3 ? Javatari.SCREEN_FILTER_MODE : user !== null && user > -3 ? user : -1); }; this.crtModeToggle = function() { var newMode = crtMode + 1; if (newMode > 1) newMode = -1; setCRTMode(newMode); var effectDesc = crtModeEffective === 1 ? "Phosphor" : "OFF"; this.showOSD("CRT mode: " + (crtMode === -1 ? "AUTO (" + effectDesc + ")" : effectDesc), true); }; this.crtModeSetDefault = function() { setCRTMode(Javatari.SCREEN_CRT_MODE); }; this.displayToggleFullscreen = function() { // Only and Always user initiated if (FULLSCREEN_MODE === -2) return; // If FullScreenAPI supported but not active, enter full screen by API regardless of previous state if (fullscreenAPIEnterMethod && !isFullScreenByAPI()) { enterFullScreenByAPI(); return; } // If not, toggle complete full screen state this.setFullscreen(!isFullscreen); }; this.setFullscreen = function(mode) { if (fullscreenAPIEnterMethod) { if (mode) enterFullScreenByAPI(); else exitFullScreenByAPI(); } else setFullscreenState(mode) }; this.focus = function() { canvas.focus(); }; this.consolePowerAndUserPauseStateUpdate = function(power, paused) { if (isLoading) power = false; powerButton.style.backgroundPosition = "" + powerButton.jtBX + "px " + (mediaButtonBackYOffsets[power ? 2 : 1]) + "px"; powerButton.jtMenu[0].label = "Power " + (power ? "OFF" : "ON"); var netDisable = room.netPlayMode === 2; powerButton.jtMenu[1].disabled = powerButton.jtMenu[12].disabled = netDisable || !power; powerButton.jtMenu[6].disabled = netDisable || !(cartridgeSocket && cartridgeSocket.inserted()); powerButton.jtMenu[5].disabled = powerButton.jtMenu[8].disabled = powerButton.jtMenu[9].disabled = powerButton.jtMenu[11].disabled = netDisable; }; this.cartridgeInserted = function(cart) { consolePanel.cartridgeInserted(cart); powerButton.jtMenu[6].disabled = !cart || room.netPlayMode === 2; }; this.controlsModeStateUpdate = function () { if(settingsDialog) settingsDialog.controlsModeStateUpdate(); if(quickOtionsDialog) quickOtionsDialog.controlsModeStateUpdate(); }; this.touchControlsActiveUpdate = function(active, dirBig) { if (touchControlsActive === active && touchControlsDirBig === dirBig) return; touchControlsActive = active; touchControlsDirBig = dirBig; if (isFullscreen) { if (touchControlsActive) consoleControls.setupTouchControlsIfNeeded(fsElementCenter); this.requestReadjust(true); } }; this.roomNetPlayStatusChangeUpdate = function(oldMode) { if (!netPlayDialog || !netPlayDialog.isVisible()) closeAllOverlays(); if (netPlayDialog) netPlayDialog.roomNetPlayStatusChangeUpdate(oldMode); netplayButton.classList.toggle("jt-hidden", room.netPlayMode < 1); }; this.controlStateChanged = function(control, state) { consolePanel.controlStateChanged(control, state); if (quickOtionsDialog) quickOtionsDialog.controlStateChanged(control, state); }; this.controlsStatesRedefined = function() { consolePanel.controlsStatesRedefined(); }; this.speakerUnlockStateUpdate = function(state) { unmuteMessage.classList.toggle("jt-show", !state); if (!state) { var availWidth = canvasOuter.clientWidth - 30; // message width - borders var width = unmuteMessage.clientWidth; var scale = width < availWidth ? 1 : availWidth / width; unmuteMessage.style.transform = "translate(-50%, 0) scale(" + scale.toFixed(4) + ")"; } }; this.setLoading = function(state) { isLoading = state; updateLoading(); }; this.requestReadjust = function(now) { if (settingsDialog && settingsDialog.isVisible()) settingsDialog.position(); if (now) readjustAll(true); else { readjustRequestTime = jt.Util.performanceNow(); if (!readjustInterval) readjustInterval = setInterval(readjustAll, 50); } }; function releaseControllersOnLostFocus() { consoleControlsSocket.releaseControllers(); } function hideCursorAndBar() { hideCursor(); hideBar(); cursorHideFrameCountdown = -1; } function showCursorAndBar(forceBar) { showCursor(); if (forceBar || !mousePointerLocked) showBar(); cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; } function showCursor() { if (!cursorShowing) { fsElement.style.cursor = cursorType; cursorShowing = true; } } function hideCursor() { if (cursorShowing) { fsElement.style.cursor = "none"; cursorShowing = false; } } function fullscreenByAPIChanged() { var prevFSState = isFullscreen; var newAPIState = isFullScreenByAPI(); // Return to window interface mode if user asked or not in standalone mode if (newAPIState || fullScreenAPIExitUserRequested || !isBrowserStandalone) setFullscreenState(newAPIState); else self.requestReadjust(); // If console not paused and on mobile, set message to resume, or set event to return to full screen if (prevFSState && !newAPIState && !fullScreenAPIExitUserRequested && isMobileDevice) { if (isBrowserStandalone) { setEnterFullscreenByAPIOnFirstTouch(); } else { atariConsole.systemPause(true); showLogoMessage("
Emulation suspended", "RESUME", true, function () { self.setFullscreen(true); atariConsole.systemPause(false); }); } } fullScreenAPIExitUserRequested = false; } function isFullScreenByAPI() { return !!document[fullScreenAPIQueryProp]; } function enterFullScreenByAPI() { if (fullscreenAPIEnterMethod) try { fullscreenAPIEnterMethod.call(fsElement); } catch (e) { /* give up */ } } function exitFullScreenByAPI() { if (fullScreenAPIExitMethod) try { fullScreenAPIExitUserRequested = true; fullScreenAPIExitMethod.call(document); } catch (e) { /* give up */ } } function updateScale() { var canvasWidth = Math.round(targetWidth * scaleY * aspectX * 2); // Fixed internal aspectX of 2 var canvasHeight = Math.round(targetHeight * scaleY); canvas.style.width = "" + canvasWidth + "px"; canvas.style.height = "" + canvasHeight + "px"; updateBarWidth(canvasWidth); if (!signalIsOn) updateLogoScale(); if (settingsDialog && settingsDialog.isVisible()) settingsDialog.position(); updateConsolePanelScale(canvasWidth); } function updateBarWidth(canvasWidth) { var fixedWidth = buttonsBarDesiredWidth > 0 ? buttonsBarDesiredWidth : canvasWidth; buttonsBar.style.width = buttonsBarDesiredWidth === -1 ? "100%" : "" + fixedWidth + "px"; buttonsBar.classList.toggle("jt-narrow", fixedWidth < NARROW_WIDTH); } function updateConsolePanelScale(maxWidth) { var panelHeight = consolePanel.updateScale(maxWidth, isFullscreen, isLandscape); mainElement.style.marginBottom = !isFullscreen && panelHeight > 0 ? "" + Math.ceil(panelHeight + 3) + "px" : "initial"; } function updateCanvasContentSize() { var factor = crtFilterEffective > 0 ? CANVAS_SIZE_FACTOR : 1; canvas.width = targetWidth * factor; canvas.height = targetHeight * factor; canvasContext = null; } function setCRTFilter(level) { crtFilter = level; crtFilterEffective = crtFilter === -2 ? null : crtFilter === -1 ? crtFilterAutoValue() : level; updateCanvasContentSize(); } function crtFilterAutoValue() { // Use mode 1 by default (context imageSmoothing OFF and CSS image-rendering set to smooth) // iOS browser bug: freezes after some time if imageSmoothing = true. OK if we use the setting above // Firefox on Android bug: image looks terrible if imageSmoothing = false. Lets use mode 2 or 3, or let browser default return isMobileDevice && !isIOSDevice && browserName === "FIREFOX" ? 0 : 1; } function setCRTMode(mode) { crtMode = mode; crtModeEffective = crtMode === -1 ? crtModeAutoValue() : crtMode; canvasContext = null; } function crtModeAutoValue() { return isMobileDevice ? 0 : 1; } function updateLogo() { if (!signalIsOn) { updateLogoScale(); showCursorAndBar(true); if (canvasContext) canvasContext.clearRect(0, 0, canvas.width, canvas.height); } logo.classList.toggle("jt-show", !signalIsOn); } function updateLoading() { var disp = isLoading ? "block" : "none"; logoLoadingIcon.style.display = disp; canvasLoadingIcon.style.display = disp; } function createCanvasContext() { // Prepare Context used to draw frame canvasContext = canvas.getContext("2d", { alpha: false, antialias: false }); setImageComposition(); setImageSmoothing(); } function setImageComposition() { if (crtModeEffective > 0 && !debugMode) { canvasContext.globalCompositeOperation = "source-over"; canvasContext.globalAlpha = 0.8; } else { canvasContext.globalCompositeOperation = "copy"; canvasContext.globalAlpha = 1; } } function setImageSmoothing() { canvas.style.imageRendering = (crtFilterEffective === 0 || crtFilterEffective === 2) ? canvasImageRenderingValue : "initial"; if (crtFilterEffective === null) return; // let default values for imageSmoothingEnabled var smoothing = crtFilterEffective >= 2; if (canvasContext.imageSmoothingEnabled !== undefined) canvasContext.imageSmoothingEnabled = smoothing; else { canvasContext.webkitImageSmoothingEnabled = smoothing; canvasContext.mozImageSmoothingEnabled = smoothing; canvasContext.msImageSmoothingEnabled = smoothing; } } function suppressContextMenu(element) { element.addEventListener("contextmenu", jt.Util.blockEvent); } function preventDrag(element) { element.ondragstart = jt.Util.blockEvent; } function setupMain() { mainElement.innerHTML = jt.ScreenGUI.html(); mainElement.tabIndex = -1; delete jt.ScreenGUI.html; fsElement = document.getElementById("jt-screen-fs"); fsElementCenter = document.getElementById("jt-screen-fs-center"); canvasOuter = document.getElementById("jt-screen-canvas-outer"); canvas = document.getElementById("jt-screen-canvas"); canvasLoadingIcon = document.getElementById("jt-canvas-loading-icon"); osd = document.getElementById("jt-osd"); logo = document.getElementById("jt-logo"); logoCenter = document.getElementById("jt-logo-center"); logoImage = document.getElementById("jt-logo-image"); logoLoadingIcon = document.getElementById("jt-logo-loading-icon"); logoMessage = document.getElementById("jt-logo-message"); logoMessageText = document.getElementById("jt-logo-message-text"); logoMessageOK = document.getElementById("jt-logo-message-ok"); logoMessageOKText = document.getElementById("jt-logo-message-ok-text"); scrollMessage = document.getElementById("jt-screen-scroll-message"); unmuteMessage = document.getElementById("jt-unmute-message"); consolePanelElement = document.getElementById("jt-console-panel"); suppressContextMenu(mainElement); preventDrag(logoImage); preventDrag(logoLoadingIcon); preventDrag(canvasLoadingIcon); updateCanvasContentSize(); // Try to determine correct value for image-rendering for the canvas filter modes switch (browserName) { case "CHROME": case "EDGE": case "OPERA": canvasImageRenderingValue = "pixelated"; break; case "FIREFOX": canvasImageRenderingValue = "-moz-crisp-edges"; break; case "SAFARI": canvasImageRenderingValue = "-webkit-optimize-contrast"; break; default: canvasImageRenderingValue = "pixelated"; } setupMainEvents(); } function setupMainEvents() { (isMobileDevice ? canvasOuter : fsElement).addEventListener("mousemove", function showCursorOnMouseMove() { showCursorAndBar(); }); if ("onblur" in document) fsElement.addEventListener("blur", releaseControllersOnLostFocus, true); else fsElement.addEventListener("focusout", releaseControllersOnLostFocus, true); window.addEventListener("orientationchange", function orientationChanged() { closeAllOverlays(); if (signalIsOn) hideCursorAndBar(); else showCursorAndBar(); self.requestReadjust(); }); mainElement.addEventListener("drop", closeAllOverlays, true); logoMessageOK.jtNeedsUIG = logoMessageOKText.jtNeedsUIG = true; // User Initiated Gesture required jt.Util.onTapOrMouseDownWithBlockUIG(logoMessageOK, self.closeLogoMessage); // Used to show bar and close overlays and modals if not processed by any other function jt.Util.addEventsListener(fsElementCenter, "touchstart touchend mousedown", function backScreenTouched(e) { if (e.type !== "touchend") { // Execute actions only for touchstart or mousedown closeAllOverlays(); showCursorAndBar(); } else if (e.cancelable) e.preventDefault(); // preventDefault only on touchend to avoid redundant mousedown ater a touchstart }); } function setupBar() { buttonsBar = document.getElementById("jt-bar"); buttonsBarInner = document.getElementById("jt-bar-inner"); if (BAR_AUTO_HIDE) { document.documentElement.classList.add("jt-bar-auto-hide"); fsElement.addEventListener("mouseleave", hideBar); hideBar(); } var menu = [ { label: "Power", clickModif: 0, control: jt.PeripheralControls.CONSOLE_POWER_TOGGLE }, { label: "Fry Console", control: jt.PeripheralControls.CONSOLE_POWER_FRY }, { label: "", divider: true }, { label: "Net Play!", control: jt.PeripheralControls.SCREEN_OPEN_NETPLAY }, { label: "", divider: true }, { label: "Select Cartridge", control: jt.PeripheralControls.CARTRIDGE_LOAD_RECENT }, { label: "Set ROM Format", clickModif: KEY_SHIFT_MASK, control: jt.PeripheralControls.CARTRIDGE_CHOOSE_FORMAT }, { label: "", divider: true }, { label: "Open File", clickModif: KEY_CTRL_MASK, control: jt.PeripheralControls.AUTO_LOAD_FILE, needsUIG: true }, { label: "Open URL", clickModif: KEY_CTRL_MASK | KEY_ALT_MASK, control: jt.PeripheralControls.AUTO_LOAD_URL, needsUIG: true }, { label: "", divider: true }, { label: "Load State", control: jt.PeripheralControls.CONSOLE_LOAD_STATE_MENU }, { label: "Save State", control: jt.PeripheralControls.CONSOLE_SAVE_STATE_MENU } ]; powerButton = addBarButton("jt-bar-power", -5, -26, "System Power", null, false, menu, "System"); barMenuSystem = menu; self.consolePowerAndUserPauseStateUpdate(false, false); // init states netplayButton = addBarButton("jt-bar-netplay", -192, -1, "NetPlay!", jt.PeripheralControls.SCREEN_OPEN_NETPLAY); netplayButton.classList.add("jt-hidden"); if (!isMobileDevice) { menu = [ { label: "Help & Settings", clickModif: 0, control: jt.PeripheralControls.SCREEN_OPEN_SETTINGS }, { label: "Quick Options", control: jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS }, { label: "Defaults", control: jt.PeripheralControls.SCREEN_DEFAULTS/*, fullScreenHidden: true*/ } ]; settingsButton = addBarButton("jt-bar-settings", -33, -26, "Settings", null, false, menu, "Settings"); } else { settingsButton = addBarButton("jt-bar-settings", -33, -26, "Quick Options", jt.PeripheralControls.SCREEN_OPEN_QUICK_OPTIONS, false); } gameSelectButton = addBarButton("jt-bar-select", -78, -51, "Game Select", jt.ConsoleControls.SELECT, true); gameResetButton = addBarButton("jt-bar-reset", -33, -51, "Game Reset", jt.ConsoleControls.RESET, true); if (FULLSCREEN_MODE !== -2) { fullscreenButton = addBarButton("jt-bar-full-screen", -103, -1, "Full Screen", jt.PeripheralControls.SCREEN_FULLSCREEN, false); fullscreenButton.jtNeedsUIG = true; if (isMobileDevice) fullscreenButton.classList.add("jt-mobile"); } if (!Javatari.SCREEN_RESIZE_DISABLED && !isMobileDevice) { scaleUpButton = addBarButton("jt-bar-scale-plus", -80, -1, "Increase Screen", jt.PeripheralControls.SCREEN_SCALE_PLUS, false); scaleUpButton.classList.add("jt-full-screen-hidden"); scaleDownButton = addBarButton("jt-bar-scale-minus", -58, -1, "Decrease Screen", jt.PeripheralControls.SCREEN_SCALE_MINUS, false); scaleDownButton.classList.add("jt-full-screen-hidden"); } var consolePanelButton = addBarButton("jt-bar-console-panel", -61, -25, "Toggle Console Panel", jt.PeripheralControls.SCREEN_CONSOLE_PANEL_TOGGLE, false); consolePanelButton.classList.add("jt-full-screen-only"); logoButton = addBarButton("jt-bar-logo", -99, -26, "About Javatari", jt.PeripheralControls.SCREEN_OPEN_ABOUT, false); logoButton.classList.add("jt-full-screen-hidden"); // Events for BarButtons and also MenuItems jt.Util.onTapOrMouseDownWithBlockUIG(buttonsBar, barElementTapOrMouseDown); jt.Util.addEventsListener(buttonsBar, "touchmove", barElementTouchMove); jt.Util.addEventsListener(buttonsBar, "mouseup touchend", barElementTouchEndOrMouseUp); } function addBarButton(id, bx, by, tooltip, control, isConsoleControl, menu, menuTitle) { var but = document.createElement('div'); but.id = id; but.classList.add("jt-bar-button"); but.jtBarElementType = 1; // Bar button but.jtControl = control; but.jtIsConsoleControl = isConsoleControl; but.style.backgroundPosition = "" + bx + "px " + by + "px"; but.jtBX = bx; if (menu) { but.jtMenu = menu; menu.jtTitle = menuTitle; menu.jtRefElement = but; menu.jtMenuIndex = barMenus.length; barMenus.push(menu); } if (tooltip) but.title = tooltip; // Mouse hover button but.addEventListener("mouseenter", function(e) { barButtonHoverOver(e.target, e); }); // Mouse left button (only for ConsoleControls) if (isConsoleControl) but.addEventListener("mouseleave", barButtonMouseLeft); buttonsBarInner.appendChild(but); return but; } function barButtonTapOrMousedown(elem, e, uigStart, uigEnd) { if (!uigEnd) consoleControls.hapticFeedbackOnTouch(e); if (logoMessageActive || uigStart) return; var prevActiveMenu = barMenuActive; closeAllOverlays(); // Single option, only left click if (elem.jtControl) { if (!e.button) { if (elem.jtIsConsoleControl) { barConsoleControlPressed = elem.jtControl; consoleControls.processControlState(barConsoleControlPressed, true); } else peripheralControls.controlActivated(elem.jtControl); } return; } var menu = elem.jtMenu; if (!menu) return; var modifs = 0 | (e.altKey && KEY_ALT_MASK) | (e.ctrlKey && KEY_CTRL_MASK) | (e.shiftKey && KEY_SHIFT_MASK); // Open/close menu with left-click if no modifiers if (modifs === 0 && !e.button) { if (prevActiveMenu !== menu) { showBarMenu(menu); // Only start LongTouch for touches! if (e.type === "touchstart") barButtonLongTouchStart(e); } return; } // Modifier options for left, middle or right click for (var i = 0; i < menu.length; ++i) if (menu[i].clickModif === modifs) { peripheralControls.controlActivated(menu[i].control, e.button === 1, menu[i].secSlot); // altPower for middleClick (button === 1) return; } // If no direct shortcut found with modifiers used, use SHIFT as secSlot modifier and try again if (modifs & KEY_SHIFT_MASK) { modifs &= ~KEY_SHIFT_MASK; for (i = 0; i < menu.length; ++i) if (menu[i].clickModif === modifs) { peripheralControls.controlActivated(menu[i].control, e.button === 1, true); // altPower for middleClick (button === 1) return; } } } function barButtonLongTouchStart(e) { barButtonLongTouchTarget = e.target; barButtonLongTouchSelectTimeout = window.setTimeout(function buttonsBarLongTouchSelectDefault() { if (!barMenuActive) return; var items = barMenu.jtItems; for (var i = 0; i < items.length; ++i) { var option = items[i].jtMenuOption; if (option && option.clickModif === 0) { barMenuItemSetActive(items[i], true); return; }} }, 450); } function barButtonLongTouchCancel() { if (barButtonLongTouchSelectTimeout) { clearTimeout(barButtonLongTouchSelectTimeout); barButtonLongTouchSelectTimeout = null; } } function barButtonHoverOver(elem, e) { if (barMenuActive && elem.jtMenu && barMenuActive !== elem.jtMenu ) { consoleControls.hapticFeedbackOnTouch(e); showBarMenu(elem.jtMenu); } } function barButtonMouseLeft() { if (barConsoleControlPressed) { cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; consoleControls.processControlState(barConsoleControlPressed, false); barConsoleControlPressed = null; } } function barButtonTouchEndOrMouseUp(e) { if (logoMessageActive) return; // Special case for ConsoleControl if (barConsoleControlPressed) { consoleControls.hapticFeedbackOnTouch(e); consoleControls.processControlState(barConsoleControlPressed, false); barConsoleControlPressed = null; return; } // Only touch, left or middle button if (barMenuItemActive && !(e.button > 1)) barMenuItemFireActive(e.shiftKey, e.button === 1 || e.ctrlKey); } function barMenuItemTapOrMouseDown(elem, e, uigEnd) { if (uigEnd) return; barMenuItemSetActive(elem, e.type === "touchstart"); } function barMenuItemHoverOver(elem, e) { barMenuItemSetActive(elem, e.type === "touchmove"); } function barMenuItemHoverOut() { barMenuItemSetActive(null); } function barMenuItemTouchEndOrMouseUp(e) { if (logoMessageActive) return; // Only touch, left or middle button if (barMenuItemActive && !(e.button > 1)) barMenuItemFireActive(e.shiftKey, e.button === 1 || e.ctrlKey); } function barMenuItemFireActive(secSlot, altPower) { var option = barMenuItemActive.jtMenuOption; barMenuItemSetActive(null); if (option && !option.disabled) { if (option.extension) { extensionsSocket.toggleExtension(option.extension, altPower, secSlot); } else if (option.control) { secSlot |= option.secSlot; closeAllOverlays(); peripheralControls.controlActivated(option.control, altPower, secSlot); } } } function barMenuItemSetActive(element, haptic) { if (element === barMenuItemActive) return; if (barMenuItemActive) barMenuItemActive.classList.remove("jt-hover"); if (element && element.jtMenuOption) { barMenuItemActive = element; if (haptic) consoleControls.hapticFeedback(); barMenuItemActive.classList.add("jt-hover"); } else barMenuItemActive = null; } function barElementTapOrMouseDown(e, uigStart, uigEnd) { cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; var elem = e.target; if (elem.jtBarElementType === 1) barButtonTapOrMousedown(elem, e, uigStart, uigEnd); else if (elem.jtBarElementType === 2) barMenuItemTapOrMouseDown(elem, e, uigEnd); else hideBarMenu(); } function barElementTouchMove(e) { jt.Util.blockEvent(e); var t = e.changedTouches[0]; var elem = t && document.elementFromPoint(t.clientX, t.clientY); if (barButtonLongTouchTarget && elem !== barButtonLongTouchTarget) barButtonLongTouchCancel(); if (elem.jtBarElementType !== 2 && elem !== barButtonLongTouchTarget) barMenuItemSetActive(null); if (elem.jtBarElementType === 1) barButtonHoverOver(elem, e); else if (elem.jtBarElementType === 2) barMenuItemHoverOver(elem, e); } function barElementTouchEndOrMouseUp(e) { cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; jt.Util.blockEvent(e); barButtonLongTouchCancel(); var elem = e.target; if (elem.jtBarElementType === 1) barButtonTouchEndOrMouseUp(e); else if (elem.jtBarElementType === 2) barMenuItemTouchEndOrMouseUp(e); } function setupFullscreen() { fullscreenAPIEnterMethod = fsElement.requestFullscreen || fsElement.webkitRequestFullscreen || fsElement.webkitRequestFullScreen || fsElement.mozRequestFullScreen; fullScreenAPIExitMethod = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen; if ("fullscreenElement" in document) fullScreenAPIQueryProp = "fullscreenElement"; else if ("webkitFullscreenElement" in document) fullScreenAPIQueryProp = "webkitFullscreenElement"; else if ("mozFullScreenElement" in document) fullScreenAPIQueryProp = "mozFullScreenElement"; if (!fullscreenAPIEnterMethod && isMobileDevice && !isBrowserStandalone) fullScreenScrollHack = true; if ("onfullscreenchange" in document) document.addEventListener("fullscreenchange", fullscreenByAPIChanged); else if ("onwebkitfullscreenchange" in document) document.addEventListener("webkitfullscreenchange", fullscreenByAPIChanged); else if ("onmozfullscreenchange" in document) document.addEventListener("mozfullscreenchange", fullscreenByAPIChanged); // Prevent scroll & zoom in fullscreen if not touching on the screen (canvas) or scroll message in hack mode if (!fullscreenAPIEnterMethod) { scrollMessage.jtScroll = canvas.jtScroll = logo.jtScroll = logoCenter.jtScroll = logoImage.jtScroll = logoMessage.jtScroll = logoMessageText.jtScroll = logoMessageOK.jtScroll = logoMessageOKText.jtScroll = true; fsElement.addEventListener("touchmove", function preventTouchMoveInFullscreenByHack(e) { if (isFullscreen) { if (!fullScreenScrollHack || !e.target.jtScroll) return jt.Util.blockEvent(e); else if (scrollMessageActive) setScrollMessage(false); } }); } } function setEnterFullscreenByAPIOnFirstTouch() { // Add event to enter in real fullScreenByAPI on first touch/click if possible if (fullscreenAPIEnterMethod) { var done = false; var enterFullScreenByAPIonFirstTouch = function() { if (done) return; done = true; jt.Util.removeEventsListener(fsElement, "touchend mousedown", enterFullScreenByAPIonFirstTouch, true); enterFullScreenByAPI(); }; jt.Util.addEventsListener(fsElement, "touchend mousedown", enterFullScreenByAPIonFirstTouch, true); // Capture! } } function setFullscreenState(mode) { isFullscreen = mode; if (mode) { setViewport(); document.documentElement.classList.add("jt-full-screen"); if (fullScreenScrollHack) document.documentElement.classList.add("jt-full-screen-scroll-hack"); consoleControls.setupTouchControlsIfNeeded(fsElementCenter); if (fullScreenScrollHack) setScrollMessage(true); if (!fullscreenAPIEnterMethod) tryToFixSafariBugOnFullScreenChange(); } else { restoreViewport(); document.documentElement.classList.remove("jt-full-screen"); if (fullScreenScrollHack) document.documentElement.classList.remove("jt-full-screen-scroll-hack"); if (!fullscreenAPIEnterMethod) tryToFixSafariBugOnFullScreenChange(); } closeAllOverlays(); self.requestReadjust(); } function tryToFixSafariBugOnFullScreenChange() { // Toggle a dummy element existence inside mainElement to try to force a reflow var dummy = document.getElementById("jt-dummy-element"); if (dummy) { mainElement.removeChild(dummy); } else { dummy = document.createElement("div"); dummy.id = "jt-dummy-element"; mainElement.appendChild(dummy); } } function showBar() { buttonsBar.classList.remove("jt-hidden"); } function hideBar() { if ((BAR_AUTO_HIDE || isFullscreen) && !barMenuActive && !consolePanelActive && !barConsoleControlPressed) { hideBarMenu(); buttonsBar.classList.add("jt-hidden"); } } function showBarMenu(menu, select) { if (!menu || barMenuActive === menu) return; if (!barMenu) { setupBarMenu(); setTimeout(function() { showBarMenu(menu, select); }, 1); return; } // Define items refreshBarMenu(menu); barMenuItemSetActive(select ? barMenu.jtDefaultItem : null); // Position var refElement = menu.jtRefElement; var p = (refElement && (refElement.offsetLeft - 15)) || 0; if (p + jt.ScreenGUI.BAR_MENU_WIDTH > refElement.parentElement.clientWidth) { barMenu.style.right = 0; barMenu.style.left = "auto"; barMenu.style.transformOrigin = "bottom right"; } else { if (p < 0) p = 0; barMenu.style.left = "" + p + "px"; barMenu.style.right = "auto"; barMenu.style.transformOrigin = "bottom left"; } // Show showCursorAndBar(true); barMenuActive = menu; barMenu.style.display = "inline-block"; barMenu.jtTitle.focus(); } function refreshBarMenu(menu) { barMenu.jtTitle.innerHTML = menu.jtTitle; barMenu.jtDefaultItem = null; var it = 0; var item; var maxShown = Math.min(menu.length, BAR_MENU_MAX_ITEMS); var h = jt.ScreenGUI.BAR_MENU_ITEM_HEIGHT + 3; // title + borders for (var op = 0; op < maxShown; ++op) { var option = menu[op]; if (option.label !== undefined) { item = barMenu.jtItems[it]; item.firstChild.textContent = option.label; item.jtMenuOption = null; if (option.hidden || (isFullscreen && option.fullScreenHidden) || (!isFullscreen && option.fullScreenOnly)) { item.style.display = "none"; } else { item.style.display = "block"; // Divider? if (option.divider) { item.classList.add("jt-bar-menu-item-divider"); } else { item.classList.remove("jt-bar-menu-item-divider"); h += jt.ScreenGUI.BAR_MENU_ITEM_HEIGHT; // each non-divider item // Toggle item.classList.toggle("jt-bar-menu-item-toggle", option.toggle !== undefined); // Disabled? if (option.disabled) { item.classList.add("jt-bar-menu-item-disabled"); } else { item.classList.remove("jt-bar-menu-item-disabled"); item.jtMenuOption = option; if (option.clickModif === 0) barMenu.jtDefaultItem = item; // If option is the default, set this item to be selected as default // User Generated Gesture needed? item.jtNeedsUIG = option.needsUIG; // Toggle checked if (option.toggle !== undefined) item.classList.toggle("jt-bar-menu-item-toggle-checked", !!option.checked); } } } ++it; } } for (var r = it; r < BAR_MENU_MAX_ITEMS; ++r) { item = barMenu.jtItems[r]; item.firstChild.textContent = ""; item.style.display = "none"; item.jtMenuOption = null; } var height = fsElementCenter.clientHeight - jt.ScreenGUI.BAR_HEIGHT - 12; // bar + borders + tolerance var scale = h < height ? 1 : height / h; if (barMenu) barMenu.style.transform = "scale(" + scale.toFixed(4) + ")"; //console.error("MESSAGE SCALE height: " + height + ", h: " + h); } function hideBarMenu() { if (!barMenuActive) return; barMenuActive = null; barMenu.style.display = "none"; barMenuItemSetActive(null); cursorHideFrameCountdown = CURSOR_HIDE_FRAMES; self.focus(); } function setupBarMenu() { barMenu = document.createElement('div'); barMenu.id = "jt-bar-menu"; var inner = document.createElement('div'); inner.id = "jt-bar-menu-inner"; barMenu.appendChild(inner); var title = document.createElement('div'); title.id = "jt-bar-menu-title"; title.tabIndex = -1; title.innerHTML = "Menu Title"; inner.appendChild(title); barMenu.jtTitle = title; barMenu.jtItems = new Array(BAR_MENU_MAX_ITEMS); for (var i = 0; i < BAR_MENU_MAX_ITEMS; ++i) { var item = document.createElement('div'); item.classList.add("jt-bar-menu-item"); item.style.display = "none"; item.innerHTML = "Menu Item " + i; item.jtBarElementType = 2; // Menu Item item.jtItemIndex = i; item.addEventListener("mouseenter", function (e) { barMenuItemHoverOver(e.target, e); }); item.addEventListener("mouseleave", barMenuItemHoverOut); inner.appendChild(item); barMenu.jtItems[i] = item; } // Block keys and respond to some barMenu.addEventListener("keydown", function(e) { // Hide if (MENU_CLOSE_KEYS[e.keyCode]) hideBarMenu(); // Execute else if (barMenuItemActive && MENU_EXEC_KEYS[e.keyCode & ~KEY_SHIFT_MASK & ~KEY_CTRL_MASK]) barMenuItemFireActive(e.shiftKey, e.ctrlKey); // Select Menu else if (MENU_SELECT_KEYS[e.keyCode]) { if (!barMenuActive) return; var newMenu = (barMenus.length + barMenuActive.jtMenuIndex + MENU_SELECT_KEYS[e.keyCode]) % barMenus.length; showBarMenu(barMenus[newMenu], true); } // Select Item else if (MENU_ITEM_SELECT_KEYS[e.keyCode]) { var items = barMenu.jtItems; var newItem = barMenuItemActive ? barMenuItemActive.jtItemIndex : -1; var tries = BAR_MENU_MAX_ITEMS + 1; do { newItem = (newItem + items.length + MENU_ITEM_SELECT_KEYS[e.keyCode]) % items.length; } while (--tries >= 0 && !items[newItem].jtMenuOption); if (tries >= 0) barMenuItemSetActive(items[newItem]); } return jt.Util.blockEvent(e); }); buttonsBar.appendChild(barMenu); } function closeAllOverlays() { hideBarMenu(); if (saveStateDialog) saveStateDialog.hide(); if (quickOtionsDialog) quickOtionsDialog.hide(); if (netPlayDialog) netPlayDialog.hide(); if (cartFormatDialog) cartFormatDialog.hide(); if (settingsDialog) settingsDialog.hide(); if (recentROMsDialog) recentROMsDialog.hide(); } this.closeAllOverlays = closeAllOverlays; function showLogoMessage(mes, button, higherButton, afterAction) { consolePanel.setLogoMessageActive(true); if (logoMessageActive) return; closeAllOverlays(); if (afterAction) afterMessageAction = afterAction; logoMessageText.innerHTML = mes; logoMessageOK.classList.toggle("jt-higher", !!higherButton); logoMessageOKText.innerHTML = button || "OK"; fsElement.classList.add("jt-logo-message-active"); logoMessageActive = true; signalIsOn = false; updateLogo(); } this.closeLogoMessage = function(e, uigStart, uigEnd) { if (!uigEnd) consoleControls.hapticFeedbackOnTouch(e); if (uigStart) return; consolePanel.setLogoMessageActive(false); fsElement.classList.remove("jt-logo-message-active"); logoMessageActive = false; if (afterMessageAction) { var action = afterMessageAction; afterMessageAction = null; action(); } }; function updateLogoScale() { var width = canvasOuter.clientWidth; var scale = Math.min(width / jt.ScreenGUI.LOGO_SCREEN_WIDTH, 1); if (scale < 1) logoCenter.style.transform = "translate(-50%, -50%) scale(" + scale.toFixed(4) + ")"; else logoCenter.style.transform = "translate(-50%, -50%)"; } function setScrollMessage(state) { console.error("Scroll Message: " + state); fsElement.classList.toggle("jt-scroll-message", state); scrollMessageActive = state; if (state) { setTimeout(function() { setScrollMessage(false); }, 5000); } } function readjustAll(force) { if (isReadjustScreeSizeChanged(force)) { if (isFullscreen) { buttonsBarDesiredWidth = isLandscape ? 0 : -1; var winH = readjustScreenSize.h; if (!isLandscape) winH -= jt.ScreenGUI.BAR_HEIGHT + 2; monitor.displayScale(aspectX, displayOptimalScaleY(readjustScreenSize.w, winH)); } else { buttonsBarDesiredWidth = -1; monitor.displayScale(Javatari.SCREEN_DEFAULT_ASPECT, self.displayDefaultScale()); } self.focus(); consolePanelUpdateForOrientation(); consoleControlsSocket.releaseControllers(); //console.log("READJUST"); } if (readjustInterval && (jt.Util.performanceNow() - readjustRequestTime >= 1000)) { clearInterval(readjustInterval); readjustInterval = null; //console.log("READJUST TERMINATED"); } } function isReadjustScreeSizeChanged(force) { var parW = mainElement.parentElement.clientWidth; var winW = fsElementCenter.clientWidth; var winH = fsElementCenter.clientHeight; if (!force && readjustScreenSize.pw === parW && readjustScreenSize.w === winW && readjustScreenSize.h === winH) return false; readjustScreenSize.pw = parW; readjustScreenSize.w = winW; readjustScreenSize.h = winH; isLandscape = winW > winH; return true; } function displayOptimalScaleY(maxWidth, maxHeight) { var effectiveScaleX = aspectX * 2; // Fixed internal aspectX of 2 var scY = maxHeight / targetHeight; if (targetWidth * effectiveScaleX * scY > maxWidth) scY = maxWidth / (targetWidth * effectiveScaleX); return scY; } function setViewport() { if (!isMobileDevice) return; if (viewPortOriginalContent === undefined) { // store only once! viewPortOriginalTag = document.querySelector("meta[name=viewport]"); viewPortOriginalContent = (viewPortOriginalTag && viewPortOriginalTag.content) || null; } if (!viewportTag) { viewportTag = document.createElement('meta'); viewportTag.name = "viewport"; // Android Firefox bug (as of 11/2016). Going back and forth from full-screen makes scale all wrong. Set user-scalable = yes to let user correct it in full-screen :-( viewportTag.content = "width = device-width, height = device-height, initial-scale = 1.0, minimum-scale = 1.0, maximum-scale = 1.0, user-scalable = yes"; document.head.appendChild(viewportTag); } if (viewPortOriginalTag) try { document.head.removeChild(viewPortOriginalTag); } catch (e) { /* ignore */ } viewPortOriginalTag = null; } function restoreViewport() { if (!isMobileDevice) return; if (!viewPortOriginalTag && viewPortOriginalContent) { viewPortOriginalTag = document.createElement('meta'); viewPortOriginalTag.name = "viewport"; viewPortOriginalTag.content = viewPortOriginalContent; document.head.appendChild(viewPortOriginalTag); } if (viewportTag) try { document.head.removeChild(viewportTag); } catch (e) { /* ignore */ } viewportTag = null; } function setPageVisibilityHandling() { var wasUnpaused; function visibilityChange() { if (logoMessageActive) return; if (document.hidden) { wasUnpaused = !atariConsole.systemPause(true); } else { if (wasUnpaused) atariConsole.systemPause(false); } } document.addEventListener("visibilitychange", visibilityChange); } var afterMessageAction; var atariConsole; var consoleControlsSocket; var monitor; var peripheralControls; var fileLoader; var fileDownloader; var consoleControls; var cartridgeSocket; var stateMedia; var recentROMs; var readjustInterval = 0, readjustRequestTime = 0; var readjustScreenSize = { w: 0, wk: 0, h: 0, pw: 0, l: false }; var isFullscreen = false, isLandscape = false; var isTouchDevice = jt.Util.isTouchDevice(); var isMobileDevice = jt.Util.isMobileDevice(); var isIOSDevice = jt.Util.isIOSDevice(); var isBrowserStandalone = jt.Util.isBrowserStandaloneMode(); var browserName = jt.Util.browserInfo().name; var fullscreenAPIEnterMethod, fullScreenAPIExitMethod, fullScreenAPIQueryProp, fullScreenAPIExitUserRequested = false, fullScreenScrollHack = false; var viewportTag, viewPortOriginalTag, viewPortOriginalContent; var consolePanel; var consolePanelElement; var settingsDialog; var saveStateDialog; var recentROMsDialog; var quickOtionsDialog; var netPlayDialog; var cartFormatDialog; var fsElement, fsElementCenter; var canvas, canvasOuter, canvasLoadingIcon; var canvasContext; var canvasImageRenderingValue; var touchControlsActive = false, touchControlsDirBig = false; var consolePanelActive = false; var consolePanelActiveLandscape = false; var consolePanelActivePortrait = jt.ConsolePanel.shouldStartActive(); var buttonsBar, buttonsBarInner, buttonsBarDesiredWidth = -1; // 0 = same as canvas. -1 means full width mode (100%) var barButtonLongTouchTarget, barButtonLongTouchSelectTimeout; var barMenu; var barMenus = [], barMenuActive, barMenuItemActive, barMenuSystem; var barConsoleControlPressed; var osd; var osdTimeout; var osdShowing = false; var cursorType = "auto"; var cursorShowing = true; var cursorHideFrameCountdown = -1; var signalIsOn = false; var crtFilter = -2, crtFilterEffective = null; var crtMode = -1, crtModeEffective = 0; var debugMode = false; var isLoading = false; var aspectX = Javatari.SCREEN_DEFAULT_ASPECT; var scaleY = 1.0; var mousePointerLocked = false; var targetWidth = 160; var targetHeight = 213; var logo, logoCenter, logoImage, logoMessage, logoMessageText, logoMessageOK, logoMessageOKText, logoMessageActive = false; var logoLoadingIcon; var scrollMessage, scrollMessageActive = false; var unmuteMessage; var powerButton; var netplayButton; var logoButton; var scaleDownButton; var scaleUpButton; var fullscreenButton; var settingsButton; var gameSelectButton; var gameResetButton; var mediaButtonBackYOffsets = [-51, -26, -1]; var CANVAS_SIZE_FACTOR = Javatari.SCREEN_CANVAS_SIZE; var OSD_TIME = 3000; var CURSOR_HIDE_FRAMES = 180; var FULLSCREEN_MODE = Javatari.SCREEN_FULLSCREEN_MODE; var BAR_AUTO_HIDE = Javatari.SCREEN_CONTROL_BAR === 0; var BAR_MENU_MAX_ITEMS = 13; var NARROW_WIDTH = 336; var k = jt.DOMKeys; var KEY_CTRL_MASK = k.CONTROL; var KEY_ALT_MASK = k.ALT; var KEY_SHIFT_MASK = k.SHIFT; var MENU_CLOSE_KEYS = {}; MENU_CLOSE_KEYS[k.VK_ESCAPE.c] = 1; MENU_CLOSE_KEYS[k.VK_CONTEXT.c] = 1; var MENU_EXEC_KEYS = {}; MENU_EXEC_KEYS[k.VK_ENTER.c] = 1; MENU_EXEC_KEYS[k.VK_SPACE.c] = 1; var MENU_SELECT_KEYS = {}; MENU_SELECT_KEYS[k.VK_LEFT.c] = -1; MENU_SELECT_KEYS[k.VK_RIGHT.c] = 1; var MENU_ITEM_SELECT_KEYS = {}; MENU_ITEM_SELECT_KEYS[k.VK_UP.c] = -1; MENU_ITEM_SELECT_KEYS[k.VK_DOWN.c] = 1; init(); this.eval = function(str) { return eval(str); }; }; ================================================ FILE: src/main/room/screen/ConsolePanel.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.ConsolePanel = function(screen, panelElement) { "use strict"; this.connectPeripherals = function(pFileLoader, pConsoleControls, pPeripheralControls) { consoleControls = pConsoleControls; peripheralControls = pPeripheralControls; pFileLoader.registerForDnD(panelElement); }; this.connect = function(pControlsSocket) { controlsSocket = pControlsSocket; }; this.setActive = function(pActive) { active = pActive; if (active) { if (!powerButton) create(); refreshCartridge(); updateVisibleControlsState(); } document.documentElement.classList.toggle("jt-console-panel-active", active); }; this.setLogoMessageActive = function(active) { logoMessageActive = active; }; this.updateScale = function(screenWidth, isFullscreen, isLandscape) { var height = 0, width = 0; if (active) { screenWidth = isFullscreen ? isLandscape ? screenWidth * 0.85 : screenWidth - 36 : screenWidth * 0.85; var scale = Math.min(1, screenWidth / jt.ConsolePanel.DEFAULT_WIDTH); panelElement.style.transform = scale < 1 ? "translateX(-50%) scale(" + scale.toFixed(8) + ")" : "translateX(-50%)"; height = Math.ceil(scale * jt.ConsolePanel.DEFAULT_HEIGHT); width = Math.ceil(scale * jt.ConsolePanel.DEFAULT_WIDTH); } if (consoleControls) consoleControls.getTouchControls().updateConsolePanelSize(screenWidth, width, height, isFullscreen, isLandscape); //console.error("PANEL SCALE: " + scale); return height; }; function create() { setupMain(); setupButtons(); setupCartridgeLabel(); } var refreshControls = function() { // Controls State setVisibility(powerButton, !controlsStateReport[controls.POWER]); setVisibility(colorButton, controlsStateReport[controls.BLACK_WHITE]); setVisibility(selectButton, controlsStateReport[controls.SELECT]); setVisibility(resetButton, controlsStateReport[controls.RESET]); setVisibility(p0DiffButton, controlsStateReport[controls.DIFFICULTY0]); setVisibility(p1DiffButton, controlsStateReport[controls.DIFFICULTY1]); refreshCartridge(); }; var refreshCartridge = function () { // Cartridge Image setVisibility(cartInsertedImage, cartridgeInserted); setVisibility(cartLabel, cartridgeInserted); // Cartridge Label cartLabel.innerHTML = (cartridgeInserted && cartridgeInserted.rom.info.l) || DEFAULT_CARTRIDGE_LABEL; if (cartridgeInserted && cartridgeInserted.rom.info.lc) { var colors = cartridgeInserted.rom.info.lc.trim().split(/\s+/); cartLabel.style.color = colors[0] || DEFAULT_CARTRIDGE_LABEL_COLOR; cartLabel.style.background = colors[1] || DEFAULT_CARTRIDGE_BACK_COLOR; cartLabel.style.borderColor = colors[2] || DEFAULT_CARTRIDGE_BORDER_COLOR; } else { cartLabel.style.color = DEFAULT_CARTRIDGE_LABEL_COLOR; cartLabel.style.background = DEFAULT_CARTRIDGE_BACK_COLOR; cartLabel.style.borderColor = DEFAULT_CARTRIDGE_BORDER_COLOR; } }; var updateVisibleControlsState = function() { controlsSocket.controlsStateReport(controlsStateReport); refreshControls(); }; var setupMain = function () { panelElement.innerHTML = jt.ScreenGUI.htmlConsolePanel; delete jt.ScreenGUI.htmlConsolePanel; if (jt.Util.isMobileDevice()) panelElement.classList.add("jt-hide-labels"); }; var setupButtons = function() { powerButton = document.getElementById("jt-console-panel-power"); consoleControlButton(powerButton, controls.POWER, true); colorButton = document.getElementById("jt-console-panel-color"); consoleControlButton(colorButton, controls.BLACK_WHITE, true); selectButton = document.getElementById("jt-console-panel-select"); consoleControlButton(selectButton, controls.SELECT, true); resetButton = document.getElementById("jt-console-panel-reset"); consoleControlButton(resetButton, controls.RESET, true); p0DiffButton = document.getElementById("jt-console-panel-p0-diff"); consoleControlButton(p0DiffButton, controls.DIFFICULTY0, true); p1DiffButton = document.getElementById("jt-console-panel-p1-diff"); consoleControlButton(p1DiffButton, controls.DIFFICULTY1, true); cartInsertedImage = document.getElementById("jt-console-panel-cart-image"); cartChangeButton = document.getElementById("jt-console-panel-cart-load"); addCartridgeControlButton(cartChangeButton, jt.PeripheralControls.CARTRIDGE_LOAD_RECENT); cartChangeFileButton = document.getElementById("jt-console-panel-cart-file"); cartChangeURLButton = document.getElementById("jt-console-panel-cart-url"); if (!Javatari.CARTRIDGE_CHANGE_DISABLED) { addCartridgeControlButton(cartChangeFileButton, jt.PeripheralControls.CARTRIDGE_LOAD_RECENT); addCartridgeControlButton(cartChangeURLButton, jt.PeripheralControls.AUTO_LOAD_URL); } else { setUnavailable(cartChangeFileButton); setUnavailable(cartChangeURLButton); } }; var consoleControlButton = function (but, control, isHold) { but.jtControl = control; if (isHold) { but.jtPressed = false; jt.Util.addEventsListener(but, "mousedown touchstart", switchPressed); jt.Util.addEventsListener(but, "mouseup touchend touchcancel", switchReleased); jt.Util.addEventsListener(but, "mouseleave", switchLeft); } else jt.Util.onTapOrMouseDown(but, switchPressed); }; function switchPressed(e) { jt.Util.blockEvent(e); if (logoMessageActive) return; consoleControls.hapticFeedbackOnTouch(e); screen.closeAllOverlays(); e.target.jtPressed = true; consoleControls.processControlState(e.target.jtControl, true); } function switchReleased(e) { jt.Util.blockEvent(e); e.target.jtPressed = false; if (logoMessageActive) return; consoleControls.hapticFeedbackOnTouch(e); consoleControls.processControlState(e.target.jtControl, false); } function switchLeft(e) { if (!e.target.jtPressed) return; switchReleased(e); } var addCartridgeControlButton = function (but, control) { but.jtControl = control; but.jtNeedsUIG = true; jt.Util.onTapOrMouseDownWithBlockUIG(but, cartridgeButtonPressed); }; function cartridgeButtonPressed(e, uigStart, uigEnd) { if (!uigEnd) consoleControls.hapticFeedbackOnTouch(e); if (uigStart) return; screen.closeAllOverlays(); peripheralControls.controlActivated(e.target.jtControl); } var setVisibility = function(element, boo) { element.style.opacity = boo ? 1 : 0; }; var setUnavailable = function(element, boo) { element.style.display = "none"; }; var setupCartridgeLabel = function() { // Adjust default colors for the label as per parameters var colors = (Javatari.CARTRIDGE_LABEL_COLORS || "").trim().split(/\s+/); if (colors[0]) DEFAULT_CARTRIDGE_LABEL_COLOR = colors[0]; if (colors[1]) DEFAULT_CARTRIDGE_BACK_COLOR = colors[1]; if (colors[2]) DEFAULT_CARTRIDGE_BORDER_COLOR = colors[2]; cartLabel = document.getElementById("jt-console-panel-cart-label"); addCartridgeControlButton(cartLabel, jt.PeripheralControls.CARTRIDGE_LOAD_RECENT); }; // Controls interface ----------------------------------- var controls = jt.ConsoleControls; this.controlStateChanged = function(control, state) { if (active && visibleControls[control]) updateVisibleControlsState(); }; this.controlsStatesRedefined = function () { if (active) updateVisibleControlsState(); }; // Cartridge interface ------------------------------------ this.cartridgeInserted = function(cartridge) { cartridgeInserted = cartridge; if (active) refreshCartridge(); }; var active = false; var consoleControls; var peripheralControls; var controlsSocket, controlsStateReport = {}; var cartridgeInserted; var logoMessageActive = false; var powerButton; var colorButton; var selectButton; var resetButton; var p0DiffButton; var p1DiffButton; var cartInsertedImage; var cartChangeButton; var cartChangeFileButton; var cartChangeURLButton; var cartLabel; var visibleControls = {}; visibleControls[controls.POWER] = 1; visibleControls[controls.BLACK_WHITE] = 1; visibleControls[controls.SELECT] = 1; visibleControls[controls.RESET] = 1; visibleControls[controls.DIFFICULTY0] = 1; visibleControls[controls.DIFFICULTY1] = 1; var DEFAULT_CARTRIDGE_LABEL = "JAVATARI"; var DEFAULT_CARTRIDGE_LABEL_COLOR = "#fa2525"; var DEFAULT_CARTRIDGE_BACK_COLOR = "#101010"; var DEFAULT_CARTRIDGE_BORDER_COLOR = "transparent"; }; jt.ConsolePanel.DEFAULT_WIDTH = 460; jt.ConsolePanel.DEFAULT_HEIGHT = 134; jt.ConsolePanel.shouldStartActive = function() { // Try some backward compatible means to find if Panel should not be active by default return !Javatari.SCREEN_CONSOLE_PANEL_DISABLED && (Javatari.CONSOLE_PANEL_ELEMENT_ID === -1 || document.getElementById(Javatari.CONSOLE_PANEL_ELEMENT_ID)); }; jt.ConsolePanel.sameBoxShadowAsScreen = function() { var screenElement = document.getElementById(Javatari.SCREEN_ELEMENT_ID); return screenElement ? window.getComputedStyle(screenElement, null).getPropertyValue("box-shadow") : "none"; }; ================================================ FILE: src/main/room/screen/FullScreenSetup.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. JavatariFullScreenSetup = { apply: function fullScreenSetup() { // Setup Basic full-screen CSS if (!this.cssApplied) { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = this.css; document.head.appendChild(style); this.cssApplied = true; } // Apply Standalone mode full-screen basic styles to html and body immediately if needed document.documentElement.classList.toggle("jt-full-screen", this.shouldStartInFullScreen()); }, shouldStartInFullScreen: function () { return window.Javatari ? Javatari.SCREEN_FULLSCREEN_MODE === 1 || (Javatari.SCREEN_FULLSCREEN_MODE === -1 && this.isBrowserStandaloneMode()) : this.isBrowserStandaloneMode(); }, isBrowserStandaloneMode: function () { return navigator.standalone || window.matchMedia("(display-mode: standalone)").matches; }, css: '' + 'html.jt-full-screen, html.jt-full-screen body {' + ' background: black;' + '}' + 'html.jt-full-screen .jt-full-screen-hidden {' + ' display: none;' + '}' + 'html:not(.jt-full-screen) .jt-full-screen-only {' + ' display: none;' + '}' }; JavatariFullScreenSetup.apply(); ================================================ FILE: src/main/room/screen/Monitor.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Monitor = function(display) { "use strict"; var self = this; function init() { prepareResources(); setDisplayDefaultSize(); self.setVideoStandard(videoStandard); } this.connect = function(pVideoSignal) { videoSignal = pVideoSignal; videoSignal.connectMonitor(this); }; this.nextLine = function(pixels, vSynchSignal) { // Process new line received var vSynched = false; if (line < signalHeight) { // Copy to the back buffer only contents that will be displayed if (line >= viewportOriginY && line < viewportOriginY + viewportHeight) backBuffer.set(pixels, (line - viewportOriginY) * signalWidth); } else vSynched = maxLineExceeded(); line++; if (!videoStandardDetected) videoStandardDetectionFrameLineCount++; if (vSynchSignal) { if (!videoStandardDetected) videoStandardDetectionNewFrame(); vSynched |= newFrame(); } return vSynched; }; //this.nextLineNew = function(pixels, vSynchSignal) { // // Process new line received // var frameEnd = false; // if (line < signalHeight) { // // Copy to the back buffer only contents that will be displayed // if (line >= viewportOriginY && line < viewportOriginY + viewportHeight) // backBuffer.set(pixels, (line - viewportOriginY) * signalWidth); // } else // frameEnd = maxLineExceeded(); // line++; // if (!videoStandardDetected) ++videoStandardDetectionFrameLineCount; // if (vSynchActive ^ vSynchSignal) { // vSynchActive = vSynchSignal; // if (!vSynchSignal) { // if (!videoStandardDetected) videoStandardDetectionNewFrame(); // return newFrame(); // } // } // return frameEnd; //}; var newFrame = function() { if (line < minLinesToSync) return false; if (showInfo) display.showOSD(videoStandard.name + " " + line + " lines" /* , CRT mode: " + crtModeNames[crtMode] */, true); // Start a new frame line = 0; frame++; return true; }; var maxLineExceeded = function() { if (line > maxLinesToSync) { //if (debug > 0) Util.log("Display maximum scanlines exceeded: " + line); return newFrame(); } else return false; }; this.setVideoStandard = function(standard) { videoStandard = standard; signalWidth = standard.totalWidth; signalHeight = standard.totalHeight; minLinesToSync = signalHeight - VSYNC_TOLERANCE; maxLinesToSync = signalHeight + VSYNC_TOLERANCE + EXTRA_UPPER_VSYNC_TOLERANCE; if (isDefaultViewport) { viewportHeightPct = videoStandard.defaultHeightPct; viewportOriginYPct = videoStandard.defaultOriginYPct; } setViewportSize(viewportWidth, viewportHeightPct); setViewportOrigin(viewportOriginX, viewportOriginYPct); }; var videoStandardDetectionNewFrame = function() { var linesCount = videoStandardDetectionFrameLineCount; videoStandardDetectionFrameLineCount = 0; // Only consider frames with linesCount in range with tolerances (NTSC 262, PAL 312) if ((linesCount >= 250 && linesCount <= 281) || (linesCount >= 300 && linesCount <= 325)) if (++videoStandardDetectionFrameCount >= 5) videoStandardDetectionFinish(linesCount); }; var videoStandardDetectionFinish = function(linesCount) { videoStandardDetected = linesCount < 290 ? jt.VideoStandard.NTSC : jt.VideoStandard.PAL; // Compute an additional number of lines to make the display bigger, if needed // Only used when the detected number of lines per frame is bigger than standard by a reasonable amount var prevAdd = videoStandardDetectionAdtLinesPerFrame; var newAdd = linesCount - videoStandardDetected.totalHeight; if (newAdd > 2) newAdd = (newAdd > 6 ? 6 : newAdd) - 2; else newAdd = 0; // Only sets size now if additional lines changed if (newAdd != prevAdd) { videoStandardDetectionAdtLinesPerFrame = newAdd; self.setVideoStandard(videoStandardDetected); } }; this.videoSignalOff = function() { line = 0; display.videoSignalOff(); }; var setViewportOrigin = function(x, yPct) { viewportOriginX = x; if (viewportOriginX < 0) viewportOriginX = 0; else if (viewportOriginX > signalWidth - viewportWidth) viewportOriginX = signalWidth - viewportWidth; viewportOriginYPct = yPct; if (viewportOriginYPct < 0) viewportOriginYPct = 0; else if ((viewportOriginYPct / 100 * signalHeight) > signalHeight - viewportHeight) viewportOriginYPct = (signalHeight - viewportHeight) / signalHeight * 100; // Compute final display originY, adding a little for additional lines as discovered in last video standard detection var adtOriginY = videoStandardDetectionAdtLinesPerFrame / 2; viewportOriginY = ((viewportOriginYPct / 100 * signalHeight) + adtOriginY) | 0; if ((viewportOriginY + viewportHeight) > signalHeight) viewportOriginY = signalHeight - viewportHeight; }; var setViewportSize = function(width, heightPct) { viewportWidth = width; if (viewportWidth < 10) viewportWidth = 10; else if (viewportWidth > signalWidth) viewportWidth = signalWidth; viewportHeightPct = heightPct; if (viewportHeightPct < 10) viewportHeightPct = 10; else if (viewportHeightPct > 100) viewportHeightPct = 100; // Compute final display height, considering additional lines as discovered in last video standard detection viewportHeight = (viewportHeightPct / 100 * (signalHeight + videoStandardDetectionAdtLinesPerFrame)) | 0; if (viewportHeight > signalHeight) viewportHeight = signalHeight; offCanvas.width = viewportWidth; offCanvas.height = viewportHeight; setViewportOrigin(viewportOriginX, viewportOriginYPct); displayUpdateSize(); }; var displayUpdateSize = function() { if (!display) return; display.displayMetrics(viewportWidth, viewportHeight); }; var setDisplayDefaultSize = function() { isDefaultViewport = true; viewportOriginX = DEFAULT_ORIGIN_X; viewportOriginYPct = videoStandard.defaultOriginYPct; setViewportSize(DEFAULT_WIDTH, videoStandard.defaultHeightPct); }; var prepareResources = function() { offCanvas = document.createElement('canvas'); offCanvas.width = DEFAULT_WIDTH; offCanvas.height = DEFAULT_HEIGHT; offContext = offCanvas.getContext("2d", { alpha: false, antialias: false }); offContext.globalCompositeOperation = "copy"; offContext.globalAlpha = 1; offImageData = offContext.createImageData(jt.VideoStandard.PAL.totalWidth, jt.VideoStandard.PAL.totalHeight); backBuffer = new Uint32Array(offImageData.data.buffer); }; this.currentLine = function() { return line; }; this.refresh = function() { // First paint the offscreen canvas with new frame data offContext.putImageData(offImageData, -viewportOriginX, 0, viewportOriginX, 0, viewportWidth, viewportHeight); // Then refresh display with the new image (canvas) and correct dimensions display.refresh(offCanvas, viewportWidth, viewportHeight); //if (debug > 0) cleanBackBuffer(); }; this.videoStandardDetectionStart = function() { videoStandardDetected = null; videoStandardDetectionFrameCount = 0; videoStandardDetectionFrameLineCount = 0; }; this.getVideoStandardDetected = function() { return videoStandardDetected; }; this.toggleShowInfo = function() { showInfo = !showInfo; if (!showInfo) display.showOSD(null, true); }; this.signalOff = function() { display.videoSignalOff(); }; this.showOSD = function(message, overlap, error) { display.showOSD(message, overlap, error); }; this.setDefaults = function() { setDisplayDefaultSize(); display.crtModeSetDefault(); display.crtFilterSetDefault(); display.requestReadjust(true); }; this.setDebugMode = function(boo) { display.setDebugMode(boo); }; this.crtModeToggle = function() { display.crtModeToggle(); }; this.crtFilterToggle = function() { display.crtFilterToggle(); }; this.fullscreenToggle = function() { display.displayToggleFullscreen(); }; this.displayAspectDecrease = function() { this.displayScale(normalizeAspectX(displayAspectX - SCALE_STEP), displayScaleY); this.showOSD("Display Aspect: " + displayAspectX.toFixed(2) + "x", true); }; this.displayAspectIncrease = function() { this.displayScale(normalizeAspectX(displayAspectX + SCALE_STEP), displayScaleY); this.showOSD("Display Aspect: " + displayAspectX.toFixed(2) + "x", true); }; this.displayScaleDecrease = function() { this.displayScale(displayAspectX, normalizeScaleY(displayScaleY - SCALE_STEP)); this.showOSD("Display Size: " + displayScaleY.toFixed(2) + "x", true); }; this.displayScaleIncrease = function() { this.displayScale(displayAspectX, normalizeScaleY(displayScaleY + SCALE_STEP)); this.showOSD("Display Size: " + displayScaleY.toFixed(2) + "x", true); }; this.viewportOriginDecrease = function() { isDefaultViewport = false; setViewportOrigin(viewportOriginX, viewportOriginYPct + ORIGIN_Y_STEP); this.showOSD("Viewport Origin: " + viewportOriginY, true); }; this.viewportOriginIncrease = function() { isDefaultViewport = false; setViewportOrigin(viewportOriginX, viewportOriginYPct - ORIGIN_Y_STEP); this.showOSD("Viewport Origin: " + viewportOriginY, true); }; this.viewportSizeDecrease = function() { setDisplayDefaultSize(); this.showOSD("Viewport Size: Standard", true); }; this.viewportSizeIncrease = function() { isDefaultViewport = false; setViewportSize(signalWidth, 100); this.showOSD("Viewport Size: Full Signal", true); }; this.displayScale = function(aspectX, scaleY) { displayAspectX = aspectX; displayScaleY = scaleY; display.displayScale(displayAspectX, displayScaleY); }; function normalizeAspectX(aspectX) { var ret = aspectX < 0.5 ? 0.5 : aspectX > 2.5 ? 2.5 : aspectX; return Math.round(ret * 10) / 10; } function normalizeScaleY(scaleY) { var ret = scaleY < 0.5 ? 0.5 : scaleY; return Math.round(ret * 10) / 10; } this.controlStateChanged = function(control, state) { display.controlStateChanged(control, state); }; this.controlsStatesRedefined = function() { display.controlsStatesRedefined(); }; this.consolePowerAndUserPauseStateUpdate = function(power, paused) { display.consolePowerAndUserPauseStateUpdate(power, paused); }; this.cartridgeInserted = function(cart) { display.cartridgeInserted(cart); }; var offCanvas; var offContext; var offImageData; var backBuffer; var videoSignal; var signalWidth; var signalHeight; var videoStandard = jt.VideoStandard.NTSC; var minLinesToSync; var maxLinesToSync; var line = 0; var frame = 0; var viewportWidth; var viewportHeight; var viewportHeightPct; var viewportOriginX; var viewportOriginY; var viewportOriginYPct; var isDefaultViewport = true; var displayAspectX; var displayScaleY; var videoStandardDetected; var videoStandardDetectionFrameCount; var videoStandardDetectionFrameLineCount = 0; var videoStandardDetectionAdtLinesPerFrame = 0; var showInfo = false; var DEFAULT_WIDTH = 160; var DEFAULT_HEIGHT = 213; var DEFAULT_ORIGIN_X = 68; var VSYNC_TOLERANCE = 16; var EXTRA_UPPER_VSYNC_TOLERANCE = 5; var SCALE_STEP = 0.1; var ORIGIN_Y_STEP = 0.4; init(); }; ================================================ FILE: src/main/room/screen/ScreenGUI.es5.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.ScreenGUI = jt.Util.isMobileDevice() ? { BAR_HEIGHT: 29, BAR_MENU_WIDTH: 150, BAR_MENU_ITEM_HEIGHT: 33, BAR_MENU_ITEM_FONT_SIZE: 14, LOGO_SCREEN_WIDTH: 618, LOGO_SCREEN_HEIGHT: 455, TOUCH_CONTROLS_LEFT_WIDTH: 119, TOUCH_CONTROLS_LEFT_WIDTH_BIG: 143, TOUCH_CONTROLS_RIGHT_WIDTH: 80 } : { BAR_HEIGHT: 29, BAR_MENU_WIDTH: 140, BAR_MENU_ITEM_HEIGHT: 29, BAR_MENU_ITEM_FONT_SIZE: 13, LOGO_SCREEN_WIDTH: 618, LOGO_SCREEN_HEIGHT: 455, TOUCH_CONTROLS_LEFT_WIDTH: 119, TOUCH_CONTROLS_LEFT_WIDTH_BIG: 143, TOUCH_CONTROLS_RIGHT_WIDTH: 80 }; jt.ScreenGUI.html = function() { return '
Swipe up/down on the Screen
to hide the browser bars!
'; }; jt.ScreenGUI.htmlConsolePanel = '
' ; jt.ScreenGUI.css = function() { return 'html.jt-full-screen-scroll-hack body { position: absolute; width: 100%; height: ' + Math.max(1280, (Math.max(screen.width, screen.height) * 1.4) | 0) + 'px; top: 0; left: 0; margin: 0; padding: 0; border: none; overflow-x: hidden; overflow-y: auto; } #jt-screen-fs, #jt-screen-fs div, #jt-screen-fs canvas { outline: none; } #' + Javatari.SCREEN_ELEMENT_ID + ' { display: inline-block; visibility: hidden; font-family: sans-serif; font-weight: normal; margin: 0; padding: 0; border: 1px solid black; background: black; overflow: visible; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; touch-callout: none; -webkit-tap-highlight-color: transparent; tap-highlight-color: transparent; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; } html.jt-full-screen #' + Javatari.SCREEN_ELEMENT_ID + ' { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; box-shadow: none; z-index: 2147483646; /* one behind fsElement */ } html.jt-started #' + Javatari.SCREEN_ELEMENT_ID + ' { visibility: visible; } #jt-screen-scroll-message { position: absolute; bottom: 150%; left: 50%; height: 0; width: 0; margin: 0; padding: 0; font-size: 16px; line-height: 28px; white-space: nowrap; color: hsl(0, 0%, 4%); background: hsl(0, 0%, 92%); border-radius: 15px; transform: translate(-50%, 0); box-shadow: 2px 2px 9px rgba(0, 0, 0, 0.7); transition: all 1.7s step-end, opacity 1.6s linear; overflow: hidden; opacity: 0; z-index: -1; } html.jt-full-screen-scroll-hack #jt-screen-fs.jt-scroll-message #jt-screen-scroll-message { opacity: 1; bottom: 23%; width: 215px; height: 56px; padding: 13px 20px; z-index: 60; transition: none; } #jt-screen-fs { position: relative; background: black; text-align: center; -webkit-tap-highlight-color: rgba(0,0,0,0); tap-highlight-color: rgba(0,0,0,0) } html.jt-full-screen #jt-screen-fs { position: absolute; width: 100%; height: 100%; left: 0; bottom: 0; right: 0; z-index: 2147483647; } html.jt-full-screen-scroll-hack #jt-screen-fs { position: fixed; bottom: 0; height: 100vh; } html.jt-full-screen #jt-screen-fs-center { /* Used to center and move things horizontally in Landscape Full Screen */ position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #jt-screen-canvas-outer { display: inline-block; position: relative; overflow: hidden; vertical-align: top; line-height: 1px; z-index: 3; } #jt-screen-canvas { display: block; } #jt-bar { position: relative; left: 0; right: 0; height: ' + this.BAR_HEIGHT + 'px; margin: 0 auto; border-top: 1px solid black; background: hsl(0, 0%, 16%); overflow: visible; /* for the Menu to show through */ box-sizing: content-box; z-index: 40; } #jt-bar-inner { position: absolute; overflow: hidden; top: 0; bottom: 0; left: 0; right: 0; text-align: left; } html.jt-bar-auto-hide #jt-bar, html.jt-full-screen #jt-bar { position: absolute; bottom: 0; transition: height 0.08s ease-in-out; } html.jt-bar-auto-hide #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } @media only screen and (orientation: landscape) { html.jt-full-screen #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } } #jt-bar.jt-narrow .jt-narrow-hidden { display: none; } .jt-bar-button { display: inline-block; width: 24px; height: 28px; margin: 0 1px; background-image: url("' + jt.Images.urls.iconSprites + '"); background-repeat: no-repeat; background-size: 264px 82px; cursor: pointer; } /* Firefox-specific rules */ @-moz-document url-prefix() { .jt-bar-button { image-rendering: optimizequality; } } /* .jt-bar-button { border: 1px solid yellow; background-origin: border-box; box-sizing: border-box; } */ #jt-bar-power { margin: 0 3px 0 6px; } #jt-bar-netplay.jt-hidden { display: none; } #jt-bar-select { margin: 0 2px 0 9px; width: 50px; } #jt-bar-reset { margin: 0 2px; width: 50px; } html.jt-console-panel-active #jt-bar-select, html.jt-console-panel-active #jt-bar-reset { display: none; } #jt-bar-settings, #jt-bar-full-screen, #jt-bar-scale-plus, #jt-bar-scale-minus { float: right; margin: 0; } #jt-bar-settings { margin-right: 5px; } #jt-bar-full-screen.jt-mobile { margin: 0 6px; } #jt-bar-scale-plus { width: 21px; } #jt-bar-scale-minus { width: 18px; } #jt-bar-text { float: right; width: 32px; } #jt-bar-text.jt-mobile { margin: 0 0 0 6px; } #jt-bar-console-panel { position: absolute; left: 2px; right: 0; width: 39px; margin: 0 auto; } #jt-bar.jt-narrow #jt-bar-console-panel { position: static; float: right; margin-right: 3px; } #jt-bar-logo { position: absolute; left: 0; right: 0; width: 34px; margin: 0 auto; } html:not(.jt-console-panel-active) #jt-bar.jt-narrow #jt-bar-logo { display: none; } #jt-bar-menu { position: absolute; display: none; bottom: ' + this.BAR_HEIGHT + 'px; font-size: ' + this.BAR_MENU_ITEM_FONT_SIZE + 'px; line-height: 1px; overflow: hidden; transform-origin: bottom center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-bar-menu-inner { display: inline-block; padding-bottom: 2px; border: 1px solid black; background: hsl(0, 0%, 16%); } .jt-bar-menu-item, #jt-bar-menu-title { position: relative; display: none; width: ' + this.BAR_MENU_WIDTH + 'px; height: ' + this.BAR_MENU_ITEM_HEIGHT + 'px; color: rgb(205, 205, 205); border: none; padding: 0; line-height: ' + this.BAR_MENU_ITEM_HEIGHT + 'px; text-shadow: 1px 1px 1px black; background: transparent; outline: none; overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden; cursor: pointer; box-sizing: border-box; } #jt-bar-menu-title { display: block; color: white; font-weight: bold; border-bottom: 1px solid black; margin-bottom: 1px; text-align: center; background: rgb(70, 70, 70); cursor: auto; } .jt-bar-menu-item.jt-hover:not(.jt-bar-menu-item-disabled):not(.jt-bar-menu-item-divider) { color: white; background: hsl(358, 67%, 46%); } .jt-bar-menu-item-disabled { color: rgb(110, 110, 110); } .jt-bar-menu-item-divider { height: 1px; margin: 1px 0; background: black; } .jt-bar-menu-item-toggle { text-align: left; padding-left: 30px; } .jt-bar-menu-item-toggle::after { content: ""; position: absolute; width: 6px; height: 19px; top: ' + (((this.BAR_MENU_ITEM_HEIGHT - 21) / 2) | 0) + 'px; left: 10px; background: rgb(70, 70, 70); box-shadow: black 1px 1px 1px; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked { color: white; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked::after { background: rgb(248, 33, 28); } #jt-console-panel { display: none; position: absolute; bottom: -' + (jt.ConsolePanel.DEFAULT_HEIGHT + 2) + 'px; left: 50%; transform: translate(-50%, 0); transform-origin: center top; margin: 0 auto; border: 1px solid black; z-index: 30; } html.jt-console-panel-active #jt-console-panel { display: block; } html.jt-full-screen #jt-console-panel { bottom: ' + (jt.ScreenGUI.BAR_HEIGHT + 2) + 'px; border: none; transform-origin: center bottom; } .jt-select-dialog { position: absolute; overflow: hidden; display: none; top: 0; bottom: 0; left: 0; right: 0; width: 540px; max-width: 92%; height: 297px; margin: auto; color: white; font-size: 18px; line-height: 21px; background: hsl(0, 0%, 16%); padding: 11px 0 0; text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } .jt-select-dialog.jt-show { display: block; } .jt-select-dialog > .jt-footer { position: absolute; width: 100%; bottom: 7px; font-size: 13px; text-align: center; color: rgb(170, 170, 170); } .jt-select-dialog > ul { position: relative; width: 88%; top: 5px; margin: auto; padding: 0; list-style: none; font-size: 14px; color: hsl(0, 0%, 88%); } .jt-select-dialog > ul li { display: none; position: relative; overflow: hidden; height: 26px; background: rgb(70, 70, 70); margin: 7px 0; padding: 11px 10px 0 18px; /* Space on the left for the toggle mark for all lines */ line-height: 0; text-align: left; text-overflow: ellipsis; border: 2px dashed transparent; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); white-space: nowrap; box-sizing: border-box; cursor: pointer; } .jt-select-dialog > ul li.jt-visible { display: block; } .jt-select-dialog > ul li.jt-selected { color: white; background: hsl(358, 67%, 46%); } .jt-select-dialog > ul li.jt-droptarget { color: white; border-color: lightgray; } .jt-select-dialog > ul li.jt-toggle::after { content: ""; position: absolute; width: 6px; height: 17px; top: 2px; left: 6px; background: rgb(60, 60, 60); box-shadow: black 1px 1px 1px; } .jt-select-dialog > ul li.jt-toggle-checked::after { background: rgb(248, 33, 28); } #jt-cartridge-format.jt-select-dialog > ul { width: 100%; height: 226px; margin: 7px auto 0; padding: 0 0 0 30px; overflow-y: auto; box-sizing: border-box; } #jt-cartridge-format.jt-select-dialog > ul li { width: 280px; margin: 7px 0 2px 0; } #jt-cartridge-format.jt-select-dialog > ul li:first-child { margin-top: 0; } #jt-cartridge-format ::-webkit-scrollbar { width: 12px; } #jt-cartridge-format ::-webkit-scrollbar-track { background: transparent; } #jt-cartridge-format ::-webkit-scrollbar-thumb { border: solid transparent; border-width: 1px 1px 1px 2px; background: rgb(80, 80, 80); background-clip: content-box; } #jt-cartridge-format ul.jt-quick-options-list { width: 230px; margin: 18px 0 0 52px; } #jt-cartridge-format ul.jt-quick-options-list li div { height: 24px; line-height: 24px; } #jt-cartridge-format .jt-control { width: 60px; line-height: 24px; } /* Firefox-specific rules */ @-moz-document url-prefix() { /* Try to hide scrollbar, since we cant style it :-( */ #jt-cartridge-format.jt-select-dialog > ul { width: 304px; } } #jt-logo { position: absolute; display: none; top: 0; bottom: 0; left: 0; right: 0; background: black; } #jt-logo.jt-show { display: block; } #jt-logo-center { position: absolute; top: 50%; left: 50%; width: 598px; height: 456px; transform: translate(-50%, -50%); } #jt-logo-image { position: absolute; top: 50%; left: 50%; width: 335px; max-width: 57%; transform: translate(-50%, -50%); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-image { top: 128px; width: 37%; max-width: initial; } #jt-logo-loading-icon, #jt-canvas-loading-icon { display: none; position: absolute; top: 79%; left: 0; right: 0; width: 14%; height: 3%; margin: 0 auto; background-color: rgba(0, 0, 0, .8); border: solid transparent; border-width: 8px 30px; border-radius: 3px; box-sizing: content-box; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-loading-icon { top: 204px; } #jt-unmute-message { display: none; position: absolute; left: 50%; bottom: 5px; height: 30px; padding: 0 10px; margin: 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; font-size: 15px; line-height: 30px; color: rgb(210, 210, 210); background: rgba(0, 0, 0, 0.7); transform-origin: bottom center; transform: translate(-50%, 0); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-unmute-message::before { content: ""; display: inline-block; width: 24px; height: 20px; margin: 5px 9px 0 0; background-image: url("' + jt.Images.urls.muteIcon + '"); background-repeat: no-repeat; background-size: 24px 20px; vertical-align: top; } #jt-unmute-message::after { content: "Audio is muted. Click to unmute"; } #jt-unmute-message.jt-show { display: inline-block; } #jt-logo-message { display: none; position: absolute; top: 226px; width: 100%; color: hsl(0, 0%, 97%); font-size: 29px; line-height: 34px; } #jt-screen-fs.jt-logo-message-active #jt-logo-message { display: block; } #jt-logo-message-ok { display: block; position: absolute; top: 91px; left: 193px; width: 214px; height: 130px; } #jt-logo-message-ok.jt-higher { top: 74px; } #jt-logo-message-ok-text { position: absolute; top: 49%; left: 50%; width: 120px; height: 47px; font-size: 23px; line-height: 47px; background: hsl(358, 67%, 46%); border-radius: 6px; color: white; transform: translate(-50%, -50%); } #jt-osd { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: -29px; right: 16px; height: 29px; padding: 0 12px; margin: 0; font-weight: bold; font-size: 15px; line-height: 29px; color: rgb(0, 255, 0); background: rgba(0, 0, 0, 0.7); transform-origin: top right; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; opacity: 0; } .jt-arrow-up, .jt-arrow-down, .jt-arrow-left, .jt-arrow-right { border: 0px solid transparent; box-sizing: border-box; } .jt-arrow-up { border-bottom-color: inherit; } .jt-arrow-down { border-top-color: inherit; } .jt-arrow-left { border-right-color: inherit; } .jt-arrow-right { border-left-color: inherit; } .jt-quick-options-list { margin-top: 12px; padding: 0; list-style: none; color: hsl(0, 0%, 88%); } .jt-quick-options-list li { margin-top: 8px; line-height: 1px; text-align: left; } .jt-quick-options-list li div { display: inline-block; overflow: hidden; height: 26px; font-size: 14px; line-height: 26px; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; } .jt-quick-options-list .jt-control { float: right; width: 86px; font-size: 15px; line-height: 25px; color: hsl(0, 0%, 70%); background: black; text-align: center; cursor: pointer; } .jt-quick-options-list .jt-control.jt-selected { color: white; background: hsl(358, 67%, 46%); box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); } .jt-quick-options-list .jt-control.jt-selected.jt-inactive { line-height: 21px; border: 2px dashed hsl(358, 67%, 46%); background: black; } #jt-quick-options { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 233px; height: 345px; margin: auto; padding: 11px 14px 0; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-quick-options.jt-show { display: block; } #jt-quick-options::before { content: "Quick Options"; display: block; } #jt-netplay { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 390px; height: 220px; margin: auto; padding-top: 11px; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform-origin: left center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-netplay.jt-show { display: block; } #jt-netplay::before { content: "Net Play!"; display: block; } #jt-netplay-status-box { position: relative; margin-top: 17px; } #jt-netplay-status { display: inline-block; position: relative; width: 340px; font-size: 15px; line-height: 27px; background: black; vertical-align: top; text-shadow: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; box-sizing: border-box; cursor: auto; } #jt-netplay-status-box.jt-active #jt-netplay-status { padding: 0 16px 0 12px; } #jt-netplay-status-box.jt-active #jt-netplay-status::after { content: ""; position: absolute; width: 6px; height: 18px; top: 4px; left: 7px; background: rgb(248, 33, 28); } #jt-netplay-link { display: none; position: absolute; right: 25px; top: 0; width: 26px; height: 27px; color: white; font-size: 15px; font-weight: 600; line-height: 27px; text-decoration: none; background: black; text-align: center; } #jt-netplay-link:hover { background: hsl(358, 67%, 46%); cursor: pointer; } #jt-netplay-status-box.jt-active #jt-netplay-link { display: block; } .jt-netplay-button { display: inline-block; width: 86px; padding: 0; margin: 0; font-size: 15px; line-height: 26px; color: white; background: hsl(358, 67%, 46%); text-shadow: 1px 1px 1px black; border: none; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); cursor: pointer; } #jt-netplay-session-box { margin-top: 18px; } #jt-netplay-session-label, #jt-netplay-nick-label { font-size: 15px; margin-bottom: 4px; } #jt-netplay-session-label::before { content: "Session Name"; } #jt-netplay-session-box input { width: 150px; height: 26px; padding: 0 10px; margin: 0 8px; font-size: 15px; line-height: 26px; background: rgb(240, 240, 240); border: none; border-radius: 0; box-sizing: border-box; outline: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; cursor: auto; } #jt-netplay-nick-label { margin-top: 10px; } #jt-netplay-nick-label::before { content: "User Nickname"; } .jt-netplay-button:disabled { color: rgb(130, 130, 130); background: rgb(70, 70, 70); cursor: default; } #jt-netplay input:disabled { color: black; background: rgb(180, 180, 180); cursor: default; } #jt-netplay-session-box.jt-disabled div { color: rgb(130, 130, 130); } input#jt-netplay-link-text { position: absolute; top: 8px; left: 50px; width: 1px; height: 1px; padding: 0; margin: 0; border: none; color: transparent; background: transparent; opacity: 0; z-index: -10; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } #jt-touch-left, #jt-touch-right, #jt-touch-speed { display: none; position: absolute; z-index: 1; } html.jt-full-screen.jt-touch-active #jt-touch-left, html.jt-full-screen.jt-touch-active #jt-touch-right, html.jt-full-screen.jt-touch-active #jt-touch-speed { display: block; } .jt-touch-dir { width: 130px; height: 130px; color: hsl(0, 0%, 75%); border-radius: 100%; } .jt-touch-dir::before { content: ""; position: absolute; top: 14px; left: 14px; right: 14px; bottom: 14px; border: 1px solid hsl(0, 0%, 26%); border-radius: 100%; } .jt-touch-dir-joy .jt-touch-dir-up, .jt-touch-dir-joy .jt-touch-dir-left { position: absolute; background: hsl(0, 0%, 31%); border-radius: 2px 2px 0 0; box-shadow: inset 1px 2px 0px hsl(0, 0%, 43%), inset -1px -1px hsl(0, 0%, 19%), 0 3px 0 1px hsl(0, 0%, 21%); } .jt-touch-dir-joy .jt-touch-dir-up { width: 26px; height: 78px; top: 24px; left: 52px; } .jt-touch-dir-joy .jt-touch-dir-left { width: 78px; height: 25px; top: 51px; left: 26px; } .jt-touch-dir-joy .jt-touch-dir-left::before { content: ""; position: absolute; top: 2px; left: 23px; width: 33px; height: 22px; background: inherit; z-index: 1; } .jt-touch-dir-joy .jt-touch-dir-left::after { content: ""; position: absolute; top: 4px; left: 30px; height: 17px; width: 17px; border-radius: 100%; box-shadow: inset 0 0 2px hsl(0, 0%, 22%), inset 1px 2px 3px 1px hsl(0, 0%, 26%), inset -1px -2px 1px hsl(0, 0%, 64%); z-index: 2; } .jt-touch-dir .jt-arrow-up, .jt-touch-dir .jt-arrow-down, .jt-touch-dir .jt-arrow-left, .jt-touch-dir .jt-arrow-right { position: absolute; border-width: 5px; z-index: 2; } .jt-touch-dir .jt-arrow-up { top: 26px; left: 60px; border-bottom-width: 11px; } .jt-touch-dir .jt-arrow-down { bottom: 29px; left: 60px; border-top-width: 11px; } .jt-touch-dir .jt-arrow-left { top: 58px; left: 26px; border-right-width: 11px; } .jt-touch-dir .jt-arrow-right { top: 58px; right: 26px; border-left-width: 11px; } .jt-touch-button { position: relative; display: block; width: 72px; height: 72px; font-size: 20px; line-height: 67px; color: hsl(0, 0%, 79%); border-radius: 100%; cursor: default; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; z-index: 0; } .jt-touch-button::before { content: ""; position: absolute; box-sizing: border-box; z-index: -1; } .jt-touch-button-joy::before, .jt-touch-button-none::before { width: 50px; height: 48px; top: 9px; left: 11px; border-radius: 100%; } #jt-screen-fs.jt-touch-config-active .jt-touch-button-none::before { border: 2px solid hsl(0, 0%, 30%); } .jt-touch-button-joy.jt-touch-button-joy-button::before { border: none; background: hsl(1, 70%, 37%); box-shadow: inset -2px -7px 3px 1px hsl(1, 68%, 43%), inset 0px 0px 1px 9px hsl(1, 72%, 33%), 0px -1px 0px 1px hsl(1, 70%, 47%), 0px 1px 0px 2px hsl(1, 70%, 29%); } .jt-touch-button-joy.jt-touch-button-joy-buttonT::before { border: none; background: hsl(220, 72%, 39%); box-shadow: inset -2px -7px 3px 1px hsl(220, 70%, 43%), inset 0px 0px 1px 9px hsl(220, 75%, 34%), 0px -1px 0px 1px hsl(220, 72%, 50%), 0px 1px 0px 2px hsl(220, 72%, 28%); } #jt-touch-button { z-index: 7 } #jt-touch-buttonT { z-index: 6 } #jt-touch-speed.jt-center { width: 84px; left: 0; right: 0; margin: 0 auto; } #jt-touch-speed.jt-center.jt-poweroff #jt-touch-pause { margin-left: 21px } #jt-touch-pause, #jt-touch-fast { float: left; width: 42px; height: 42px; border-color: hsl(0, 0%, 70%); } #jt-touch-pause::after, #jt-touch-fast::before, #jt-touch-fast::after { content: ""; display: inline-block; border: 0 solid transparent; box-sizing: border-box; } #jt-touch-pause::after { margin-top: 14px; width: 13px; height: 14px; border-width: 0; border-left-width: 4px; border-left-color: inherit; border-right-width: 4px; border-right-color: inherit; } #jt-touch-fast::before, #jt-touch-fast::after { margin-top: 14px; width: 11px; height: 14px; border-width: 7px; border-left-width: 11px; border-left-color: inherit; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-pause::after, #jt-touch-speed.jt-poweroff #jt-touch-pause::after { margin: 12px 0 0 3px; width: 15px; height: 18x; border-width: 9px; border-left-width: 15px; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-fast::after { width: 7px; border-width: 0; border-left-width: 3px; } #jt-touch-speed.jt-poweroff #jt-touch-fast { display: none; } .jt-console-panel { width:' + jt.ConsolePanel.DEFAULT_WIDTH + 'px; height:' + jt.ConsolePanel.DEFAULT_HEIGHT + 'px; background: black url("' + jt.Images.urls.panel + '") no-repeat; background-size: 460px 134px; box-shadow: ' + jt.ConsolePanel.sameBoxShadowAsScreen() + '; outline: none; } html.jt-full-screen .jt-console-panel { box-shadow: none; } .jt-console-panel-icon { position: absolute; background: url("' + jt.Images.urls.iconSprites + '") center no-repeat; background-size: 264px 82px; } .jt-console-panel-switch { position: absolute; bottom: 107px; width: 50px; height: 26px; opacity: 0; cursor: pointer; } .jt-console-panel-switch:after { content: ""; position: absolute; left: 11px; bottom: 5px; width: 27px; height: 16px; background: url("' + jt.Images.urls.panelSprites + '") center no-repeat; background-size: 256px 93px; } .jt-console-panel-lever { position: absolute; bottom: 30px; width: 44px; height: 72px; cursor: pointer; } .jt-console-panel-lever:after { content: ""; position: absolute; left: 12px; bottom: 8px; width: 20px; height: 46px; background: url("' + jt.Images.urls.panelSprites + '") center no-repeat; background-size: 256px 93px; } .jt-console-panel-power { left: 19px; } .jt-console-panel-power:after { background-position: 0px 0px; } .jt-console-panel-color { left: 84px; } .jt-console-panel-color:after { background-position: -21px 0px; } .jt-console-panel-select { left: 340px; } .jt-console-panel-select:after { background-position: 0px -47px; } .jt-console-panel-reset { left: 403px; } .jt-console-panel-reset:after { background-position: -21px -47px; } .jt-console-panel-p0-diff { left: 152px; } .jt-console-panel-p0-diff:after { background-position: -229px -17px; } .jt-console-panel-p1-diff { left: 265px; } .jt-console-panel-p1-diff:after { background-position: -229px 0px; } .jt-console-panel-cart-image { position: absolute; left: 140px; bottom: 9px; width: 186px; height: 82px; background: url("' + jt.Images.urls.panelSprites + '") center no-repeat; background-size: 256px 93px; background-position: -42px 0px; } .jt-console-panel-cart-load { position: absolute; left: 141px; bottom: 36px; width: 184px; height: 55px; cursor: pointer; } .jt-console-panel-cart-file { left: 170px; bottom: 3px; width: 31px; height: 30px; background-position: -132px -6px; cursor: pointer; } .jt-console-panel-cart-url { left: 266px; bottom: 3px; width: 31px; height: 30px; background-position: -161px -6px; cursor: pointer; } .jt-console-panel-cart-label { position: absolute; top: 51px; left: 156px; width: 148px; height: 25px; padding: 0px 2px; margin: 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: normal; font-variant: normal; font-weight: bold; font-stretch: normal; font-size: 14px; line-height: 25px; font-family: sans-serif; text-align: center; color: black; background: black; border: 1px solid transparent; opacity: 1; cursor: pointer; } .jt-console-panel-power-labels { left: 31px; bottom: 9px; width: 88px; height: 15px; background-position: -135px -37px; } .jt-console-panel-reset-labels { right: 16px; bottom: 9px; width: 96px; height: 15px; background-position: -135px -55px; } .jt-console-panel-p0-diff-label { left: 128px; top: 8px; width: 29px; height: 15px; background-position: -233px -37px; } .jt-console-panel-p1-diff-label { left: 313px; top: 8px; width: 28px; height: 15px; background-position: -233px -55px; } .jt-hide-labels .jt-console-panel-p0-diff-label, .jt-hide-labels .jt-console-panel-p1-diff-label, .jt-hide-labels .jt-console-panel-power-labels, .jt-hide-labels .jt-console-panel-reset-labels, .jt-hide-labels .jt-console-panel-cart-file, .jt-hide-labels .jt-console-panel-cart-url { visibility: hidden; } @media only screen and (orientation: landscape) { /* Landscape */ #jt-touch-left { left: calc(-6px - ' + this.TOUCH_CONTROLS_LEFT_WIDTH + 'px); bottom: 50%; transform: translateY(50%); } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { left: calc(-6px - ' + this.TOUCH_CONTROLS_LEFT_WIDTH_BIG + 'px); transform: translateY(50%) scale(1.2); transform-origin: left center; } #jt-touch-right { right: calc(5px - ' + this.TOUCH_CONTROLS_RIGHT_WIDTH + 'px); bottom: 50%; transform: translateY(50%); } #jt-touch-speed { position: absolute; left: -103px; top: 10px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-speed { left: -118px; } /* Adjust centered elements leaving space to the touch controls on both sides */ html.jt-full-screen.jt-touch-active #jt-screen-fs-center { left: ' + this.TOUCH_CONTROLS_LEFT_WIDTH + 'px; right: ' + this.TOUCH_CONTROLS_RIGHT_WIDTH + 'px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-screen-fs-center { left: ' + this.TOUCH_CONTROLS_LEFT_WIDTH_BIG + 'px; } } @media only screen and (orientation: portrait) { /* Portrait */ #jt-touch-left { left: 2px; bottom: 200px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { transform: scale(1.2); transform-origin: left center; } #jt-touch-right { right: 5px; bottom: 144px; width: 112px; height: 112px; } #jt-touch-speed { position: absolute; left: 19px; bottom: ' + (this.BAR_HEIGHT + 12) + 'px; } .jt-touch-button { position: absolute; } #jt-touch-button { bottom: 50%; right: 50%; } #jt-touch-buttonT { bottom: 100%; right: 0%; } } @media only screen and (orientation: portrait) and (max-device-height: 638px) { /* Medium Portrait. Like iPhone 5 */ #jt-touch-left { bottom: 156px; } #jt-touch-right { bottom: 100px; } } @media only screen and (orientation: portrait) and (max-device-height: 518px) { /* Short Portrait. Like iPhone 4 */ #jt-touch-left { bottom: 98px; } #jt-touch-right { bottom: 42px; } html.jt-console-panel-active #jt-touch-left { bottom: 106px; } html.jt-console-panel-active #jt-touch-right { bottom: 52px; } html.jt-full-screen.jt-console-panel-active #jt-touch-speed { display: none; } } '; }; ================================================ FILE: src/main/room/screen/dialogs/CartridgeFormatDialog.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.CartridgeFormatDialog = function(screen, mainElement, atariConsole, cartridgeSocket) { "use strict"; var self = this; this.show = function (pAltPower) { if (!dialog) { create(); return setTimeout(function() { self.show(pAltPower); }, 0); } altPower = pAltPower; cartridge = cartridgeSocket.inserted(); if (!cartridge) return; format = cartridge.format.name; saveFormat = !!userROMFormats.getForROM(cartridge.rom); saveFormatEnabled = !!cartridge.rom.info.h; // No save when hash unavailable visible = true; dialog.classList.add("jt-show"); refreshList(); dialog.focus(); jt.Util.scaleToFitParentHeight(dialog, mainElement, jt.ScreenGUI.BAR_HEIGHT); }; this.hide = function (confirm) { if (!visible) return; dialog.classList.remove("jt-show"); visible = false; Javatari.room.screen.focus(); if (confirm) { var formatName = userFormatOptions[optionSelected]; var isAuto = formatName === userFormatOptions[0]; var newCart = jt.CartridgeCreator.changeCartridgeFormat(cartridge, jt.CartridgeFormats[formatName]); if (saveFormat) userROMFormats.setForROM(cartridge.rom, formatName, isAuto); cartridgeSocket.insert(newCart, !altPower && atariConsole.powerIsOn, true); screen.showOSD("ROM Format: " + formatName + (isAuto ? " (Auto)" : ""), true); } cartridge = undefined; }; function refreshList() { optionSelected = 0; cartridge.reinsertROMContent(); userFormatOptions = jt.CartridgeCreator.getUserFormatOptionNames(cartridge.rom); var autoOption = jt.CartridgeCreator.getBestFormatOption(cartridge.rom); if (!autoOption) autoOption = jt.CartridgeFormats["4K"]; // default userFormatOptions.unshift(autoOption.name); for (var i = 0; i < listItems.length; ++i) { if (i < userFormatOptions.length) { if (userFormatOptions[i] === format) optionSelected = i; listItems[i].innerHTML = i === 0 ? "AUTO: " + autoOption.name + ": " + autoOption.desc : userFormatOptions[i] + ": " + jt.CartridgeFormats[userFormatOptions[i]].desc; listItems[i].classList.add("jt-visible"); } else listItems[i].classList.remove("jt-visible"); } if (cartridge.format === autoOption) optionSelected = 0; refreshListSelection(); refreshSaveFormat(); } function refreshListSelection() { var selItem; for (var i = 0; i < userFormatOptions.length; ++i) { if (i === optionSelected) { selItem = listItems[i]; selItem.classList.add("jt-selected"); } else listItems[i].classList.remove("jt-selected"); } // Scroll to selected item if needed if (list.scrollTop > selItem.offsetTop) { list.scrollTop = selItem.offsetTop; } else if (list.scrollTop + list.offsetHeight < selItem.offsetTop + 26 + 2) { list.scrollTop = selItem.offsetTop - (list.offsetHeight - 26 - 2); // item height ~ 26px } } function refreshSaveFormat() { saveButton.textContent = saveFormatEnabled ? saveFormat ? "YES" : "NO" : "- -"; saveButton.classList.toggle("jt-selected", saveFormat); } function create() { dialog = document.createElement("div"); dialog.id = "jt-cartridge-format"; dialog.classList.add("jt-select-dialog"); dialog.style.width = "340px"; dialog.style.height = "310px"; dialog.tabIndex = -1; var header = document.createTextNode("Select ROM Format"); dialog.appendChild(header); // Define list list = document.createElement('ul'); for (var i = 0, len = jt.CartridgeFormatsUserOptions.length + 1; i < len; ++i) { // + 1 for Auto var li = document.createElement("li"); li.jtIndex = i; li.classList.add("jt-visible"); li.style.textAlign = "center"; listItems.push(li); list.appendChild(li); } dialog.appendChild(list); // Define Remember selection option var wDiv = document.createElement('div'); var ul = document.createElement('ul'); ul.classList.add("jt-quick-options-list"); li = document.createElement('li'); var div = document.createElement('div'); div.innerHTML = "💾  Remember Choice"; li.appendChild(div); saveButton = document.createElement('div'); saveButton.innerHTML = "NO"; saveButton.classList.add("jt-control"); li.appendChild(saveButton); ul.appendChild(li); wDiv.appendChild(ul); dialog.appendChild(wDiv); setupEvents(); mainElement.appendChild(dialog); } function setupEvents() { function hideAbort() { self.hide(false); } function hideConfirm() { self.hide(true); } // Do not close with taps or clicks inside jt.Util.onTapOrMouseDownWithBlock(dialog, function() { list.focus(); }); // Allow touch scrolls and touch clicks to happen jt.Util.addEventsListener(list, "touchstart touchmove touchend", function(e) { e.stopPropagation(); }); // Only select with mousedown jt.Util.addEventsListener(list, "mousedown", function(e) { e.stopPropagation(); jt.DOMConsoleControls.hapticFeedbackOnTouch(e); if (e.target.jtIndex >= 0) selectLineElement(e.target.jtIndex); }); // Confirm on click jt.Util.addEventsListener(list, "click", function(e) { jt.Util.blockEvent(e); if (e.target.jtIndex >= 0) { var sameWasSelected = e.target.jtIndex === optionSelected; selectLineElement(e.target.jtIndex); setTimeout(hideConfirm, sameWasSelected ? 0 : 120); } }); function selectLineElement(line) { optionSelected = line; refreshListSelection(); } // Toggle Save Format option with tap or mousedown jt.Util.onTapOrMouseDownWithBlock(saveButton, function(e) { if (!saveFormatEnabled) return; jt.DOMConsoleControls.hapticFeedbackOnTouch(e); saveFormat = !saveFormat; refreshSaveFormat(); }); // Trap keys, respond to some dialog.addEventListener("keydown", function(e) { var keyCode = domKeys.codeForKeyboardEvent(e); // Abort if (keyCode === ESC_KEY) hideAbort(); // Confirm else if (CONFIRM_KEYS.indexOf(keyCode) >= 0) hideConfirm(); // Select else if (SELECT_KEYS[keyCode]) { optionSelected += SELECT_KEYS[keyCode]; if (optionSelected < 0) optionSelected = 0; else if (optionSelected >= userFormatOptions.length) optionSelected = userFormatOptions.length - 1; refreshListSelection(); } return jt.Util.blockEvent(e); }); } var altPower = false; var cartridge; var format = ""; var optionSelected = 0; var userFormatOptions = []; var dialog, list, saveButton; var listItems = []; var visible = false; var saveFormat = false, saveFormatEnabled = false; var userROMFormats = Javatari.userROMFormats; var domKeys = jt.DOMKeys; var ESC_KEY = domKeys.VK_ESCAPE.c; var CONFIRM_KEYS = [ domKeys.VK_ENTER.c, domKeys.VK_SPACE.c ]; var SELECT_KEYS = {}; SELECT_KEYS[domKeys.VK_UP.c] = -1; SELECT_KEYS[domKeys.VK_DOWN.c] = 1; }; ================================================ FILE: src/main/room/screen/dialogs/NetPlayDialog.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.NetPlayDialog = function(room, mainElement) { "use strict"; var self = this; this.show = function () { if (!dialog) { create(); return setTimeout(self.show, 0); } refresh(); refreshPreferencesData(); visible = true; dialog.classList.add("jt-show"); dialog.focus(); jt.Util.scaleToFitParentWidth(dialog, mainElement, 12); }; this.hide = function() { if (!visible) return; dialog.classList.remove("jt-show"); visible = false; room.screen.focus(); }; this.roomNetPlayStatusChangeUpdate = function(oldMode) { if (visible) refresh(); // Close automatically when entering Client mode if (room.netPlayMode === 2 && oldMode < 0 && visible) return setTimeout(function() { self.hide(); }, 2000); // Open automatically when leaving Server/Client mode if (room.netPlayMode === 0 && oldMode > 0 && !visible) self.show(); }; this.isVisible = function() { return visible; }; function refresh() { switch (room.netPlayMode) { case 0: status.textContent = "STANDALONE"; start.textContent = "HOST"; join.textContent = "JOIN"; start.disabled = false; join.disabled = false; sessionName.disabled = false; nick.disabled = false; statusBox.classList.remove("jt-active"); sessionBox.classList.remove("jt-disabled"); sessionName.setAttribute("placeholder", "Enter a name"); break; case 1: var netServer = room.getNetServer(); status.textContent = "HOSTING Session: " + netServer.getSessionID(); start.textContent = "STOP"; join.textContent = "JOIN"; start.disabled = false; join.disabled = true; sessionName.disabled = true; nick.disabled = true; statusBox.classList.add("jt-active"); sessionBox.classList.add("jt-disabled"); sessionName.setAttribute("placeholder", "Automatic"); link.href = getSessionLink(); break; case 2: var netClient = room.getNetClient(); status.textContent = "JOINED Session: " + netClient.getSessionID(); start.textContent = "HOST"; join.textContent = "LEAVE"; start.disabled = true; join.disabled = false; sessionName.disabled = true; nick.disabled = true; statusBox.classList.add("jt-active"); sessionBox.classList.remove("jt-disabled"); sessionBox.classList.add("jt-disabled"); sessionName.setAttribute("placeholder", "Enter a name"); link.href = getSessionLink(); break; case -1: case -2: status.textContent = "Establishing connection..."; sessionName.disabled = true; nick.disabled = true; statusBox.classList.remove("jt-active"); sessionBox.classList.add("jt-disabled"); if (room.netPlayMode === -1) { start.textContent = "CANCEL"; join.textContent = "JOIN"; start.disabled = false; join.disabled = true; sessionName.setAttribute("placeholder", "Automatic"); } else { start.textContent = "HOST"; join.textContent = "CANCEL"; start.disabled = true; join.disabled = false; sessionName.setAttribute("placeholder", "Enter a name"); } break; } } function refreshPreferencesData() { sessionName.value = prefs.netPlaySessionName; nick.value = prefs.netPlayNick; } function getSessionLink() { return jt.Util.browserCurrentURL() + "?JOIN=" + room.netController.getSessionID(); } function performCommand(e) { var button = e.target; if (button.disabled) return; jt.DOMConsoleControls.hapticFeedbackOnTouch(e); var save = false; var prevMode = room.netPlayMode; if (button === start && (prevMode === 0 || prevMode === 1 || prevMode === -1)) { if (prevMode === 0) { room.getNetServer().startSession(sessionName.value); save = true; } else room.getNetServer().stopSession(false, prevMode === -1 ? "NetPlay connection aborted" : undefined); } else if (button === join && (prevMode === 0 || prevMode === 2 || prevMode === -2)) { if (prevMode === 0) { room.getNetClient().joinSession(sessionName.value, nick.value); save = true; } else room.getNetClient().leaveSession(false, prevMode === -2 ? "NetPlay connection aborted" : undefined); } // Save Session Name and Nick if starting/joining if (save) { var s = sessionName.value.trim(); var n = nick.value.trim(); if (prefs.netPlaySessionName !== s || prefs.netPlayNick !== n) { prefs.netPlaySessionName = s; prefs.netPlayNick = n; Javatari.userPreferences.setDirty(); Javatari.userPreferences.save(); } } } function create() { dialog = document.createElement("div"); dialog.id = "jt-netplay"; dialog.tabIndex = -1; statusBox = document.createElement("div"); statusBox.id = "jt-netplay-status-box"; dialog.appendChild(statusBox); linkText = document.createElement("input"); linkText.id = "jt-netplay-link-text"; statusBox.appendChild(linkText); status = document.createElement("div"); status.id = "jt-netplay-status"; status.textContent = "STANDALONE"; statusBox.appendChild(status); link = document.createElement("a"); link.id = "jt-netplay-link"; link.textContent = "\uD83D\uDD17"; link.setAttribute("title", "Copy Join Session link to clipboard"); statusBox.appendChild(link); sessionBox = document.createElement("div"); sessionBox.id = "jt-netplay-session-box"; dialog.appendChild(sessionBox); var sessionLabel = document.createElement("div"); sessionLabel.id = "jt-netplay-session-label"; sessionBox.appendChild(sessionLabel); start = document.createElement("button"); start.id = "jt-netplay-start"; start.jtCommand = true; start.classList.add("jt-netplay-button"); start.textContent = "HOST"; sessionBox.appendChild(start); sessionName = document.createElement("input"); sessionName.id = "jt-netplay-session-name"; sessionName.setAttribute("placeholder", "Enter a name"); sessionName.setAttribute("maxlength", 12); sessionName.spellcheck = false; sessionName.autocorrect = false; sessionName.autocapitalize = false; sessionBox.appendChild(sessionName); join = document.createElement("button"); join.id = "jt-netplay-join"; join.jtCommand = true; join.classList.add("jt-netplay-button"); join.textContent = "JOIN"; sessionBox.appendChild(join); var nickLabel = document.createElement("div"); nickLabel.id = "jt-netplay-nick-label"; sessionBox.appendChild(nickLabel); nick = document.createElement("input"); nick.id = "jt-netplay-nick"; nick.setAttribute("placeholder", "Automatic"); nick.setAttribute("maxlength", 12); nick.spellcheck = false; nick.autocorrect = false; nick.autocapitalize = false; sessionBox.appendChild(nick); setupEvents(); mainElement.appendChild(dialog); } function setupEvents() { // Do not close with taps or clicks inside, select with tap or mousedown jt.Util.onTapOrMouseDownWithBlock(dialog, function(e) { if (e.target.jtCommand) { performCommand(e); } else dialog.focus(); }); // Trap keys, respond to some dialog.addEventListener("keydown", function(e) { // Exit if (EXIT_KEYS.indexOf(e.keyCode) >= 0) self.hide(); return jt.Util.blockEvent(e); }); // Block invalid characters in sessionName and nick function filterChars(e) { var item = e.target; var value = item.value; if (!value || value.match(/^[A-Za-z0-9]+[A-Za-z0-9_\-]*@?$/)) // OK, store value return item.jtLastValidValue = value; else return item.value = item.jtLastValidValue || ""; // Not OK, use last OK value } sessionName.addEventListener("input", filterChars); nick.addEventListener("input", filterChars); // Allow selection and edit in status, sessionName and nick jt.Util.addEventsListener(status, "touchstart touchmove touchend mousedown mousemove mouseup keydown keyup", function(e) { e.stopPropagation(); }); jt.Util.addEventsListener(sessionName, "touchstart touchmove touchend mousedown mousemove mouseup keydown keyup", function(e) { e.stopPropagation(); }); jt.Util.addEventsListener(nick, "touchstart touchmove touchend mousedown mousemove mouseup keydown keyup", function(e) { e.stopPropagation(); }); // Block drag dialog.ondragstart = jt.Util.blockEvent; // Allow context in status statusBox.addEventListener("contextmenu", function(e) { e.stopPropagation(); }); // Click on link jt.Util.addEventsListener(link, "click", function(e) { jt.Util.blockEvent(e); if (!document.queryCommandSupported || !document.queryCommandSupported('copy')) return room.showOSD("Copy to Clipboard not supported by the browser!", true, true); linkText.value = getSessionLink(); linkText.focus(); linkText.select(); document.execCommand("copy"); dialog.focus(); }); } var visible = false; var dialog, statusBox, sessionBox; var start, join, stop, status, link, linkText, sessionName, nick; var prefs = Javatari.userPreferences.current; var k = jt.DOMKeys; var EXIT_KEYS = [ k.VK_ESCAPE.c ]; }; ================================================ FILE: src/main/room/screen/dialogs/QuickOptionsDialog.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.QuickOptionsDialog = function(mainElement, consoleControls, consoleControlsSocket, peripheralControls) { "use strict"; var self = this; this.show = function () { if (!dialog) { create(); return setTimeout(self.show, 0); } refresh(); visible = true; dialog.classList.add("jt-show"); dialog.focus(); jt.Util.scaleToFitParentHeight(dialog, mainElement, jt.ScreenGUI.BAR_HEIGHT); }; this.hide = function() { if (!visible) return; Javatari.userPreferences.save(); dialog.classList.remove("jt-show"); visible = false; Javatari.room.screen.focus(); }; this.controlsModeStateUpdate = function () { if (visible) refresh(); }; this.controlStateChanged = function(control, state) { if (visible && (control === cc.NO_COLLISIONS || control === cc.VSYNCH)) refresh(); }; function refresh() { for (var i = 0; i < items.length; ++i) { var item = items[i]; var report = item.peripheral ? peripheralControls.getControlReport(item.control) : consoleControlsSocket.getControlReport(item.control); item.value = report.label; item.selected = report.active; controlsItems[i].innerHTML = item.value; controlsItems[i].classList.toggle("jt-selected", !!item.selected); } } function create() { dialog = document.createElement("div"); dialog.id = "jt-quick-options"; dialog.tabIndex = -1; var pc = jt.PeripheralControls; items = [ { label: "Paddles", control: pc.PADDLES_TOGGLE_MODE, peripheral: true }, { label: "Swap Controllers", control: pc.P1_CONTROLS_TOGGLE, peripheral: true }, { label: "No Collisions", control: cc.NO_COLLISIONS }, { label: "💾  V-Synch", control: cc.VSYNCH }, { label: "💾  CRT Filter", control: pc.SCREEN_CRT_FILTER, peripheral: true }, { label: "💾  Audio Buffer", control: pc.SPEAKER_BUFFER_TOGGLE, peripheral: true }, { label: "💾  Big Directionals", control: pc.TOUCH_TOGGLE_DIR_BIG, peripheral: true }, { label: "💾  TurboFire Speed", control: pc.TURBO_FIRE_TOGGLE, peripheral: true }, { label: "💾  Haptic Feedback", control: pc.HAPTIC_FEEDBACK_TOGGLE_MODE, peripheral: true } ]; // Define list var list = document.createElement('ul'); list.classList.add("jt-quick-options-list"); for (var i = 0; i < items.length; ++i) { var li = document.createElement("li"); var label = document.createElement("div"); label.innerHTML = items[i].label; li.appendChild(label); var control = document.createElement("div"); control.classList.add("jt-control"); control.jtControlItem = items[i]; li.appendChild(control); list.appendChild(li); controlsItems.push(control); } dialog.appendChild(list); setupEvents(); mainElement.appendChild(dialog); } function setupEvents() { // Do not close with taps or clicks inside, select with tap or mousedown jt.Util.onTapOrMouseDownWithBlock(dialog, function(e) { if (e.target.jtControlItem) { jt.DOMConsoleControls.hapticFeedbackOnTouch(e); var item = e.target.jtControlItem; if (item.peripheral) { peripheralControls.controlActivated(item.control, false, false); refresh(); } else consoleControls.processControlState(item.control, true); // will get update and refresh } else dialog.focus(); }); // Trap keys, respond to some dialog.addEventListener("keydown", function(e) { // Exit if (EXIT_KEYS.indexOf(e.keyCode) >= 0) self.hide(); return jt.Util.blockEvent(e); }); } var visible = false; var dialog, list; var items, controlsItems = []; var cc = jt.ConsoleControls; var k = jt.DOMKeys; var EXIT_KEYS = [ k.VK_ESCAPE.c, k.VK_ENTER.c, k.VK_SPACE.c ]; }; ================================================ FILE: src/main/room/screen/dialogs/RecentROMsDialog.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.RecentROMsDialog = function(mainElement, screen, recentROMs, fileLoader) { "use strict"; var self = this; this.show = function (pSave) { if (!dialog) { create(); return setTimeout(function() { self.show(pSave); }, 0); } items = recentROMs.getCatalog().slice(0); // clone items.sort(function (a, b) { return a.n > b.n; }); var last = recentROMs.lastROMLoadedIndex; last = items.indexOf(items.find(function(r) { return r.i === last; })); itemSelected = last < 0 || last >= items.length ? items.length : last; visible = true; refreshList(); dialog.classList.add("jt-show"); dialog.focus(); jt.Util.scaleToFitParentHeight(dialog, mainElement, jt.ScreenGUI.BAR_HEIGHT); }; this.hide = function (confirm) { if (!visible) return; dialog.classList.remove("jt-show"); visible = false; Javatari.room.screen.focus(); if (confirm) { if (itemSelected === items.length) screen.openLoadFileDialog(); else { var rom = recentROMs.getROM(items[itemSelected].i); fileLoader.loadROM(rom); } } }; function refreshList() { dialog.style.height = "" + (42 + (items.length + 1) * 33) + "px"; for (var i = 0; i < 11; ++i) { // 10 + 1 for Open File option var li = listItems[i]; var item = items[i]; li.classList.toggle("jt-visible", i <= items.length); li.classList.toggle("jt-toggle", i < items.length); li.classList.toggle("jt-toggle-checked", i < items.length); li.jtNeedsUIG = i === items.length; // Open file li.innerHTML = item ? item.n : "  Open ROM File..."; } refreshListSelection(); } function refreshListSelection() { for (var i = 0; i < listItems.length; ++i) listItems[i].classList.toggle("jt-selected", i === itemSelected); } function create() { dialog = document.createElement("div"); dialog.id = "jt-recent-roms"; dialog.classList.add("jt-select-dialog"); dialog.style.width = "350px"; dialog.tabIndex = -1; dialog.appendChild(document.createTextNode("Select Cartridge")); // Define list list = document.createElement('ul'); list.style.width = "85%"; for (var i = 0; i < 11; ++i) { var li = document.createElement("li"); li.style.textAlign = "center"; li.innerHTML = ""; li.jtItem = i; listItems.push(li); list.appendChild(li); } dialog.appendChild(list); setupEvents(); mainElement.appendChild(dialog); } function setupEvents() { function hideAbort() { self.hide(false); } function hideConfirm() { self.hide(true); } // Do not close with taps or clicks inside jt.Util.onTapOrMouseDownWithBlock(dialog, function() { dialog.focus(); }); // Select with tap or mousedown (UIG) jt.Util.onTapOrMouseDownWithBlockUIG(dialog, function(e, uigStart) { if (e.target.jtItem >= 0) { if (uigStart) jt.DOMConsoleControls.hapticFeedbackOnTouch(e); itemSelected = e.target.jtItem; refreshListSelection(); if (!uigStart) setTimeout(hideConfirm, 120); } }); // Trap keys, respond to some dialog.addEventListener("keydown", function(e) { // Abort if (e.keyCode === ESC_KEY) hideAbort(); // Confirm else if (CONFIRM_KEYS.indexOf(e.keyCode) >= 0) hideConfirm(); // Select else if (SELECT_KEYS[e.keyCode]) { itemSelected += SELECT_KEYS[e.keyCode]; if (itemSelected < 0) itemSelected = 0; else if (itemSelected > items.length) itemSelected = items.length; // + 1 for Open File refreshListSelection(); } return jt.Util.blockEvent(e); }); } var items = []; var itemSelected = 0; var dialog, list; var listItems = []; var visible = false; var k = jt.DOMKeys; var ESC_KEY = k.VK_ESCAPE.c; var CONFIRM_KEYS = [ k.VK_ENTER.c, k.VK_SPACE.c ]; var SELECT_KEYS = {}; SELECT_KEYS[k.VK_UP.c] = -1; SELECT_KEYS[k.VK_DOWN.c] = 1; }; ================================================ FILE: src/main/room/screen/dialogs/SaveStateDialog.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.SaveStateDialog = function(mainElement, consoleControls, peripheralControls, stateMedia) { "use strict"; var self = this; this.show = function (pSave) { if (!dialog) { create(); return setTimeout(function() { self.show(pSave); }, 0); } save = pSave; visible = true; refreshList(); dialog.classList.add("jt-show"); dialog.focus(); jt.Util.scaleToFitParentHeight(dialog, mainElement, jt.ScreenGUI.BAR_HEIGHT); }; this.hide = function (confirm) { if (!visible) return; dialog.classList.remove("jt-show"); visible = false; Javatari.room.screen.focus(); if (confirm) { var option = slotOptions[slotSelected]; var control = save ? option.save : option.load; if (option.peripheral) peripheralControls.controlActivated(control); else consoleControls.processControlState(control, true); } }; function refreshList() { header.textContent = "Select Slot to " + (save ? "Save" : "Load"); var prefix = save ? "Save to " : "Load from "; for (var i = 0; i < listItems.length; ++i) { var li = listItems[i]; li.innerHTML = prefix + slotOptions[i].d; li.classList.toggle("jt-toggle-checked", stateMedia.isSlotUsed(i + 1)); } refreshListSelection(); } function refreshListSelection() { for (var i = 0; i < listItems.length; ++i) listItems[i].classList.toggle("jt-selected", i === slotSelected); } function create() { dialog = document.createElement("div"); dialog.id = "jt-savestate"; dialog.classList.add("jt-select-dialog"); dialog.style.width = "280px"; dialog.style.height = "" + (41 + 11 * 33) + "px"; dialog.tabIndex = -1; header = document.createTextNode("Select Slot"); dialog.appendChild(header); // Define list list = document.createElement('ul'); list.style.width = "80%"; for (var i = 0; i < slotOptions.length; ++i) { var li = document.createElement("li"); li.classList.add("jt-visible"); if (i < slotOptions.length - 1) li.classList.add("jt-toggle"); li.style.textAlign = "center"; li.innerHTML = slotOptions[i].d; li.jtSlot = i; li.jtNeedsUIG = true; // Will open dialog or download file! listItems.push(li); list.appendChild(li); } dialog.appendChild(list); setupEvents(); mainElement.appendChild(dialog); } function setupEvents() { function hideAbort() { self.hide(false); } function hideConfirm() { self.hide(true); } // Do not close with taps or clicks inside jt.Util.onTapOrMouseDownWithBlock(dialog, function() { dialog.focus(); }); // Select with tap or mousedown (UIG) jt.Util.onTapOrMouseDownWithBlockUIG(dialog, function(e, uigStart) { if (e.target.jtSlot >= 0) { if (uigStart) jt.DOMConsoleControls.hapticFeedbackOnTouch(e); slotSelected = e.target.jtSlot; refreshListSelection(); if (!uigStart) setTimeout(hideConfirm, 120); // UIG } }); // Trap keys, respond to some dialog.addEventListener("keydown", function(e) { // Abort if (e.keyCode === ESC_KEY) hideAbort(); // Confirm else if (CONFIRM_KEYS.indexOf(e.keyCode) >= 0) hideConfirm(); // Select else if (SELECT_KEYS[e.keyCode]) { slotSelected += SELECT_KEYS[e.keyCode]; if (slotSelected < 0) slotSelected = 0; else if (slotSelected > 10) slotSelected = 10; refreshListSelection(); } return jt.Util.blockEvent(e); }); } var save = false; var slotSelected = 0; var dialog, list; var listItems = []; var visible = false; var header; var c = jt.ConsoleControls; var p = jt.PeripheralControls; var slotOptions = [ { d: "Slot 1", load: c.LOAD_STATE_1, save: c.SAVE_STATE_1 }, { d: "Slot 2", load: c.LOAD_STATE_2, save: c.SAVE_STATE_2 }, { d: "Slot 3", load: c.LOAD_STATE_3, save: c.SAVE_STATE_3 }, { d: "Slot 4", load: c.LOAD_STATE_4, save: c.SAVE_STATE_4 }, { d: "Slot 5", load: c.LOAD_STATE_5, save: c.SAVE_STATE_5 }, { d: "Slot 6", load: c.LOAD_STATE_6, save: c.SAVE_STATE_6 }, { d: "Slot 7", load: c.LOAD_STATE_7, save: c.SAVE_STATE_7 }, { d: "Slot 8", load: c.LOAD_STATE_8, save: c.SAVE_STATE_8 }, { d: "Slot 9", load: c.LOAD_STATE_9, save: c.SAVE_STATE_9 }, { d: "Slot 10", load: c.LOAD_STATE_10, save: c.SAVE_STATE_10 }, { d: "File...", load: p.CONSOLE_LOAD_STATE_FILE, save: p.CONSOLE_SAVE_STATE_FILE, peripheral: true } ]; var k = jt.DOMKeys; var ESC_KEY = k.VK_ESCAPE.c; var CONFIRM_KEYS = [ k.VK_ENTER.c, k.VK_SPACE.c ]; var SELECT_KEYS = {}; SELECT_KEYS[k.VK_UP.c] = -1; SELECT_KEYS[k.VK_DOWN.c] = 1; }; ================================================ FILE: src/main/room/screen/es6/ScreenGUI.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.ScreenGUI = jt.Util.isMobileDevice() ? { BAR_HEIGHT: 29, BAR_MENU_WIDTH: 150, BAR_MENU_ITEM_HEIGHT: 33, BAR_MENU_ITEM_FONT_SIZE: 14, LOGO_SCREEN_WIDTH: 618, LOGO_SCREEN_HEIGHT: 455, TOUCH_CONTROLS_LEFT_WIDTH: 119, TOUCH_CONTROLS_LEFT_WIDTH_BIG: 143, TOUCH_CONTROLS_RIGHT_WIDTH: 80 } : { BAR_HEIGHT: 29, BAR_MENU_WIDTH: 140, BAR_MENU_ITEM_HEIGHT: 29, BAR_MENU_ITEM_FONT_SIZE: 13, LOGO_SCREEN_WIDTH: 618, LOGO_SCREEN_HEIGHT: 455, TOUCH_CONTROLS_LEFT_WIDTH: 119, TOUCH_CONTROLS_LEFT_WIDTH_BIG: 143, TOUCH_CONTROLS_RIGHT_WIDTH: 80 }; jt.ScreenGUI.html = function() { return `
Swipe up/down on the Screen
to hide the browser bars!
`; }; jt.ScreenGUI.htmlConsolePanel = `
` ; jt.ScreenGUI.css = function() { return `html.jt-full-screen-scroll-hack body { position: absolute; width: 100%; height: ` + Math.max(1280, (Math.max(screen.width, screen.height) * 1.4) | 0) + `px; top: 0; left: 0; margin: 0; padding: 0; border: none; overflow-x: hidden; overflow-y: auto; } #jt-screen-fs, #jt-screen-fs div, #jt-screen-fs canvas { outline: none; } #` + Javatari.SCREEN_ELEMENT_ID + ` { display: inline-block; visibility: hidden; font-family: sans-serif; font-weight: normal; margin: 0; padding: 0; border: 1px solid black; background: black; overflow: visible; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; touch-callout: none; -webkit-tap-highlight-color: transparent; tap-highlight-color: transparent; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; text-size-adjust: none; } html.jt-full-screen #` + Javatari.SCREEN_ELEMENT_ID + ` { display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; box-shadow: none; z-index: 2147483646; /* one behind fsElement */ } html.jt-started #` + Javatari.SCREEN_ELEMENT_ID + ` { visibility: visible; } #jt-screen-scroll-message { position: absolute; bottom: 150%; left: 50%; height: 0; width: 0; margin: 0; padding: 0; font-size: 16px; line-height: 28px; white-space: nowrap; color: hsl(0, 0%, 4%); background: hsl(0, 0%, 92%); border-radius: 15px; transform: translate(-50%, 0); box-shadow: 2px 2px 9px rgba(0, 0, 0, 0.7); transition: all 1.7s step-end, opacity 1.6s linear; overflow: hidden; opacity: 0; z-index: -1; } html.jt-full-screen-scroll-hack #jt-screen-fs.jt-scroll-message #jt-screen-scroll-message { opacity: 1; bottom: 23%; width: 215px; height: 56px; padding: 13px 20px; z-index: 60; transition: none; } #jt-screen-fs { position: relative; background: black; text-align: center; -webkit-tap-highlight-color: rgba(0,0,0,0); tap-highlight-color: rgba(0,0,0,0) } html.jt-full-screen #jt-screen-fs { position: absolute; width: 100%; height: 100%; left: 0; bottom: 0; right: 0; z-index: 2147483647; } html.jt-full-screen-scroll-hack #jt-screen-fs { position: fixed; bottom: 0; height: 100vh; } html.jt-full-screen #jt-screen-fs-center { /* Used to center and move things horizontally in Landscape Full Screen */ position: absolute; top: 0; bottom: 0; left: 0; right: 0; } #jt-screen-canvas-outer { display: inline-block; position: relative; overflow: hidden; vertical-align: top; line-height: 1px; z-index: 3; } #jt-screen-canvas { display: block; } #jt-bar { position: relative; left: 0; right: 0; height: ` + this.BAR_HEIGHT + `px; margin: 0 auto; border-top: 1px solid black; background: hsl(0, 0%, 16%); overflow: visible; /* for the Menu to show through */ box-sizing: content-box; z-index: 40; } #jt-bar-inner { position: absolute; overflow: hidden; top: 0; bottom: 0; left: 0; right: 0; text-align: left; } html.jt-bar-auto-hide #jt-bar, html.jt-full-screen #jt-bar { position: absolute; bottom: 0; transition: height 0.08s ease-in-out; } html.jt-bar-auto-hide #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } @media only screen and (orientation: landscape) { html.jt-full-screen #jt-bar.jt-hidden { transition: height 0.5s ease-in-out; height: 0; bottom: -1px; } } #jt-bar.jt-narrow .jt-narrow-hidden { display: none; } .jt-bar-button { display: inline-block; width: 24px; height: 28px; margin: 0 1px; background-image: url("` + jt.Images.urls.iconSprites + `"); background-repeat: no-repeat; background-size: 264px 82px; cursor: pointer; } /* Firefox-specific rules */ @-moz-document url-prefix() { .jt-bar-button { image-rendering: optimizequality; } } /* .jt-bar-button { border: 1px solid yellow; background-origin: border-box; box-sizing: border-box; } */ #jt-bar-power { margin: 0 3px 0 6px; } #jt-bar-netplay.jt-hidden { display: none; } #jt-bar-select { margin: 0 2px 0 9px; width: 50px; } #jt-bar-reset { margin: 0 2px; width: 50px; } html.jt-console-panel-active #jt-bar-select, html.jt-console-panel-active #jt-bar-reset { display: none; } #jt-bar-settings, #jt-bar-full-screen, #jt-bar-scale-plus, #jt-bar-scale-minus { float: right; margin: 0; } #jt-bar-settings { margin-right: 5px; } #jt-bar-full-screen.jt-mobile { margin: 0 6px; } #jt-bar-scale-plus { width: 21px; } #jt-bar-scale-minus { width: 18px; } #jt-bar-text { float: right; width: 32px; } #jt-bar-text.jt-mobile { margin: 0 0 0 6px; } #jt-bar-console-panel { position: absolute; left: 2px; right: 0; width: 39px; margin: 0 auto; } #jt-bar.jt-narrow #jt-bar-console-panel { position: static; float: right; margin-right: 3px; } #jt-bar-logo { position: absolute; left: 0; right: 0; width: 34px; margin: 0 auto; } html:not(.jt-console-panel-active) #jt-bar.jt-narrow #jt-bar-logo { display: none; } #jt-bar-menu { position: absolute; display: none; bottom: ` + this.BAR_HEIGHT + `px; font-size: ` + this.BAR_MENU_ITEM_FONT_SIZE + `px; line-height: 1px; overflow: hidden; transform-origin: bottom center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-bar-menu-inner { display: inline-block; padding-bottom: 2px; border: 1px solid black; background: hsl(0, 0%, 16%); } .jt-bar-menu-item, #jt-bar-menu-title { position: relative; display: none; width: ` + this.BAR_MENU_WIDTH + `px; height: ` + this.BAR_MENU_ITEM_HEIGHT + `px; color: rgb(205, 205, 205); border: none; padding: 0; line-height: ` + this.BAR_MENU_ITEM_HEIGHT + `px; text-shadow: 1px 1px 1px black; background: transparent; outline: none; overflow: hidden; backface-visibility: hidden; -webkit-backface-visibility: hidden; cursor: pointer; box-sizing: border-box; } #jt-bar-menu-title { display: block; color: white; font-weight: bold; border-bottom: 1px solid black; margin-bottom: 1px; text-align: center; background: rgb(70, 70, 70); cursor: auto; } .jt-bar-menu-item.jt-hover:not(.jt-bar-menu-item-disabled):not(.jt-bar-menu-item-divider) { color: white; background: hsl(358, 67%, 46%); } .jt-bar-menu-item-disabled { color: rgb(110, 110, 110); } .jt-bar-menu-item-divider { height: 1px; margin: 1px 0; background: black; } .jt-bar-menu-item-toggle { text-align: left; padding-left: 30px; } .jt-bar-menu-item-toggle::after { content: ""; position: absolute; width: 6px; height: 19px; top: ` + (((this.BAR_MENU_ITEM_HEIGHT - 21) / 2) | 0) + `px; left: 10px; background: rgb(70, 70, 70); box-shadow: black 1px 1px 1px; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked { color: white; } .jt-bar-menu-item-toggle.jt-bar-menu-item-toggle-checked::after { background: rgb(248, 33, 28); } #jt-console-panel { display: none; position: absolute; bottom: -` + (jt.ConsolePanel.DEFAULT_HEIGHT + 2) + `px; left: 50%; transform: translate(-50%, 0); transform-origin: center top; margin: 0 auto; border: 1px solid black; z-index: 30; } html.jt-console-panel-active #jt-console-panel { display: block; } html.jt-full-screen #jt-console-panel { bottom: ` + (jt.ScreenGUI.BAR_HEIGHT + 2) + `px; border: none; transform-origin: center bottom; } .jt-select-dialog { position: absolute; overflow: hidden; display: none; top: 0; bottom: 0; left: 0; right: 0; width: 540px; max-width: 92%; height: 297px; margin: auto; color: white; font-size: 18px; line-height: 21px; background: hsl(0, 0%, 16%); padding: 11px 0 0; text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } .jt-select-dialog.jt-show { display: block; } .jt-select-dialog > .jt-footer { position: absolute; width: 100%; bottom: 7px; font-size: 13px; text-align: center; color: rgb(170, 170, 170); } .jt-select-dialog > ul { position: relative; width: 88%; top: 5px; margin: auto; padding: 0; list-style: none; font-size: 14px; color: hsl(0, 0%, 88%); } .jt-select-dialog > ul li { display: none; position: relative; overflow: hidden; height: 26px; background: rgb(70, 70, 70); margin: 7px 0; padding: 11px 10px 0 18px; /* Space on the left for the toggle mark for all lines */ line-height: 0; text-align: left; text-overflow: ellipsis; border: 2px dashed transparent; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); white-space: nowrap; box-sizing: border-box; cursor: pointer; } .jt-select-dialog > ul li.jt-visible { display: block; } .jt-select-dialog > ul li.jt-selected { color: white; background: hsl(358, 67%, 46%); } .jt-select-dialog > ul li.jt-droptarget { color: white; border-color: lightgray; } .jt-select-dialog > ul li.jt-toggle::after { content: ""; position: absolute; width: 6px; height: 17px; top: 2px; left: 6px; background: rgb(60, 60, 60); box-shadow: black 1px 1px 1px; } .jt-select-dialog > ul li.jt-toggle-checked::after { background: rgb(248, 33, 28); } #jt-cartridge-format.jt-select-dialog > ul { width: 100%; height: 226px; margin: 7px auto 0; padding: 0 0 0 30px; overflow-y: auto; box-sizing: border-box; } #jt-cartridge-format.jt-select-dialog > ul li { width: 280px; margin: 7px 0 2px 0; } #jt-cartridge-format.jt-select-dialog > ul li:first-child { margin-top: 0; } #jt-cartridge-format ::-webkit-scrollbar { width: 12px; } #jt-cartridge-format ::-webkit-scrollbar-track { background: transparent; } #jt-cartridge-format ::-webkit-scrollbar-thumb { border: solid transparent; border-width: 1px 1px 1px 2px; background: rgb(80, 80, 80); background-clip: content-box; } #jt-cartridge-format ul.jt-quick-options-list { width: 230px; margin: 18px 0 0 52px; } #jt-cartridge-format ul.jt-quick-options-list li div { height: 24px; line-height: 24px; } #jt-cartridge-format .jt-control { width: 60px; line-height: 24px; } /* Firefox-specific rules */ @-moz-document url-prefix() { /* Try to hide scrollbar, since we cant style it :-( */ #jt-cartridge-format.jt-select-dialog > ul { width: 304px; } } #jt-logo { position: absolute; display: none; top: 0; bottom: 0; left: 0; right: 0; background: black; } #jt-logo.jt-show { display: block; } #jt-logo-center { position: absolute; top: 50%; left: 50%; width: 598px; height: 456px; transform: translate(-50%, -50%); } #jt-logo-image { position: absolute; top: 50%; left: 50%; width: 335px; max-width: 57%; transform: translate(-50%, -50%); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-image { top: 128px; width: 37%; max-width: initial; } #jt-logo-loading-icon, #jt-canvas-loading-icon { display: none; position: absolute; top: 79%; left: 0; right: 0; width: 14%; height: 3%; margin: 0 auto; background-color: rgba(0, 0, 0, .8); border: solid transparent; border-width: 8px 30px; border-radius: 3px; box-sizing: content-box; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #jt-screen-fs.jt-logo-message-active #jt-logo-loading-icon { top: 204px; } #jt-unmute-message { display: none; position: absolute; left: 50%; bottom: 5px; height: 30px; padding: 0 10px; margin: 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; font-size: 15px; line-height: 30px; color: rgb(210, 210, 210); background: rgba(0, 0, 0, 0.7); transform-origin: bottom center; transform: translate(-50%, 0); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-unmute-message::before { content: ""; display: inline-block; width: 24px; height: 20px; margin: 5px 9px 0 0; background-image: url("` + jt.Images.urls.muteIcon + `"); background-repeat: no-repeat; background-size: 24px 20px; vertical-align: top; } #jt-unmute-message::after { content: "Audio is muted. Click to unmute"; } #jt-unmute-message.jt-show { display: inline-block; } #jt-logo-message { display: none; position: absolute; top: 226px; width: 100%; color: hsl(0, 0%, 97%); font-size: 29px; line-height: 34px; } #jt-screen-fs.jt-logo-message-active #jt-logo-message { display: block; } #jt-logo-message-ok { display: block; position: absolute; top: 91px; left: 193px; width: 214px; height: 130px; } #jt-logo-message-ok.jt-higher { top: 74px; } #jt-logo-message-ok-text { position: absolute; top: 49%; left: 50%; width: 120px; height: 47px; font-size: 23px; line-height: 47px; background: hsl(358, 67%, 46%); border-radius: 6px; color: white; transform: translate(-50%, -50%); } #jt-osd { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: -29px; right: 16px; height: 29px; padding: 0 12px; margin: 0; font-weight: bold; font-size: 15px; line-height: 29px; color: rgb(0, 255, 0); background: rgba(0, 0, 0, 0.7); transform-origin: top right; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; opacity: 0; } .jt-arrow-up, .jt-arrow-down, .jt-arrow-left, .jt-arrow-right { border: 0px solid transparent; box-sizing: border-box; } .jt-arrow-up { border-bottom-color: inherit; } .jt-arrow-down { border-top-color: inherit; } .jt-arrow-left { border-right-color: inherit; } .jt-arrow-right { border-left-color: inherit; } .jt-quick-options-list { margin-top: 12px; padding: 0; list-style: none; color: hsl(0, 0%, 88%); } .jt-quick-options-list li { margin-top: 8px; line-height: 1px; text-align: left; } .jt-quick-options-list li div { display: inline-block; overflow: hidden; height: 26px; font-size: 14px; line-height: 26px; text-overflow: ellipsis; white-space: nowrap; box-sizing: border-box; } .jt-quick-options-list .jt-control { float: right; width: 86px; font-size: 15px; line-height: 25px; color: hsl(0, 0%, 70%); background: black; text-align: center; cursor: pointer; } .jt-quick-options-list .jt-control.jt-selected { color: white; background: hsl(358, 67%, 46%); box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); } .jt-quick-options-list .jt-control.jt-selected.jt-inactive { line-height: 21px; border: 2px dashed hsl(358, 67%, 46%); background: black; } #jt-quick-options { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 233px; height: 345px; margin: auto; padding: 11px 14px 0; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-quick-options.jt-show { display: block; } #jt-quick-options::before { content: "Quick Options"; display: block; } #jt-netplay { display: none; position: absolute; top: 0; bottom: 0; left: 0; right: 0; width: 390px; height: 220px; margin: auto; padding-top: 11px; color: white; font-size: 18px; line-height: 22px; background: hsl(0, 0%, 16%); text-align: center; border: 1px solid black; box-sizing: initial; text-shadow: 1px 1px 1px black; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform-origin: left center; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; cursor: auto; z-index: 50; } #jt-netplay.jt-show { display: block; } #jt-netplay::before { content: "Net Play!"; display: block; } #jt-netplay-status-box { position: relative; margin-top: 17px; } #jt-netplay-status { display: inline-block; position: relative; width: 340px; font-size: 15px; line-height: 27px; background: black; vertical-align: top; text-shadow: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; box-sizing: border-box; cursor: auto; } #jt-netplay-status-box.jt-active #jt-netplay-status { padding: 0 16px 0 12px; } #jt-netplay-status-box.jt-active #jt-netplay-status::after { content: ""; position: absolute; width: 6px; height: 18px; top: 4px; left: 7px; background: rgb(248, 33, 28); } #jt-netplay-link { display: none; position: absolute; right: 25px; top: 0; width: 26px; height: 27px; color: white; font-size: 15px; font-weight: 600; line-height: 27px; text-decoration: none; background: black; text-align: center; } #jt-netplay-link:hover { background: hsl(358, 67%, 46%); cursor: pointer; } #jt-netplay-status-box.jt-active #jt-netplay-link { display: block; } .jt-netplay-button { display: inline-block; width: 86px; padding: 0; margin: 0; font-size: 15px; line-height: 26px; color: white; background: hsl(358, 67%, 46%); text-shadow: 1px 1px 1px black; border: none; box-shadow: 1px 1px 1px rgba(0, 0, 0, .5); cursor: pointer; } #jt-netplay-session-box { margin-top: 18px; } #jt-netplay-session-label, #jt-netplay-nick-label { font-size: 15px; margin-bottom: 4px; } #jt-netplay-session-label::before { content: "Session Name"; } #jt-netplay-session-box input { width: 150px; height: 26px; padding: 0 10px; margin: 0 8px; font-size: 15px; line-height: 26px; background: rgb(240, 240, 240); border: none; border-radius: 0; box-sizing: border-box; outline: none; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; cursor: auto; } #jt-netplay-nick-label { margin-top: 10px; } #jt-netplay-nick-label::before { content: "User Nickname"; } .jt-netplay-button:disabled { color: rgb(130, 130, 130); background: rgb(70, 70, 70); cursor: default; } #jt-netplay input:disabled { color: black; background: rgb(180, 180, 180); cursor: default; } #jt-netplay-session-box.jt-disabled div { color: rgb(130, 130, 130); } input#jt-netplay-link-text { position: absolute; top: 8px; left: 50px; width: 1px; height: 1px; padding: 0; margin: 0; border: none; color: transparent; background: transparent; opacity: 0; z-index: -10; -webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; } #jt-touch-left, #jt-touch-right, #jt-touch-speed { display: none; position: absolute; z-index: 1; } html.jt-full-screen.jt-touch-active #jt-touch-left, html.jt-full-screen.jt-touch-active #jt-touch-right, html.jt-full-screen.jt-touch-active #jt-touch-speed { display: block; } .jt-touch-dir { width: 130px; height: 130px; color: hsl(0, 0%, 75%); border-radius: 100%; } .jt-touch-dir::before { content: ""; position: absolute; top: 14px; left: 14px; right: 14px; bottom: 14px; border: 1px solid hsl(0, 0%, 26%); border-radius: 100%; } .jt-touch-dir-joy .jt-touch-dir-up, .jt-touch-dir-joy .jt-touch-dir-left { position: absolute; background: hsl(0, 0%, 31%); border-radius: 2px 2px 0 0; box-shadow: inset 1px 2px 0px hsl(0, 0%, 43%), inset -1px -1px hsl(0, 0%, 19%), 0 3px 0 1px hsl(0, 0%, 21%); } .jt-touch-dir-joy .jt-touch-dir-up { width: 26px; height: 78px; top: 24px; left: 52px; } .jt-touch-dir-joy .jt-touch-dir-left { width: 78px; height: 25px; top: 51px; left: 26px; } .jt-touch-dir-joy .jt-touch-dir-left::before { content: ""; position: absolute; top: 2px; left: 23px; width: 33px; height: 22px; background: inherit; z-index: 1; } .jt-touch-dir-joy .jt-touch-dir-left::after { content: ""; position: absolute; top: 4px; left: 30px; height: 17px; width: 17px; border-radius: 100%; box-shadow: inset 0 0 2px hsl(0, 0%, 22%), inset 1px 2px 3px 1px hsl(0, 0%, 26%), inset -1px -2px 1px hsl(0, 0%, 64%); z-index: 2; } .jt-touch-dir .jt-arrow-up, .jt-touch-dir .jt-arrow-down, .jt-touch-dir .jt-arrow-left, .jt-touch-dir .jt-arrow-right { position: absolute; border-width: 5px; z-index: 2; } .jt-touch-dir .jt-arrow-up { top: 26px; left: 60px; border-bottom-width: 11px; } .jt-touch-dir .jt-arrow-down { bottom: 29px; left: 60px; border-top-width: 11px; } .jt-touch-dir .jt-arrow-left { top: 58px; left: 26px; border-right-width: 11px; } .jt-touch-dir .jt-arrow-right { top: 58px; right: 26px; border-left-width: 11px; } .jt-touch-button { position: relative; display: block; width: 72px; height: 72px; font-size: 20px; line-height: 67px; color: hsl(0, 0%, 79%); border-radius: 100%; cursor: default; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; z-index: 0; } .jt-touch-button::before { content: ""; position: absolute; box-sizing: border-box; z-index: -1; } .jt-touch-button-joy::before, .jt-touch-button-none::before { width: 50px; height: 48px; top: 9px; left: 11px; border-radius: 100%; } #jt-screen-fs.jt-touch-config-active .jt-touch-button-none::before { border: 2px solid hsl(0, 0%, 30%); } .jt-touch-button-joy.jt-touch-button-joy-button::before { border: none; background: hsl(1, 70%, 37%); box-shadow: inset -2px -7px 3px 1px hsl(1, 68%, 43%), inset 0px 0px 1px 9px hsl(1, 72%, 33%), 0px -1px 0px 1px hsl(1, 70%, 47%), 0px 1px 0px 2px hsl(1, 70%, 29%); } .jt-touch-button-joy.jt-touch-button-joy-buttonT::before { border: none; background: hsl(220, 72%, 39%); box-shadow: inset -2px -7px 3px 1px hsl(220, 70%, 43%), inset 0px 0px 1px 9px hsl(220, 75%, 34%), 0px -1px 0px 1px hsl(220, 72%, 50%), 0px 1px 0px 2px hsl(220, 72%, 28%); } #jt-touch-button { z-index: 7 } #jt-touch-buttonT { z-index: 6 } #jt-touch-speed.jt-center { width: 84px; left: 0; right: 0; margin: 0 auto; } #jt-touch-speed.jt-center.jt-poweroff #jt-touch-pause { margin-left: 21px } #jt-touch-pause, #jt-touch-fast { float: left; width: 42px; height: 42px; border-color: hsl(0, 0%, 70%); } #jt-touch-pause::after, #jt-touch-fast::before, #jt-touch-fast::after { content: ""; display: inline-block; border: 0 solid transparent; box-sizing: border-box; } #jt-touch-pause::after { margin-top: 14px; width: 13px; height: 14px; border-width: 0; border-left-width: 4px; border-left-color: inherit; border-right-width: 4px; border-right-color: inherit; } #jt-touch-fast::before, #jt-touch-fast::after { margin-top: 14px; width: 11px; height: 14px; border-width: 7px; border-left-width: 11px; border-left-color: inherit; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-pause::after, #jt-touch-speed.jt-poweroff #jt-touch-pause::after { margin: 12px 0 0 3px; width: 15px; height: 18x; border-width: 9px; border-left-width: 15px; border-right-width: 0; } #jt-touch-speed.jt-paused #jt-touch-fast::after { width: 7px; border-width: 0; border-left-width: 3px; } #jt-touch-speed.jt-poweroff #jt-touch-fast { display: none; } .jt-console-panel { width:` + jt.ConsolePanel.DEFAULT_WIDTH + `px; height:` + jt.ConsolePanel.DEFAULT_HEIGHT + `px; background: black url("` + jt.Images.urls.panel + `") no-repeat; background-size: 460px 134px; box-shadow: ` + jt.ConsolePanel.sameBoxShadowAsScreen() + `; outline: none; } html.jt-full-screen .jt-console-panel { box-shadow: none; } .jt-console-panel-icon { position: absolute; background: url("` + jt.Images.urls.iconSprites + `") center no-repeat; background-size: 264px 82px; } .jt-console-panel-switch { position: absolute; bottom: 107px; width: 50px; height: 26px; opacity: 0; cursor: pointer; } .jt-console-panel-switch:after { content: ""; position: absolute; left: 11px; bottom: 5px; width: 27px; height: 16px; background: url("` + jt.Images.urls.panelSprites + `") center no-repeat; background-size: 256px 93px; } .jt-console-panel-lever { position: absolute; bottom: 30px; width: 44px; height: 72px; cursor: pointer; } .jt-console-panel-lever:after { content: ""; position: absolute; left: 12px; bottom: 8px; width: 20px; height: 46px; background: url("` + jt.Images.urls.panelSprites + `") center no-repeat; background-size: 256px 93px; } .jt-console-panel-power { left: 19px; } .jt-console-panel-power:after { background-position: 0px 0px; } .jt-console-panel-color { left: 84px; } .jt-console-panel-color:after { background-position: -21px 0px; } .jt-console-panel-select { left: 340px; } .jt-console-panel-select:after { background-position: 0px -47px; } .jt-console-panel-reset { left: 403px; } .jt-console-panel-reset:after { background-position: -21px -47px; } .jt-console-panel-p0-diff { left: 152px; } .jt-console-panel-p0-diff:after { background-position: -229px -17px; } .jt-console-panel-p1-diff { left: 265px; } .jt-console-panel-p1-diff:after { background-position: -229px 0px; } .jt-console-panel-cart-image { position: absolute; left: 140px; bottom: 9px; width: 186px; height: 82px; background: url("` + jt.Images.urls.panelSprites + `") center no-repeat; background-size: 256px 93px; background-position: -42px 0px; } .jt-console-panel-cart-load { position: absolute; left: 141px; bottom: 36px; width: 184px; height: 55px; cursor: pointer; } .jt-console-panel-cart-file { left: 170px; bottom: 3px; width: 31px; height: 30px; background-position: -132px -6px; cursor: pointer; } .jt-console-panel-cart-url { left: 266px; bottom: 3px; width: 31px; height: 30px; background-position: -161px -6px; cursor: pointer; } .jt-console-panel-cart-label { position: absolute; top: 51px; left: 156px; width: 148px; height: 25px; padding: 0px 2px; margin: 0px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: normal; font-variant: normal; font-weight: bold; font-stretch: normal; font-size: 14px; line-height: 25px; font-family: sans-serif; text-align: center; color: black; background: black; border: 1px solid transparent; opacity: 1; cursor: pointer; } .jt-console-panel-power-labels { left: 31px; bottom: 9px; width: 88px; height: 15px; background-position: -135px -37px; } .jt-console-panel-reset-labels { right: 16px; bottom: 9px; width: 96px; height: 15px; background-position: -135px -55px; } .jt-console-panel-p0-diff-label { left: 128px; top: 8px; width: 29px; height: 15px; background-position: -233px -37px; } .jt-console-panel-p1-diff-label { left: 313px; top: 8px; width: 28px; height: 15px; background-position: -233px -55px; } .jt-hide-labels .jt-console-panel-p0-diff-label, .jt-hide-labels .jt-console-panel-p1-diff-label, .jt-hide-labels .jt-console-panel-power-labels, .jt-hide-labels .jt-console-panel-reset-labels, .jt-hide-labels .jt-console-panel-cart-file, .jt-hide-labels .jt-console-panel-cart-url { visibility: hidden; } @media only screen and (orientation: landscape) { /* Landscape */ #jt-touch-left { left: calc(-6px - ` + this.TOUCH_CONTROLS_LEFT_WIDTH + `px); bottom: 50%; transform: translateY(50%); } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { left: calc(-6px - ` + this.TOUCH_CONTROLS_LEFT_WIDTH_BIG + `px); transform: translateY(50%) scale(1.2); transform-origin: left center; } #jt-touch-right { right: calc(5px - ` + this.TOUCH_CONTROLS_RIGHT_WIDTH + `px); bottom: 50%; transform: translateY(50%); } #jt-touch-speed { position: absolute; left: -103px; top: 10px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-speed { left: -118px; } /* Adjust centered elements leaving space to the touch controls on both sides */ html.jt-full-screen.jt-touch-active #jt-screen-fs-center { left: ` + this.TOUCH_CONTROLS_LEFT_WIDTH + `px; right: ` + this.TOUCH_CONTROLS_RIGHT_WIDTH + `px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-screen-fs-center { left: ` + this.TOUCH_CONTROLS_LEFT_WIDTH_BIG + `px; } } @media only screen and (orientation: portrait) { /* Portrait */ #jt-touch-left { left: 2px; bottom: 200px; } html.jt-full-screen.jt-touch-active.jt-dir-big #jt-touch-left { transform: scale(1.2); transform-origin: left center; } #jt-touch-right { right: 5px; bottom: 144px; width: 112px; height: 112px; } #jt-touch-speed { position: absolute; left: 19px; bottom: ` + (this.BAR_HEIGHT + 12) + `px; } .jt-touch-button { position: absolute; } #jt-touch-button { bottom: 50%; right: 50%; } #jt-touch-buttonT { bottom: 100%; right: 0%; } } @media only screen and (orientation: portrait) and (max-device-height: 638px) { /* Medium Portrait. Like iPhone 5 */ #jt-touch-left { bottom: 156px; } #jt-touch-right { bottom: 100px; } } @media only screen and (orientation: portrait) and (max-device-height: 518px) { /* Short Portrait. Like iPhone 4 */ #jt-touch-left { bottom: 98px; } #jt-touch-right { bottom: 42px; } html.jt-console-panel-active #jt-touch-left { bottom: 106px; } html.jt-console-panel-active #jt-touch-right { bottom: 52px; } html.jt-full-screen.jt-console-panel-active #jt-touch-speed { display: none; } } `; }; ================================================ FILE: src/main/room/screen/es6/SettingsGUI.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // HTML and CSS data for Settings jt.SettingsGUI = { WIDTH: 600, HEIGHT: 450}; jt.SettingsGUI.html = function() { return `
Help & Settings
CONSOLE
CONTROLLERS
EMULATION
ABOUT
F1
POWER
F2
TV TYPE
F4
P1 Difficulty
F5
Load Cartridge File
F6
Load Cartridge URL
F7
Remove Cartridge
F12
RESET
F11
SELECT
F9
P2 Difficulty
Alt
 + 
L
Toggle Paddles
Alt
 + 
K
Toggle Swap Sides
Alt
 + 
J
Toggle Gamepads
Alt
 + 
H
Adjust Turbo Fire speed
PLAYER 1
Fire
Up
Turbo Fire
Left
Right
Down
PLAYER 2
Fire
Up
Turbo Fire
Left
Right
Down
Alt
 + 
C
Collisions
Shift
 + 
F1
Fry Console
Alt
 + 
Q
NTSC/PAL
Alt
 + 
W
V-Synch Modes
Alt
 + 
R
CRT Modes
Alt
 + 
T
CRT Filters
Alt
 + 
D
Debug Modes
Alt
 + 
I
Show Info
Alt
 + 
G
Capture Screen
Right-Click Bar Icons: Default Action
Alt
 + 
0 - 9
Load State
Ctrl
 + 
0 - 9
Save State
F8
Save State File
F12
  /  
Shift
 + 
F12
Fast / Slow Speed
Shift
 
Alt
 + 
Arrows
Adjust Speed
Alt
 + 
P
Toggle Pause
Alt
 + 
O
 / 
F
Next Frame
Alt
 + 
Enter
Full Screen
Ctrl
 
Alt
 + 
Arrows
Screen Size / Width
Shift
 
Ctrl
 + 
Arrows
Viewport Size / Origin
Backspace
Defaults
version ` + Javatari.VERSION + `
` + atob("Q3JlYXRlZCBieSBQYXVsbyBBdWd1c3RvIFBlY2Npbg==") + `
` + atob("PGEgdGFyZ2V0PSJfYmxhbmsiIGhyZWY9Imh0dHA6Ly9qYXZhdGFyaS5vcmciPmh0dHA6Ly9qYXZhdGFyaS5vcmc8L2E+") + `
`; }; jt.SettingsGUI.css = function() { return `#jt-modal * { outline: none; box-sizing: border-box; } #jt-modal { position: absolute; overflow: hidden; width: ` + jt.SettingsGUI.WIDTH + `px; height: 0; opacity: 0; visibility: hidden; top: 50%; left: 50%; color: hsl(0, 0%, 10%); font: normal 13px sans-serif; white-space: nowrap; text-align: initial; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform: scale(0.85); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out, height .25s step-end; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; z-index: 50; } #jt-modal.jt-show { transform: scale(1); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out; height: ` + jt.SettingsGUI.HEIGHT + `px; visibility: visible; opacity: 1; } #jt-modal .jt-heading { font-weight: 700; color: hsl(0, 0%, 30%); } #jt-modal .jt-link { font-weight: 700; line-height: 21px; color: hsl(228, 90%, 40%); cursor: pointer; } #jt-modal .jt-link:hover { outline: 1px solid; } .jt-command { position: relative; display: inline-block; font-weight: 600; color: hsl(0, 0%, 48%); } .jt-hotkey { height: 27px; padding: 3px 5px; box-sizing: border-box; } .jt-hotkey .jt-desc { display: inline-block; line-height: 21px; } .jt-key { position: relative; display: inline-block; top: -1px; min-width: 25px; height: 21px; padding: 4px 6px 3px; box-sizing: border-box; font-weight: 600; font-size: 12px; line-height: 12px; color: hsl(0, 0%, 42%); background: white; border-radius: 3px; border: 1px solid rgb(210, 210, 210); box-shadow: 0 1px 0 1px hsl(0, 0%, 47%); text-align: center; } .jt-key-fixed { width: 31px; padding-left: 0; padding-right: 2px; } .jt-footer { margin-top: 16px; text-align: center; } #jt-menu { position: relative; background: white; border-bottom: 1px solid hsl(0, 0%, 72%); } #jt-menu #jt-back { position: absolute; width: 40px; height: 34px; margin: 3px 1px; padding: 16px 12px; cursor: pointer; } #jt-menu #jt-back:hover { background: rgba(0, 0, 0, .12); } .jt-back-arrow { display: block; width: 16px; height: 2px; border-radius: 1000px; background: hsl(0, 0%, 98%); } .jt-back-arrow:before { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(-45deg); transform-origin: 1px 1px; } .jt-back-arrow:after { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(45deg); transform-origin: 1px 1px; } #jt-menu .jt-caption { height: 29px; margin: 0 -1px; padding: 10px 0 0 48px; font-size: 18px; color: white; background: hsl(358, 66%, 50%); box-shadow: 0 1px 3px rgba(0, 0, 0, .9); vertical-align: middle; box-sizing: content-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-menu .jt-items { position: relative; width: 84%; height: 39px; margin: 0 auto; font-weight: 600; } #jt-menu .jt-item { float: left; width: 25%; height: 100%; padding-top: 13px; font-size: 14px; color: rgba(0, 0, 0, .43); text-align: center; cursor: pointer; } #jt-menu .jt-selected { color: hsl(358, 67%, 46%); } #jt-menu #jt-menu-selection { position: absolute; left: 0; bottom: 0; width: 25%; height: 3px; background: hsl(358, 67%, 46%); transition: left 0.3s ease-in-out; } #jt-content { position: relative; left: 0; width: 3000px; height: 371px; background: rgb(218, 218, 218); transition: left 0.3s ease-in-out } #jt-console, #jt-ports, #jt-general, #jt-about { position: absolute; width: ` + jt.SettingsGUI.WIDTH + `px; height: 100%; box-sizing: border-box; } #jt-console { padding-top: 35px; } #jt-console .jt-hotkey { height: 29px; } #jt-console .jt-command { width: 42px; } #jt-console .jt-left, #jt-console .jt-middle, #jt-console .jt-right { float: left; } #jt-console .jt-left { width: 160px; margin-left: 58px; } #jt-console .jt-middle { width: 204px; } #jt-console .jt-right .jt-command { width: 46px; } #jt-console .jt-console-panel { position: relative; margin: 18px auto 0; box-shadow: rgba(0, 0, 0, 0.6) 2px 2px 4px; } #jt-console .jt-console-panel * { cursor: auto; } #jt-console .jt-footer { margin: 20px auto; } #jt-ports { left: ` + jt.SettingsGUI.WIDTH + `px; padding: 18px 0 0 27px; } #jt-ports > .jt-left { float: left; width: 335px; padding-left: 26px; } #jt-ports > .jt-right { float: left; } #jt-ports .jt-command { width: 91px; } #jt-ports .jt-bottom { width: 546px; text-align: center; } #jt-ports .jt-player { position: absolute; top: 146px; width: 217px; color: rgba(0, 0, 0, .8); } #jt-ports .jt-p1 { left: 47px; } #jt-ports .jt-p2 { right: 47px; } #jt-ports .jt-title { margin-bottom: 09px; font-size: 14px; line-height: 14px; font-weight: bold; color: hsl(0, 0%, 35%); text-align: center; } #jt-ports .jt-player .jt-command { display: block; position: relative; float: left; width: 33%; height: 45px; font-size: 13px; text-align: center; } #jt-ports .jt-command.jt-fire1, #jt-ports .jt-command.jt-fire2 { top: 14px; } #jt-ports .jt-command.jt-left, #jt-ports .jt-command.jt-right { top: 27px; } #jt-ports .jt-command.jt-down { float: none; clear: both; margin: 0 auto; } #jt-ports .jt-command.jt-controller { height: 90px; } #jt-ports #jt-control-p1-controller, #jt-ports #jt-control-p2-controller { width: 70px; height: 89px; margin-left: 1px; background: url("` + jt.Images.urls.controllers + `") no-repeat -1px 0; background-size: 73px 179px; } #jt-ports .jt-player .jt-key { min-width: 33px; height: 23px; padding: 5px 6px 4px; margin-top: 2px; cursor: pointer; } #jt-ports .jt-player .jt-key:hover { box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5), 1px 2px 6px 4px rgb(170, 170, 170); } #jt-ports .jt-player .jt-key.jt-redefining { color: white; background-color: rgb(87, 128, 255); border-color: rgb(71, 117, 255); } #jt-ports .jt-player .jt-key.jt-undefined { background-color: rgb(255, 150, 130); border-color: rgb(255, 130, 90); } #jt-ports-defaults, #jt-ports-revert { position: absolute; left: 260px; width: 82px; text-align: center; padding: 3px 0 1px; font-size: 12px; } #jt-ports-defaults { bottom: 47px; } #jt-ports-revert { bottom: 21px; } #jt-general { left: ` + (jt.SettingsGUI.WIDTH * 2) + `px; padding-top: 18px; padding-left: 34px; } #jt-general .jt-left { float: left; width: 245px; } #jt-general .jt-left .jt-command { width: 99px; } #jt-general .jt-right { float: left; } #jt-general .jt-right .jt-command { width: 160px; } #jt-about { left: ` + (jt.SettingsGUI.WIDTH * 3) + `px; font-size: 18px; } #jt-about #jt-logo-version { width: 300px; height: 238px; margin: 26px auto 19px; color: hsl(0, 0%, 98%); padding-top: 200px; box-sizing: border-box; text-align: center; background: black url("` + jt.Images.urls.logo + `") center 18px no-repeat; background-size: 233px 173px; box-shadow: 3px 3px 14px rgb(75, 75, 75); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-about .jt-info { line-height: 30px; text-align: center; } #jt-about a { color: rgb(0, 40, 200); text-decoration: none; } #jt-about a:hover { text-decoration: underline; } #jt-about #jt-browserinfo { position: absolute; left: 0; right: 0; bottom: 7px; font-size: 10px; text-align: center; color: transparent; } .jt-clear { clear: both; } .jt-divider { clear: both; height: 27px; } .jt-full-divider { clear: both; height: 21px; } #jt-general .jt-full-divider { clear: both; height: 18px; }`; }; ================================================ FILE: src/main/room/screen/settings/Settings.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.SettingsDialog = function(parentElement, consoleControls) { "use strict"; var self = this; this.show = function (atPage) { if (!modal) { create(); setTimeout(function() { self.show(atPage); }, 0); return; } if (!this.position()) return; controlRedefining = null; this.setPage(atPage || page); modal.classList.add("jt-show"); modal.classList.add("jt-show"); visible = true; setTimeout(function() { modal.focus(); }, 50); }; this.hide = function () { if (!visible) return; self.hideLesser(); Javatari.room.screen.focus(); }; this.hideLesser = function () { if (Javatari.userPreferences.isDirty) finishPreferences(); modal.classList.remove("jt-show"); modal.classList.remove("jt-show"); visible = false; }; this.setPage = function (pPage) { page = pPage; var contentPosition = { "CONSOLE": "0", "PORTS": "-600px", "GENERAL": "-1200px", "ABOUT": "-1800px" }[page]; var selectionPosition = { "CONSOLE": "0", "PORTS": "25%", "GENERAL": "50%", "ABOUT": "75%" }[page]; if (contentPosition) self["jt-content"].style.left = contentPosition; if (selectionPosition) self["jt-menu-selection"].style.left = selectionPosition; self["jt-menu-console"].classList.toggle("jt-selected", page === "CONSOLE"); self["jt-menu-ports"].classList.toggle("jt-selected", page === "PORTS"); self["jt-menu-general"].classList.toggle("jt-selected", page === "GENERAL"); self["jt-menu-about"].classList.toggle("jt-selected", page === "ABOUT"); switch(page) { case "ABOUT": refreshAboutPage(); break; case "PORTS": refreshPortsPage(); } }; this.isVisible = function() { return visible; }; this.position = function() { var w = parentElement.clientWidth; var h = parentElement.clientHeight; if (w < 575 || h < 400) { this.hide(); return false; } modal.style.top = "" + (((h - jt.SettingsGUI.HEIGHT) / 2) | 0) + "px"; modal.style.left = "" + (((w - jt.SettingsGUI.WIDTH) / 2) | 0) + "px"; return true; }; this.controlsModeStateUpdate = function () { if (visible && page === "PORTS") refreshPortsPage(); }; function create() { jt.Util.insertCSS(jt.SettingsGUI.css()); parentElement.insertAdjacentHTML("beforeend", jt.SettingsGUI.html()); modal = document.getElementById("jt-modal"); delete jt.SettingsGUI.html; delete jt.SettingsGUI.css; setFields(); setEvents(); } // Automatically set fields for each child element that has the "id" attribute function setFields() { traverseDOM(modal, function (element) { var jtVar = element.id && element.getAttribute && element.getAttribute("jt-var"); if (jtVar) self[element.id] = element; }); function traverseDOM(element, func) { func(element); var child = element.childNodes; for (var i = 0; i < child.length; i++) traverseDOM(child[i], func); } } function setEvents() { // Do not close with taps or clicks inside jt.Util.onTapOrMouseDownWithBlock(modal, function() { modal.focus(); }); // Close with the back button jt.Util.onTapOrMouseDownWithBlock(self["jt-back"], self.hide); // Several key events modal.addEventListener("keydown", function (e) { processKeyEvent(e, true); }); modal.addEventListener("keyup", function (e) { processKeyEvent(e, false); }); // Tabs jt.Util.onTapOrMouseDownWithBlock(self["jt-menu-console"], function () { self.setPage("CONSOLE"); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-menu-ports"], function () { self.setPage("PORTS"); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-menu-general"], function () { self.setPage("GENERAL"); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-menu-about"], function () { self.setPage("ABOUT"); }); // Key redefinition for (var elem in controlKeysElements) { (function(localControl) { jt.Util.onTapOrMouseDownWithBlock(self[localControl], function () { keyRedefinitionStart(localControl); }); })(elem); } // Controls Actions jt.Util.onTapOrMouseDownWithBlock(self["jt-ports-paddles-mode"], function() { consoleControls.togglePaddleMode(); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-ports-p1-mode"], function() { consoleControls.toggleP1ControlsMode(); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-ports-gamepads-mode"], function() { consoleControls.toggleGamepadMode(); }); jt.Util.onTapOrMouseDownWithBlock(self["jt-ports-defaults"], controlsDefaults); jt.Util.onTapOrMouseDownWithBlock(self["jt-ports-revert"], controlsRevert); } function refreshAboutPage() { self["jt-browserinfo"].innerHTML = navigator.userAgent; } function refreshPortsPage() { var paddlesMode = consoleControls.isPaddleMode(); var p1Mode = consoleControls.isP1ControlsMode(); self["jt-ports-paddles-mode"].innerHTML = "Controllers: " + (paddlesMode ? "PADDLES" : "JOYSTICKS"); self["jt-ports-p1-mode"].innerHTML = "Swap Mode: " + (p1Mode ? "SWAPPED" : "NORMAL"); self["jt-ports-gamepads-mode"].innerHTML = "Gamepads: " + (consoleControls.getGamepadModeDesc()); if (paddlesMode) { self["jt-control-p1-controller"].style.backgroundPositionY = "-91px"; self["jt-control-p2-controller"].style.backgroundPositionY = "-91px"; self["jt-control-p1-up-label"].innerHTML = self["jt-control-p2-up-label"].innerHTML = "+ Speed"; self["jt-control-p1-down-label"].innerHTML = self["jt-control-p2-down-label"].innerHTML = "- Speed"; } else { self["jt-control-p1-controller"].style.backgroundPositionY = "0"; self["jt-control-p2-controller"].style.backgroundPositionY = "0"; self["jt-control-p1-up-label"].innerHTML = self["jt-control-p2-up-label"].innerHTML = "Up"; self["jt-control-p1-down-label"].innerHTML = self["jt-control-p2-down-label"].innerHTML = "Down"; } self["jt-control-p1-label"].innerHTML = "PLAYER " + (p1Mode ? "2" : "1"); self["jt-control-p2-label"].innerHTML = "PLAYER " + (p1Mode ? "1" : "2"); var keys = prefs.joystickKeys; for (var controlElem in controlKeysElements) { var elem = self[controlElem]; if (controlElem === controlRedefining) { elem.classList.add("jt-redefining"); elem.classList.remove("jt-undefined"); elem.innerHTML = "?"; } else { elem.classList.remove("jt-redefining"); var controlInfo = controlKeysElements[controlElem]; var keyInfo = keys[controlInfo.player][controlInfo.control]; if (keyInfo.c === jt.DOMKeys.VK_VOID.c) { elem.classList.add("jt-undefined"); elem.innerHTML = ""; } else { elem.classList.remove("jt-undefined"); elem.innerHTML = keyInfo.n; } } } } function processKeyEvent(e, press) { var code = jt.DOMKeys.codeForKeyboardEvent(e); if (press && code === KEY_ESC) { hideOrKeyRedefinitionStop(); return jt.Util.blockEvent(e); } else if(controlRedefining) keyRedefinitionTry(e); } var keyRedefinitionStart = function(control) { controlRedefining = control; refreshPortsPage(); }; var keyRedefinitonStop = function() { controlRedefining = null; refreshPortsPage(); }; var keyRedefinitionTry = function (e) { if (!controlRedefining) return; var c = jt.DOMKeys.codeForKeyboardEvent(e); var n = jt.DOMKeys.nameForKeyboardEventSingle(e); if (c === jt.DOMKeys.VK_VOID.c || !n) return; var newKey = { c: c, n: n }; var controlInfo = controlKeysElements[controlRedefining]; var keys = prefs.joystickKeys; for (var con in controlKeysElements) { var otherControlInfo = controlKeysElements[con]; if (con !== controlRedefining && keys[otherControlInfo.player][otherControlInfo.control].c === newKey.c) keys[otherControlInfo.player][otherControlInfo.control] = jt.DOMKeys.VK_VOID; } keys[controlInfo.player][controlInfo.control] = newKey; Javatari.userPreferences.setDirty(); keyRedefinitonStop(); }; var hideOrKeyRedefinitionStop = function() { if (controlRedefining) keyRedefinitonStop(); else self.hide() }; var controlsDefaults = function () { Javatari.userPreferences.setDefaultJoystickKeys(); keyRedefinitonStop(); // will refresh }; var controlsRevert = function () { Javatari.userPreferences.load(); keyRedefinitonStop(); // will refresh }; var finishPreferences = function () { Javatari.userPreferences.save(); consoleControls.applyPreferences(); }; var controlKeysElements = { "jt-control-p1-button": { player: 0, control: "button" }, "jt-control-p1-buttonT": { player: 0, control: "buttonT" }, "jt-control-p1-up": { player: 0, control: "up" }, "jt-control-p1-left": { player: 0, control: "left" }, "jt-control-p1-right": { player: 0, control: "right" }, "jt-control-p1-down": { player: 0, control: "down" }, "jt-control-p2-button": { player: 1, control: "button" }, "jt-control-p2-buttonT": { player: 1, control: "buttonT" }, "jt-control-p2-up": { player: 1, control: "up" }, "jt-control-p2-left": { player: 1, control: "left" }, "jt-control-p2-right": { player: 1, control: "right" }, "jt-control-p2-down": { player: 1, control: "down" } }; var controlRedefining = null; var modal; var page = "CONSOLE"; var visible = false; var prefs = Javatari.userPreferences.current; var KEY_ESC = jt.DOMKeys.VK_ESCAPE.c; }; ================================================ FILE: src/main/room/screen/settings/SettingsGUI.es5.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // HTML and CSS data for Settings jt.SettingsGUI = { WIDTH: 600, HEIGHT: 450}; jt.SettingsGUI.html = function() { return '
Help & Settings
CONSOLE
CONTROLLERS
EMULATION
ABOUT
F1
POWER
F2
TV TYPE
F4
P1 Difficulty
F5
Load Cartridge File
F6
Load Cartridge URL
F7
Remove Cartridge
F12
RESET
F11
SELECT
F9
P2 Difficulty
Alt
 + 
L
Toggle Paddles
Alt
 + 
K
Toggle Swap Sides
Alt
 + 
J
Toggle Gamepads
Alt
 + 
H
Adjust Turbo Fire speed
PLAYER 1
Fire
Up
Turbo Fire
Left
Right
Down
PLAYER 2
Fire
Up
Turbo Fire
Left
Right
Down
Alt
 + 
C
Collisions
Shift
 + 
F1
Fry Console
Alt
 + 
Q
NTSC/PAL
Alt
 + 
W
V-Synch Modes
Alt
 + 
R
CRT Modes
Alt
 + 
T
CRT Filters
Alt
 + 
D
Debug Modes
Alt
 + 
I
Show Info
Alt
 + 
G
Capture Screen
Right-Click Bar Icons: Default Action
Alt
 + 
0 - 9
Load State
Ctrl
 + 
0 - 9
Save State
F8
Save State File
F12
  /  
Shift
 + 
F12
Fast / Slow Speed
Shift
 
Alt
 + 
Arrows
Adjust Speed
Alt
 + 
P
Toggle Pause
Alt
 + 
O
 / 
F
Next Frame
Alt
 + 
Enter
Full Screen
Ctrl
 
Alt
 + 
Arrows
Screen Size / Width
Shift
 
Ctrl
 + 
Arrows
Viewport Size / Origin
Backspace
Defaults
version ' + Javatari.VERSION + '
' + atob("Q3JlYXRlZCBieSBQYXVsbyBBdWd1c3RvIFBlY2Npbg==") + '
' + atob("PGEgdGFyZ2V0PSJfYmxhbmsiIGhyZWY9Imh0dHA6Ly9qYXZhdGFyaS5vcmciPmh0dHA6Ly9qYXZhdGFyaS5vcmc8L2E+") + '
'; }; jt.SettingsGUI.css = function() { return '#jt-modal * { outline: none; box-sizing: border-box; } #jt-modal { position: absolute; overflow: hidden; width: ' + jt.SettingsGUI.WIDTH + 'px; height: 0; opacity: 0; visibility: hidden; top: 50%; left: 50%; color: hsl(0, 0%, 10%); font: normal 13px sans-serif; white-space: nowrap; text-align: initial; box-shadow: 3px 3px 15px 2px rgba(0, 0, 0, .4); transform: scale(0.85); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out, height .25s step-end; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; z-index: 50; } #jt-modal.jt-show { transform: scale(1); transition: visibility .2s ease-out, opacity .2s ease-out, transform .2s ease-out; height: ' + jt.SettingsGUI.HEIGHT + 'px; visibility: visible; opacity: 1; } #jt-modal .jt-heading { font-weight: 700; color: hsl(0, 0%, 30%); } #jt-modal .jt-link { font-weight: 700; line-height: 21px; color: hsl(228, 90%, 40%); cursor: pointer; } #jt-modal .jt-link:hover { outline: 1px solid; } .jt-command { position: relative; display: inline-block; font-weight: 600; color: hsl(0, 0%, 48%); } .jt-hotkey { height: 27px; padding: 3px 5px; box-sizing: border-box; } .jt-hotkey .jt-desc { display: inline-block; line-height: 21px; } .jt-key { position: relative; display: inline-block; top: -1px; min-width: 25px; height: 21px; padding: 4px 6px 3px; box-sizing: border-box; font-weight: 600; font-size: 12px; line-height: 12px; color: hsl(0, 0%, 42%); background: white; border-radius: 3px; border: 1px solid rgb(210, 210, 210); box-shadow: 0 1px 0 1px hsl(0, 0%, 47%); text-align: center; } .jt-key-fixed { width: 31px; padding-left: 0; padding-right: 2px; } .jt-footer { margin-top: 16px; text-align: center; } #jt-menu { position: relative; background: white; border-bottom: 1px solid hsl(0, 0%, 72%); } #jt-menu #jt-back { position: absolute; width: 40px; height: 34px; margin: 3px 1px; padding: 16px 12px; cursor: pointer; } #jt-menu #jt-back:hover { background: rgba(0, 0, 0, .12); } .jt-back-arrow { display: block; width: 16px; height: 2px; border-radius: 1000px; background: hsl(0, 0%, 98%); } .jt-back-arrow:before { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(-45deg); transform-origin: 1px 1px; } .jt-back-arrow:after { content: ""; display: block; position: absolute; width: 10px; height: 2px; border-radius: inherit; background: inherit; transform: rotate(45deg); transform-origin: 1px 1px; } #jt-menu .jt-caption { height: 29px; margin: 0 -1px; padding: 10px 0 0 48px; font-size: 18px; color: white; background: hsl(358, 66%, 50%); box-shadow: 0 1px 3px rgba(0, 0, 0, .9); vertical-align: middle; box-sizing: content-box; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-menu .jt-items { position: relative; width: 84%; height: 39px; margin: 0 auto; font-weight: 600; } #jt-menu .jt-item { float: left; width: 25%; height: 100%; padding-top: 13px; font-size: 14px; color: rgba(0, 0, 0, .43); text-align: center; cursor: pointer; } #jt-menu .jt-selected { color: hsl(358, 67%, 46%); } #jt-menu #jt-menu-selection { position: absolute; left: 0; bottom: 0; width: 25%; height: 3px; background: hsl(358, 67%, 46%); transition: left 0.3s ease-in-out; } #jt-content { position: relative; left: 0; width: 3000px; height: 371px; background: rgb(218, 218, 218); transition: left 0.3s ease-in-out } #jt-console, #jt-ports, #jt-general, #jt-about { position: absolute; width: ' + jt.SettingsGUI.WIDTH + 'px; height: 100%; box-sizing: border-box; } #jt-console { padding-top: 35px; } #jt-console .jt-hotkey { height: 29px; } #jt-console .jt-command { width: 42px; } #jt-console .jt-left, #jt-console .jt-middle, #jt-console .jt-right { float: left; } #jt-console .jt-left { width: 160px; margin-left: 58px; } #jt-console .jt-middle { width: 204px; } #jt-console .jt-right .jt-command { width: 46px; } #jt-console .jt-console-panel { position: relative; margin: 18px auto 0; box-shadow: rgba(0, 0, 0, 0.6) 2px 2px 4px; } #jt-console .jt-console-panel * { cursor: auto; } #jt-console .jt-footer { margin: 20px auto; } #jt-ports { left: ' + jt.SettingsGUI.WIDTH + 'px; padding: 18px 0 0 27px; } #jt-ports > .jt-left { float: left; width: 335px; padding-left: 26px; } #jt-ports > .jt-right { float: left; } #jt-ports .jt-command { width: 91px; } #jt-ports .jt-bottom { width: 546px; text-align: center; } #jt-ports .jt-player { position: absolute; top: 146px; width: 217px; color: rgba(0, 0, 0, .8); } #jt-ports .jt-p1 { left: 47px; } #jt-ports .jt-p2 { right: 47px; } #jt-ports .jt-title { margin-bottom: 09px; font-size: 14px; line-height: 14px; font-weight: bold; color: hsl(0, 0%, 35%); text-align: center; } #jt-ports .jt-player .jt-command { display: block; position: relative; float: left; width: 33%; height: 45px; font-size: 13px; text-align: center; } #jt-ports .jt-command.jt-fire1, #jt-ports .jt-command.jt-fire2 { top: 14px; } #jt-ports .jt-command.jt-left, #jt-ports .jt-command.jt-right { top: 27px; } #jt-ports .jt-command.jt-down { float: none; clear: both; margin: 0 auto; } #jt-ports .jt-command.jt-controller { height: 90px; } #jt-ports #jt-control-p1-controller, #jt-ports #jt-control-p2-controller { width: 70px; height: 89px; margin-left: 1px; background: url("' + jt.Images.urls.controllers + '") no-repeat -1px 0; background-size: 73px 179px; } #jt-ports .jt-player .jt-key { min-width: 33px; height: 23px; padding: 5px 6px 4px; margin-top: 2px; cursor: pointer; } #jt-ports .jt-player .jt-key:hover { box-shadow: 0 1px 0 1px rgba(0, 0, 0, .5), 1px 2px 6px 4px rgb(170, 170, 170); } #jt-ports .jt-player .jt-key.jt-redefining { color: white; background-color: rgb(87, 128, 255); border-color: rgb(71, 117, 255); } #jt-ports .jt-player .jt-key.jt-undefined { background-color: rgb(255, 150, 130); border-color: rgb(255, 130, 90); } #jt-ports-defaults, #jt-ports-revert { position: absolute; left: 260px; width: 82px; text-align: center; padding: 3px 0 1px; font-size: 12px; } #jt-ports-defaults { bottom: 47px; } #jt-ports-revert { bottom: 21px; } #jt-general { left: ' + (jt.SettingsGUI.WIDTH * 2) + 'px; padding-top: 18px; padding-left: 34px; } #jt-general .jt-left { float: left; width: 245px; } #jt-general .jt-left .jt-command { width: 99px; } #jt-general .jt-right { float: left; } #jt-general .jt-right .jt-command { width: 160px; } #jt-about { left: ' + (jt.SettingsGUI.WIDTH * 3) + 'px; font-size: 18px; } #jt-about #jt-logo-version { width: 300px; height: 238px; margin: 26px auto 19px; color: hsl(0, 0%, 98%); padding-top: 200px; box-sizing: border-box; text-align: center; background: black url("' + jt.Images.urls.logo + '") center 18px no-repeat; background-size: 233px 173px; box-shadow: 3px 3px 14px rgb(75, 75, 75); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } #jt-about .jt-info { line-height: 30px; text-align: center; } #jt-about a { color: rgb(0, 40, 200); text-decoration: none; } #jt-about a:hover { text-decoration: underline; } #jt-about #jt-browserinfo { position: absolute; left: 0; right: 0; bottom: 7px; font-size: 10px; text-align: center; color: transparent; } .jt-clear { clear: both; } .jt-divider { clear: both; height: 27px; } .jt-full-divider { clear: both; height: 21px; } #jt-general .jt-full-divider { clear: both; height: 18px; }'; }; ================================================ FILE: src/main/room/speaker/WebAudioSpeaker.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. // Accepts multiple AudioSignals with different sampling rates // Mixes all signals performing per-signal resampling as needed jt.WebAudioSpeaker = function(mainElement) { "use strict"; this.connect = function(audioSocket) { audioSocket.connectMonitor(this); }; this.connectPeripherals = function(pScreen) { screen = pScreen; }; this.connectAudioSignal = function(pAudioSignal) { if (audioSignal.indexOf(pAudioSignal) >= 0) return; // Add only once jt.Util.arrayAdd(audioSignal, pAudioSignal); updateResamplingFactors(); }; this.disconnectAudioSignal = function(pAudioSignal) { if (audioSignal.indexOf(pAudioSignal) < 0) return; // Not present jt.Util.arrayRemoveAllElement(audioSignal, pAudioSignal); updateResamplingFactors(); }; this.powerOn = function() { createAudioContext(); if (!processor) return; registerUnlockOnTouchIfNeeded(); this.unpause(); }; this.powerOff = function() { this.pause(); if (audioContext) audioContext.close(); audioContext = processor = undefined; }; this.mute = function () { mute = true; }; this.unMute = function () { mute = false; }; this.pause = function () { if (processor) processor.disconnect(); }; this.unpause = function () { if (processor) processor.connect(audioContext.destination); }; this.toggleBufferBaseSize = function() { if (!audioContext) return screen.showOSD("Audio is DISABLED", true, true); bufferBaseSize = ((bufferBaseSize + 2) % 8) - 1; // -1..6 this.pause(); createProcessor(); this.unpause(); screen.showOSD("Audio Buffer size: " + (bufferBaseSize === -1 ? "Auto (" + bufferSize + ")" : bufferBaseSize === 0 ? "Browser (" + bufferSize + ")" : bufferSize), true); prefs.audioBufferBase = bufferBaseSize; Javatari.userPreferences.setDirty(); }; this.getControlReport = function(control) { // Only BufferBaseSize for now return { label: bufferBaseSize === -2 ? "OFF" : bufferBaseSize === -1 ? "Auto" : bufferBaseSize === 0 ? "Browser" : bufferSize, active: bufferBaseSize > 0 }; }; function determineAutoBufferBaseSize() { // Set bufferBaseSize according to browser and platform return jt.Util.isMobileDevice() ? jt.Util.browserInfo().name === "CHROME" && !jt.Util.isIOSDevice() ? 4 // for now mobile Chrome needs more buffer, except on iOS : 3 // other mobile scenarios : 2; // desktop } function determineBrowserDefaultBufferBaseSize() { // Safari/WebKit does not allow 0 (browser default), so use Auto instead return jt.Util.browserInfo().name === "SAFARI" || jt.Util.isIOSDevice() ? determineAutoBufferBaseSize() : 0; } var createAudioContext = function() { if (bufferBaseSize === -2 || Javatari.AUDIO_MONITOR_BUFFER_SIZE === 0) { jt.Util.warning("Audio disabled in configuration"); return; } try { var constr = (window.AudioContext || window.webkitAudioContext || window.WebkitAudioContext); if (!constr) throw new Error("WebAudio API not supported by the browser"); audioContext = new constr(); jt.Util.log("Speaker AudioContext created. Sample rate: " + audioContext.sampleRate + (audioContext.state ? ", " + audioContext.state : "")); createProcessor(); } catch(ex) { jt.Util.error("Could not create AudioContext. Audio DISABLED!\n" + ex); } }; var createProcessor = function() { try { // If not specified, calculate buffer size based on baseSize and host audio sampling rate. Ex: for a baseSize = 1 then 22050Hz = 256, 44100 = 512, 48000 = 512, 96000 = 1024, 192000 = 2048, etc var baseSize = bufferBaseSize === -1 ? determineAutoBufferBaseSize() : bufferBaseSize === 0 ? determineBrowserDefaultBufferBaseSize() : bufferBaseSize; var totalSize = Javatari.AUDIO_MONITOR_BUFFER_SIZE > 0 ? Javatari.AUDIO_MONITOR_BUFFER_SIZE : baseSize > 0 ? jt.Util.exp2(jt.Util.log2((audioContext.sampleRate + 14000) / 22050) | 0) * jt.Util.exp2(baseSize - 1) * 256 : 0; processor = audioContext.createScriptProcessor(totalSize, 1, 1); processor.onaudioprocess = onAudioProcess; bufferSize = processor.bufferSize; updateResamplingFactors(); jt.Util.log("Audio Processor buffer size: " + processor.bufferSize); } catch(ex) { jt.Util.error("Could not create ScriptProcessorNode. Audio DISABLED!\n" + ex); } }; function registerUnlockOnTouchIfNeeded() { // Browser may require unlocking of the AudioContext on user interaction! if (processor && (!audioContext.state || audioContext.state === "suspended")) { mainElement.addEventListener("touchend", unlockAudioContext, true); mainElement.addEventListener("mousedown", unlockAudioContext, true); mainElement.addEventListener("keydown", unlockAudioContext, true); jt.Util.log("Speaker Audio Context resume event registered"); screen.speakerUnlockStateUpdate(false); } function unlockAudioContext() { mainElement.removeEventListener("touchend", unlockAudioContext, true); mainElement.removeEventListener("mousedown", unlockAudioContext, true); mainElement.removeEventListener("keydown", unlockAudioContext, true); var ex; try { audioContext.resume().then(function () { jt.Util.log('Speaker Audio Context resumed!'); }); } catch (e) { ex = e; } var source = audioContext.createBufferSource(); source.buffer = audioContext.createBuffer(1, 1, 22050); source.connect(audioContext.destination); source.start(0); if (ex) jt.Util.log("Audio Context unlocked!"); screen.speakerUnlockStateUpdate(true); } } function updateResamplingFactors() { //if (bufferSizeProblem !== undefined) console.error("+++++++ buffer size problem: " + bufferSizeProblem); if (!processor) return; resamplingFactor.length = audioSignal.length; resamplingLeftOver.length = audioSignal.length; for (var i = 0; i < audioSignal.length; i++) { resamplingFactor[i] = audioSignal[i].getSampleRate() / audioContext.sampleRate; resamplingLeftOver[i] = 0; audioSignal[i].setAudioMonitorBufferSize((resamplingFactor[i] * bufferSize) | 0); } } function onAudioProcess(event) { //if (Javatari.room.console.powerIsOn) { // var now = performance.now(); // Javatari.onAudioProcessLog.push(now - lastOnAudioProcessTime); // lastOnAudioProcessTime = now; //} // Assumes there is only one output channel var outputBuffer = event.outputBuffer.getChannelData(0); var outputBufferSize = outputBuffer.length; //if (outputBufferSize !== bufferSize) bufferSizeProblem = outputBufferSize; // Clear output buffer for (var j = outputBufferSize - 1; j >= 0; j = j - 1) outputBuffer[j] = 0; if (audioSignal.length === 0) return; // Mix all signals, performing resampling on-the-fly for (var i = audioSignal.length - 1; i >= 0; i = i - 1) { var resampFactor = resamplingFactor[i]; var input = audioSignal[i].retrieveSamples((outputBufferSize * resampFactor + resamplingLeftOver[i]) | 0, mute); var inputBuffer = input.buffer; var inputBufferSize = input.bufferSize; // Copy to output performing basic re-sampling // Same as Util.arrayCopyCircularSourceWithStep, but optimized with local code var s = input.start + resamplingLeftOver[i]; var d = 0; while (d < outputBufferSize) { outputBuffer[d] += inputBuffer[s | 0]; // source position as integer //COUNTER--; if (COUNTER < 0) { // COUNTER = 160; // SIGNAL = -SIGNAL; //} //outputBuffer[d] = SIGNAL * 0.4; d = d + 1; s = s + resampFactor; if (s >= inputBufferSize) s = s - inputBufferSize; } resamplingLeftOver[i] = s - (s | 0); // fractional part } //var str = ""; for (var i = 0; i < audioSignal.length; i++) str = str + audioSignal[i].name + " "; //console.log("AudioProcess: " + str); } var screen; var audioSignal = []; this.signals = audioSignal; var resamplingFactor = []; var resamplingLeftOver = []; var prefs = Javatari.userPreferences.current; var bufferBaseSize = Javatari.AUDIO_MONITOR_BUFFER_BASE === -3 ? prefs.audioBufferBase : Javatari.AUDIO_MONITOR_BUFFER_BASE; var audioContext; var bufferSize; var processor; var mute = false; //var bufferSizeProblem; //Javatari.onAudioProcessLog = [ ]; //var lastOnAudioProcessTime = 0; //var COUNTER = 0; //var SIGNAL = 1; }; ================================================ FILE: src/main/userprefs/UserPreferences.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. Javatari.userPreferences = { }; Javatari.userPreferences.currentVersion = 1; Javatari.userPreferences.compatibleVersions = new Set([ 1 ]); Javatari.userPreferences.defaults = function() { "use strict"; var k = jt.DOMKeys; return { joystickKeys: [ { left: k.VK_LEFT, up: k.VK_UP, right: k.VK_RIGHT, down: k.VK_DOWN, button: k.VK_SPACE, buttonT: k.VK_DELETE }, { left: k.VK_F, up: k.VK_T, right: k.VK_H, down: k.VK_G, button: k.VK_A, buttonT: k.VK_PERIOD } ], joystickGamepads: [ { button: 0, buttonT: 1, select: 8, reset: 9, pause: 4, fastSpeed: 7, slowSpeed: 6, device: -1, // -1 = auto xAxis: 0, xAxisSig: 1, yAxis: 1, yAxisSig: 1, paddleAxis: 0, paddleAxisSig: 1, paddleCenter: 0.3, paddleSens: 0.75, deadzone: 0.3 }, { button: 0, buttonT: 1, select: 8, reset: 9, pause: 4, fastSpeed: 7, slowSpeed: 6, device: -1, // -1 = auto xAxis: 0, xAxisSig: 1, yAxis: 1, yAxisSig: 1, paddleAxis: 0, paddleAxisSig: 1, paddleCenter: 0.3, paddleSens: 0.75, deadzone: 0.3 } ], touch: { directionalBig: false }, hapticFeedback: true, turboFireSpeed: 6, vSynch: 1, // on crtFilter: -1, // auto audioBufferBase: -1, // auto netPlaySessionName: "", netPlayNick: "" }; }; Javatari.userPreferences.load = function() { var prefs; // Load from Local Storage try { prefs = JSON.parse(localStorage.javatari4prefs || "{}"); // Migrations from old to new version control fields if (prefs.version) delete prefs.version; } catch(e) { // Give up } // Absent or incompatible version if (!prefs || !Javatari.userPreferences.compatibleVersions.has(prefs.prefsVersion)) { // Create new empty preferences and keep settings as possible var oldPrefs = prefs; prefs = {}; if (oldPrefs) { // Migrations } } // Fill missing properties with defaults var defs = Javatari.userPreferences.defaults(); for (var pref in defs) if (prefs[pref] === undefined) prefs[pref] = defs[pref]; prefs.prefsVersion = Javatari.userPreferences.currentVersion; // Update current preferences if (!Javatari.userPreferences.current) Javatari.userPreferences.current = {}; var cur = Javatari.userPreferences.current; for (pref in prefs) cur[pref] = prefs[pref]; Javatari.userPreferences.isDirty = false; }; Javatari.userPreferences.setDefaultJoystickKeys = function() { Javatari.userPreferences.current.joystickKeys = Javatari.userPreferences.defaults().joystickKeys; Javatari.userPreferences.setDirty(); }; Javatari.userPreferences.save = function() { if (!Javatari.userPreferences.isDirty) return; try { Javatari.userPreferences.current.javatariVersion = Javatari.VERSION; localStorage.javatari4prefs = JSON.stringify(Javatari.userPreferences.current); Javatari.userPreferences.isDirty = false; jt.Util.log("Preferences saved!"); } catch (e) { // give up } }; Javatari.userPreferences.setDirty = function() { Javatari.userPreferences.isDirty = true; }; ================================================ FILE: src/main/userprefs/UserROMFormats.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. Javatari.userROMFormats = { init: function() { jt.CartridgeCreator.setUserROMFormats(this); this.userFormats = JSON.parse(localStorage.javatariuserformats || "{}"); }, getForROM: function(rom) { return this.userFormats[rom.info.h]; }, setForROM: function(rom, formatName, isAuto) { if (!rom.info.h) return; if (isAuto) delete this.userFormats[rom.info.h]; else this.userFormats[rom.info.h] = formatName; localStorage.javatariuserformats = JSON.stringify(this.userFormats); } }; ================================================ FILE: src/main/util/EmbeddedFiles.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.EmbeddedFiles = { get: function(fileName) { var comp = this.compressedContent[fileName]; if (comp !== undefined) return { name: fileName, content: jt.Util.uncompressStringBase64ToInt8BitArray(comp) }; var diff = this.diffsContent[fileName]; if (diff === undefined) return undefined; var base = this.get(diff.based); if (base === undefined) return undefined; var content = base.content; for (var add in diff.diffs) { var bytes = diff.diffs[add]; for (var i = 0; i < bytes.length; ++i) content[(add | 0) + i] = bytes[i]; } return { name: fileName, content: content }; }, embedFileCompressedContent: function(fileName, compressedContent) { this.compressedContent[fileName] = compressedContent; }, embedFileDiff: function(fileName, diffs) { this.diffsContent[fileName] = diffs; }, compressedContent: {}, diffsContent: {} }; ================================================ FILE: src/main/util/MD5.js ================================================ jt.MD5 = function(data) { "use strict"; // convert number to (unsigned) 32 bit hex, zero filled string function to_zerofilled_hex(n) { var t1 = (n >>> 0).toString(16) return "00000000".substr(0, 8 - t1.length) + t1 } // convert array of chars to array of bytes function chars_to_bytes(ac) { var retval = [] for (var i = 0; i < ac.length; i++) { retval = retval.concat(str_to_bytes(ac[i])) } return retval } // convert a 64 bit unsigned number to array of bytes. Little endian function int64_to_bytes(num) { var retval = [] for (var i = 0; i < 8; i++) { retval.push(num & 0xFF) num = num >>> 8 } return retval } // 32 bit left-rotation function rol(num, places) { return ((num << places) & 0xFFFFFFFF) | (num >>> (32 - places)) } // The 4 MD5 functions function fF(b, c, d) { return (b & c) | (~b & d) } function fG(b, c, d) { return (d & b) | (~d & c) } function fH(b, c, d) { return b ^ c ^ d } function fI(b, c, d) { return c ^ (b | ~d) } // pick 4 bytes at specified offset. Little-endian is assumed function bytes_to_int32(arr, off) { return (arr[off + 3] << 24) | (arr[off + 2] << 16) | (arr[off + 1] << 8) | (arr[off]) } /* Conver string to array of bytes in UTF-8 encoding See: http://www.dangrossman.info/2007/05/25/handling-utf-8-in-javascript-php-and-non-utf8-databases/ http://stackoverflow.com/questions/1240408/reading-bytes-from-a-javascript-string How about a String.getBytes() for Javascript!? Isn't it time to add it? */ function str_to_bytes(str) { var retval = [ ] for (var i = 0; i < str.length; i++) if (str.charCodeAt(i) <= 0x7F) { retval.push(str.charCodeAt(i)) } else { var tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%') for (var j = 0; j < tmp.length; j++) { retval.push(parseInt(tmp[j], 0x10)) } } return retval } // convert the 4 32-bit buffers to a 128 bit hex string. (Little-endian is assumed) function int128le_to_hex(a, b, c, d) { var ra = "" var t = 0 var ta = 0 for (var i = 3; i >= 0; i--) { ta = arguments[i] t = (ta & 0xFF) ta = ta >>> 8 t = t << 8 t = t | (ta & 0xFF) ta = ta >>> 8 t = t << 8 t = t | (ta & 0xFF) ta = ta >>> 8 t = t << 8 t = t | ta ra = ra + to_zerofilled_hex(t) } return ra } // conversion from typed byte array to plain javascript array function typed_to_plain(tarr) { var retval = new Array(tarr.length) for (var i = 0; i < tarr.length; i++) { retval[i] = tarr[i] } return retval } // check input data type and perform conversions if needed var databytes = null // String var type_mismatch = null if (typeof data == 'string') { // convert string to array bytes databytes = str_to_bytes(data) } else if (data.constructor == Array) { if (data.length === 0) { // if it's empty, just assume array of bytes databytes = data } else if (typeof data[0] == 'string') { databytes = chars_to_bytes(data) } else if (typeof data[0] == 'number') { databytes = data } else { type_mismatch = typeof data[0] } } else if (typeof ArrayBuffer != 'undefined') { if (data instanceof ArrayBuffer) { databytes = typed_to_plain(new Uint8Array(data)) } else if ((data instanceof Uint8Array) || (data instanceof Int8Array)) { databytes = typed_to_plain(data) } else if ((data instanceof Uint32Array) || (data instanceof Int32Array) || (data instanceof Uint16Array) || (data instanceof Int16Array) || (data instanceof Float32Array) || (data instanceof Float64Array) ) { databytes = typed_to_plain(new Uint8Array(data.buffer)) } else { type_mismatch = typeof data } } else { type_mismatch = typeof data } if (type_mismatch) { alert('MD5 type mismatch, cannot process ' + type_mismatch) } function _add(n1, n2) { return 0x0FFFFFFFF & (n1 + n2) } return do_digest() function do_digest() { // function update partial state for each run function updateRun(nf, sin32, dw32, b32) { var temp = d d = c c = b //b = b + rol(a + (nf + (sin32 + dw32)), b32) b = _add(b, rol( _add(a, _add(nf, _add(sin32, dw32)) ), b32 ) ) a = temp } // save original length var org_len = databytes.length // first append the "1" + 7x "0" databytes.push(0x80) // determine required amount of padding var tail = databytes.length % 64 // no room for msg length? if (tail > 56) { // pad to next 512 bit block for (var i = 0; i < (64 - tail); i++) { databytes.push(0x0) } tail = databytes.length % 64 } for (i = 0; i < (56 - tail); i++) { databytes.push(0x0) } // message length in bits mod 512 should now be 448 // append 64 bit, little-endian original msg length (in *bits*!) databytes = databytes.concat(int64_to_bytes(org_len * 8)) // initialize 4x32 bit state var h0 = 0x67452301 var h1 = 0xEFCDAB89 var h2 = 0x98BADCFE var h3 = 0x10325476 // temp buffers var a = 0, b = 0, c = 0, d = 0 // Digest message for (i = 0; i < databytes.length / 64; i++) { // initialize run a = h0 b = h1 c = h2 d = h3 var ptr = i * 64 // do 64 runs updateRun(fF(b, c, d), 0xd76aa478, bytes_to_int32(databytes, ptr), 7) updateRun(fF(b, c, d), 0xe8c7b756, bytes_to_int32(databytes, ptr + 4), 12) updateRun(fF(b, c, d), 0x242070db, bytes_to_int32(databytes, ptr + 8), 17) updateRun(fF(b, c, d), 0xc1bdceee, bytes_to_int32(databytes, ptr + 12), 22) updateRun(fF(b, c, d), 0xf57c0faf, bytes_to_int32(databytes, ptr + 16), 7) updateRun(fF(b, c, d), 0x4787c62a, bytes_to_int32(databytes, ptr + 20), 12) updateRun(fF(b, c, d), 0xa8304613, bytes_to_int32(databytes, ptr + 24), 17) updateRun(fF(b, c, d), 0xfd469501, bytes_to_int32(databytes, ptr + 28), 22) updateRun(fF(b, c, d), 0x698098d8, bytes_to_int32(databytes, ptr + 32), 7) updateRun(fF(b, c, d), 0x8b44f7af, bytes_to_int32(databytes, ptr + 36), 12) updateRun(fF(b, c, d), 0xffff5bb1, bytes_to_int32(databytes, ptr + 40), 17) updateRun(fF(b, c, d), 0x895cd7be, bytes_to_int32(databytes, ptr + 44), 22) updateRun(fF(b, c, d), 0x6b901122, bytes_to_int32(databytes, ptr + 48), 7) updateRun(fF(b, c, d), 0xfd987193, bytes_to_int32(databytes, ptr + 52), 12) updateRun(fF(b, c, d), 0xa679438e, bytes_to_int32(databytes, ptr + 56), 17) updateRun(fF(b, c, d), 0x49b40821, bytes_to_int32(databytes, ptr + 60), 22) updateRun(fG(b, c, d), 0xf61e2562, bytes_to_int32(databytes, ptr + 4), 5) updateRun(fG(b, c, d), 0xc040b340, bytes_to_int32(databytes, ptr + 24), 9) updateRun(fG(b, c, d), 0x265e5a51, bytes_to_int32(databytes, ptr + 44), 14) updateRun(fG(b, c, d), 0xe9b6c7aa, bytes_to_int32(databytes, ptr), 20) updateRun(fG(b, c, d), 0xd62f105d, bytes_to_int32(databytes, ptr + 20), 5) updateRun(fG(b, c, d), 0x2441453, bytes_to_int32(databytes, ptr + 40), 9) updateRun(fG(b, c, d), 0xd8a1e681, bytes_to_int32(databytes, ptr + 60), 14) updateRun(fG(b, c, d), 0xe7d3fbc8, bytes_to_int32(databytes, ptr + 16), 20) updateRun(fG(b, c, d), 0x21e1cde6, bytes_to_int32(databytes, ptr + 36), 5) updateRun(fG(b, c, d), 0xc33707d6, bytes_to_int32(databytes, ptr + 56), 9) updateRun(fG(b, c, d), 0xf4d50d87, bytes_to_int32(databytes, ptr + 12), 14) updateRun(fG(b, c, d), 0x455a14ed, bytes_to_int32(databytes, ptr + 32), 20) updateRun(fG(b, c, d), 0xa9e3e905, bytes_to_int32(databytes, ptr + 52), 5) updateRun(fG(b, c, d), 0xfcefa3f8, bytes_to_int32(databytes, ptr + 8), 9) updateRun(fG(b, c, d), 0x676f02d9, bytes_to_int32(databytes, ptr + 28), 14) updateRun(fG(b, c, d), 0x8d2a4c8a, bytes_to_int32(databytes, ptr + 48), 20) updateRun(fH(b, c, d), 0xfffa3942, bytes_to_int32(databytes, ptr + 20), 4) updateRun(fH(b, c, d), 0x8771f681, bytes_to_int32(databytes, ptr + 32), 11) updateRun(fH(b, c, d), 0x6d9d6122, bytes_to_int32(databytes, ptr + 44), 16) updateRun(fH(b, c, d), 0xfde5380c, bytes_to_int32(databytes, ptr + 56), 23) updateRun(fH(b, c, d), 0xa4beea44, bytes_to_int32(databytes, ptr + 4), 4) updateRun(fH(b, c, d), 0x4bdecfa9, bytes_to_int32(databytes, ptr + 16), 11) updateRun(fH(b, c, d), 0xf6bb4b60, bytes_to_int32(databytes, ptr + 28), 16) updateRun(fH(b, c, d), 0xbebfbc70, bytes_to_int32(databytes, ptr + 40), 23) updateRun(fH(b, c, d), 0x289b7ec6, bytes_to_int32(databytes, ptr + 52), 4) updateRun(fH(b, c, d), 0xeaa127fa, bytes_to_int32(databytes, ptr), 11) updateRun(fH(b, c, d), 0xd4ef3085, bytes_to_int32(databytes, ptr + 12), 16) updateRun(fH(b, c, d), 0x4881d05, bytes_to_int32(databytes, ptr + 24), 23) updateRun(fH(b, c, d), 0xd9d4d039, bytes_to_int32(databytes, ptr + 36), 4) updateRun(fH(b, c, d), 0xe6db99e5, bytes_to_int32(databytes, ptr + 48), 11) updateRun(fH(b, c, d), 0x1fa27cf8, bytes_to_int32(databytes, ptr + 60), 16) updateRun(fH(b, c, d), 0xc4ac5665, bytes_to_int32(databytes, ptr + 8), 23) updateRun(fI(b, c, d), 0xf4292244, bytes_to_int32(databytes, ptr), 6) updateRun(fI(b, c, d), 0x432aff97, bytes_to_int32(databytes, ptr + 28), 10) updateRun(fI(b, c, d), 0xab9423a7, bytes_to_int32(databytes, ptr + 56), 15) updateRun(fI(b, c, d), 0xfc93a039, bytes_to_int32(databytes, ptr + 20), 21) updateRun(fI(b, c, d), 0x655b59c3, bytes_to_int32(databytes, ptr + 48), 6) updateRun(fI(b, c, d), 0x8f0ccc92, bytes_to_int32(databytes, ptr + 12), 10) updateRun(fI(b, c, d), 0xffeff47d, bytes_to_int32(databytes, ptr + 40), 15) updateRun(fI(b, c, d), 0x85845dd1, bytes_to_int32(databytes, ptr + 4), 21) updateRun(fI(b, c, d), 0x6fa87e4f, bytes_to_int32(databytes, ptr + 32), 6) updateRun(fI(b, c, d), 0xfe2ce6e0, bytes_to_int32(databytes, ptr + 60), 10) updateRun(fI(b, c, d), 0xa3014314, bytes_to_int32(databytes, ptr + 24), 15) updateRun(fI(b, c, d), 0x4e0811a1, bytes_to_int32(databytes, ptr + 52), 21) updateRun(fI(b, c, d), 0xf7537e82, bytes_to_int32(databytes, ptr + 16), 6) updateRun(fI(b, c, d), 0xbd3af235, bytes_to_int32(databytes, ptr + 44), 10) updateRun(fI(b, c, d), 0x2ad7d2bb, bytes_to_int32(databytes, ptr + 8), 15) updateRun(fI(b, c, d), 0xeb86d391, bytes_to_int32(databytes, ptr + 36), 21) // update buffers h0 = _add(h0, a) h1 = _add(h1, b) h2 = _add(h2, c) h3 = _add(h3, d) } // Done! Convert buffers to 128 bit (LE) return int128le_to_hex(h3, h2, h1, h0).toUpperCase() } }; ================================================ FILE: src/main/util/MultiDownloader.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.MultiDownloader = function (urlSpecs, onAllSuccess, onAnyError, timeout) { "use strict"; this.start = function() { if (urlSpecs && urlSpecs.length !== 0) { scheduleLoadingIcon(); for (var i = 0; i < urlSpecs.length; i++) load(urlSpecs[i]); } checkFinish(); }; function load(urlSpec) { if (!urlSpec) return; var urls = urlSpec.url.trim().split(/\s*\|\s*/); // Special "|" divider. TODO Find a better way since "|" is allowed in Linux file names urlSpec.filesToLoad = urls.length; urlSpec.filesContent = new Array(urlSpec.filesToLoad); // Ask to load all files for (var f = 0; f < urls.length; ++f) { var url = urls[f]; if (url[0] === "@") getEmbedded(urlSpec, f, url); // Embedded file? else getHTTP(urlSpec, f, url); // No, HTTP } } function getEmbedded(urlSpec, f, url) { jt.Util.log("Reading Embedded file: " + url); var file = jt.EmbeddedFiles.get(url.substr(1)); if (file !== undefined) loadSuccess(urlSpec, f, file.content); else loadError(urlSpec, "Embedded file not found!"); } function getHTTP(urlSpec, f, url, remote) { var finalUrl = isRemote(url) ? proxyze(url) : url; // May use a proxy downloader if configured var req = new XMLHttpRequest(); req.open("GET", finalUrl, true); req.responseType = "arraybuffer"; req.timeout = timeout !== undefined ? timeout : DEFAULT_TIMEOUT; req.onload = function () { if ((req.status === 200 || req.status === 0) && req.response) loadSuccess(urlSpec, f, new Uint8Array(req.response)); else req.onerror(); }; req.onerror = req.ontimeout = function () { loadError(urlSpec, "" + req.status + " " + req.statusText); }; jt.Util.log("Reading file from: " + url); req.send(); } function loadSuccess(urlSpec, f, content) { urlSpec.filesContent[f] = content; if (--urlSpec.filesToLoad > 0) return; // Still some files to complete loading urlSpec.success = true; urlSpec.content = jt.Util.arraysConcatAll(urlSpec.filesContent); // Concat all files in order if (urlSpec.onSuccess) urlSpec.onSuccess(urlSpec); checkFinish(); } function loadError(urlSpec, error) { urlSpec.success = false; urlSpec.error = error; var mes = "Could not load file: " + urlSpec.url + "\nError: " + error; if (urlSpec.onError) { jt.Util.error(mes); urlSpec.onError(urlSpec); } else if (!onAnyError) jt.Util.message(mes); checkFinish(); } function checkFinish() { if (finished) return; for (var i = 0; i < urlSpecs.length; i++) if (urlSpecs[i] && (urlSpecs[i].success === undefined)) return; finished = true; cancelLoadingIcon(); // All urls have a definition, check for errors for (i = 0; i < urlSpecs.length; i++) if (urlSpecs[i] && !urlSpecs[i].success) { if (onAnyError) onAnyError(urlSpecs); return; } // If no errors, then success if (onAllSuccess) onAllSuccess(urlSpecs); } function isRemote(url) { return url && (url.indexOf("http:") === 0 || url.indexOf("https:") === 0); } function proxyze(url) { return Javatari.PROXY_SERVER_ADDRESS ? "https://" + Javatari.PROXY_SERVER_ADDRESS + "/proxy-remote-download?url=" + url : url; } function scheduleLoadingIcon() { if (Javatari.room.isLoading) return; loadingTimer = window.setTimeout(function setLoadingOnDelay() { loadingTimer = null; loadingSet = true; Javatari.room.setLoading(true); }, LOADING_ICON_TIMEOUT); } function cancelLoadingIcon() { if (loadingTimer) { window.clearTimeout(loadingTimer); loadingTimer = null; } if (loadingSet) { loadingSet = false; Javatari.room.setLoading(false); } } var loadingSet = false; var loadingTimer = null; var finished = false; var LOADING_ICON_TIMEOUT = 1000; var DEFAULT_TIMEOUT = 15000; }; ================================================ FILE: src/main/util/MultiFileReader.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.MultiFileReader = function (files, onAllSuccess, onFirstError, maxTotalSize) { "use strict"; this.start = function() { if (!files || files.length === 0) onAllSuccess(files); else { if (!maxTotalSize) maxTotalSize = MAX_TOTAL_SIZE; var totalSize = 0; for (var i = 0; i < files.length; i++) totalSize += files[i].size; if (totalSize > maxTotalSize) { var error = "Maximum total size limit exceeded: " + ((maxTotalSize / 1024) | 0) + "KB"; if (onFirstError) onFirstError(files, error, true); // known error return; } for (i = 0; i < files.length; i++) load(files[i]); checkFinish(); } }; function load(file) { if (!file) return; jt.Util.log("Reading file: " + file.name); var reader = new FileReader(); reader.onload = function (event) { file.success = true; file.content = new Uint8Array(event.target.result); checkFinish(); }; reader.onerror = function (event) { file.success = false; file.error = event.target.error.name; checkFinish(); }; reader.readAsArrayBuffer(file); } function checkFinish() { if (finished) return; for (var i = 0; i < files.length; i++) if (files[i] && (files[i].success === undefined)) return; finished = true; // All files have a definition, check for errors for (i = 0; i < files.length; i++) if (files[i] && !files[i].success) { if (onFirstError) onFirstError(files, files[i].error); return files; } // If no errors, then success if (onAllSuccess) onAllSuccess(files); } var finished = false; var MAX_TOTAL_SIZE = 8 * 720 * 1024; // Read up 8 720KB disks of files }; ================================================ FILE: src/main/util/Util.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Util = new function() { "use strict"; this.logs = []; this.log = function(str) { var args = [ ">> jt:" ]; Array.prototype.push.apply(args, arguments); console.log.apply(console, args); //console.log(str); // this.logs.push(str); }; this.warning = function(str) { var args = [ ">> jt Warning:" ]; Array.prototype.push.apply(args, arguments); console.warn.apply(console, args); //console.warn(str); // this.logs.push(str); }; this.error = function(str) { var args = [ ">> jt Error:" ]; Array.prototype.push.apply(args, arguments); console.error.apply(console, args); //console.error(str); // this.logs.push(str); }; this.message = function(str) { console.info(str); alert(str); }; this.asNormalArray = function(arr) { if (arr instanceof Array) return arr; return this.arrayCopy(arr, 0, new Array(arr.length)); }; this.arrayFill = function(arr, val, from, to) { if (arr.fill) return arr.fill(val, from, to); // polyfill for TypedArrays or Arrays with native fill if (from === undefined) from = 0; for (var i = (to === undefined ? arr.length : to) - 1; i >= from; i = i - 1) arr[i] = val; return arr; }; this.arrayFillSegment = function(arr, from, to, val) { //noinspection UnnecessaryLocalVariableJS var i = to; while(i-- > from) arr[i] = val; return arr; }; this.arrayCopy = function(src, srcPos, dest, destPos, length) { destPos = destPos || 0; var finalSrcPos = length ? srcPos + length : src.length; while(srcPos < finalSrcPos) dest[destPos++] = src[srcPos++]; return dest; }; this.arrayAdd = function(arr, element) { arr[arr.length] = element; return arr; }; this.arrayRemoveAllElement = function(arr, element) { var i; while ((i = arr.indexOf(element)) >= 0) { arr.splice(i, 1); } return arr; }; this.arraysConcatAll = function(arrs) { var len = 0; for (var i = 0; i < arrs.length; ++i) len += arrs[i].length; var res = new (arrs[0].constructor)(len); // Same type as the first array var pos = 0; for (i = 0; i < arrs.length; ++i) { this.arrayCopy(arrs[i], 0, res, pos); pos += arrs[i].length; } return res; }; this.arrayRemove = function(arr, element) { var i = arr.indexOf(element); if (i < 0) return; arr.splice(i, 1); }; this.arraysEqual = function(a, b) { var i = a.length; if (i !== b.length) return false; while (i--) if (a[i] !== b[i]) return false; return true; }; // Only 8 bit values this.reverseInt8 = function(val) { return ((val & 0x01) << 7) | ((val & 0x02) << 5) | ((val & 0x04) << 3) | ((val & 0x08) << 1) | ((val & 0x10) >> 1) | ((val & 0x20) >> 3) | ((val & 0x40) >> 5) | ((val & 0x80) >> 7); }; this.int8BitArrayToByteString = function(ints, start, length) { if (ints === null || ints == undefined) return ints; if (start === undefined) start = 0; if (length === undefined) length = ints.length - start; var str = ""; for(var i = start, finish = start + length; i < finish; i = i + 1) str += String.fromCharCode(ints[i] & 0xff); return str; }; this.byteStringToInt8BitArray = function(str, dest) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; var len = str.length; var ints = (dest && dest.length === len) ? dest : new (dest ? dest.constructor : Array)(len); // Preserve dest type for(var i = 0; i < len; i = i + 1) ints[i] = (str.charCodeAt(i) & 0xff); return ints; }; // Only 32 bit values this.int32BitArrayToByteString = function(ints, start, length) { if (ints === null || ints == undefined) return ints; if (start === undefined) start = 0; if (length === undefined) length = ints.length - start; var str = ""; for(var i = start, finish = start + length; i < finish; i = i + 1) str += String.fromCharCode(ints[i] & 0xff) + String.fromCharCode((ints[i] >> 8) & 0xff) + String.fromCharCode((ints[i] >> 16) & 0xff) + String.fromCharCode((ints[i] >> 24) & 0xff); return str; }; this.byteStringToInt32BitArray = function(str, dest) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; var len = (str.length / 4) | 0; var ints = (dest && dest.length === len) ? dest : new (dest ? dest.constructor : Array)(len); // Preserve dest type for(var i = 0, s = 0; i < len; i = i + 1, s = s + 4) ints[i] = (str.charCodeAt(s) & 0xff) | ((str.charCodeAt(s + 1) & 0xff) << 8) | ((str.charCodeAt(s + 2) & 0xff) << 16) | ((str.charCodeAt(s + 3) & 0xff) << 24); return ints; }; this.storeInt8BitArrayToStringBase64 = function(arr) { if (arr === null || arr === undefined) return arr; if (arr.length === 0) return ""; return btoa(this.int8BitArrayToByteString(arr)); }; this.restoreStringBase64ToInt8BitArray = function(str, dest) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; if (str == "") return []; return this.byteStringToInt8BitArray(atob(str), dest); }; this.compressInt8BitArrayToStringBase64 = function(arr, length) { if (arr === null || arr === undefined) return arr; if (arr.length === 0) return ""; if (length < arr.length) return this.storeInt8BitArrayToStringBase64(JSZip.compressions.DEFLATE.compress(arr.slice(0, length))); else return this.storeInt8BitArrayToStringBase64(JSZip.compressions.DEFLATE.compress(arr)); }; this.uncompressStringBase64ToInt8BitArray = function(str, dest, diffSize) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; if (str == "") return []; var res = JSZip.compressions.DEFLATE.uncompress(atob(str)); if (dest && (diffSize || dest.length === res.length)) return this.arrayCopy(res, 0, dest); // Preserve dest else return this.arrayCopy(res, 0, new (dest ? dest.constructor : Array)(res.length)); // Preserve dest type }; this.storeInt32BitArrayToStringBase64 = function(arr) { if (arr === null || arr === undefined) return arr; if (arr.length === 0) return ""; return btoa(this.int32BitArrayToByteString(arr)); }; this.restoreStringBase64ToInt32BitArray = function(str, dest) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; if (str == "") return []; return this.byteStringToInt32BitArray(atob(str), dest); }; this.compressStringToStringBase64 = function(str) { if (str === null || str === undefined) return str; if (str.length === 0) return str; return this.storeInt8BitArrayToStringBase64(JSZip.compressions.DEFLATE.compress(str)); }; this.uncompressStringBase64ToString = function(str) { if (str === null || str === undefined) return str; if (str == "null") return null; if (str == "undefined") return undefined; if (str == "") return str; return this.int8BitArrayToByteString(JSZip.compressions.DEFLATE.uncompress(atob(str))); }; this.toHex2 = function(num) { if (num === null || num === undefined) return num; var res = num.toString(16).toUpperCase(); if (num >= 0 && (res.length % 2)) return "0" + res; else return res; }; this.toHex4 = function(num) { if (num === null || num === undefined) return num; var res = num.toString(16).toUpperCase(); if (num < 0) return res; switch (res.length) { case 4: return res; case 3: return "0" + res; case 2: return "00" + res; case 1: return "000" + res; default: return res; } }; this.escapeHtml = function(html) { return html .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'") .replace(/\//g,"/") .replace(/\?/g,"?") .replace(/\-/g, "-") .replace(/\|/g, "|"); }; this.arrayFind = function(arr, pred) { if (arr.find) return arr.find(pred); for (var i = 0, len = arr.length; i < len; ++i) if (pred(arr[i], i, arr)) return arr[i]; }; this.arrayFindIndex = function(arr, pred) { if (arr.findIndex) return arr.findIndex(pred); for (var i = 0, len = arr.length; i < len; ++i) if (pred(arr[i], i, arr)) return i; return -1; }; this.arrayIndexOfSubArray = function(arr, subarr, fromIndex, step) { var subLen = subarr.length; var len = arr.length; var st = step || 1; Loop: for (var i = fromIndex; (i >= 0) && (i < len); i += st) { for (var j = 0; j < subLen; j = j + 1) if (arr[i + j] !== subarr[j]) continue Loop; return i; } return -1; }; this.stringCountOccurrences = function(str, char) { var total = 0; for (var i = 0, len = str.length; i < len; ++i) if (str[i] == char) ++total; return total; }; this.stringStartsWith = function(str, start) { if (str.startsWith) return str.startsWith(start); else return str.substr(0, start.length) === start; }; this.stringEndsWith = function(str, end) { if (str.endsWith) return str.endsWith(end); else return str.substr(str.length - end.length) === end; }; this.checkContentIsZIP = function(content) { if (content && content[0] === 0x50 && content[1] === 0x4b) // PK signature try { return new JSZip(content); } catch(ez) { // Error decompressing files. Abort } return null; }; this.getZIPFilesSorted = function(zip) { var files = zip.file(/.+/); files.sort(sortByName); return files; }; this.checkContentIsGZIP = function(content) { if (!content || content[0] !== 0x1f || content[1] !== 0x8b || content[2] !== 0x08) return null; // GZ Deflate signature try { var flags = content[3]; var fHCRC = flags & 0x02; var fEXTRA = flags & 0x04; var fNAME = flags & 0x08; var fCOMMENT = flags & 0x10; // Skip MTIME, XFL and OS fields, no use... var pos = 10; // Skip bytes of optional content if (fEXTRA) { var xLEN = content[pos++] | (content[pos++] << 8); pos += xLEN; } if (fNAME) while (content[pos++] !== 0); if (fCOMMENT) while (content[pos++] !== 0); if (fHCRC) pos += 2; return JSZip.compressions.DEFLATE.uncompress(content.slice(pos, content.length - 8)); } catch (ez) { return null; // Error decompressing file. Abort } }; this.leafFilename = function(fileName) { return (((fileName && fileName.indexOf("/") >= 0) ? fileName.split("/").pop() : fileName) || "").trim(); }; this.leafFilenameNoExtension = function(fileName) { var name = this.leafFilename(fileName); var period = name.lastIndexOf("."); return period <= 0 ? name : name.substr(0, period).trim(); }; this.leafFilenameOnlyExtension = function(fileName) { var name = this.leafFilename(fileName); var period = name.lastIndexOf("."); return period <= 0 ? "" : name.substr(period + 1).trim(); }; function sortByName(a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; } this.dump = function(arr, from, chunk, quant) { var res = ""; var p = from || 0; quant = quant || 1; for(var i = 0; i < quant; i++) { for(var c = 0; c < chunk; c++) { var val = arr[p++]; res = res + (val != undefined ? val.toString(16, 2) + " " : "? "); } res = res + " "; } console.log(res); }; this.browserInfo = function() { if (this.browserInfoAvailable) return this.browserInfoAvailable; var ua = navigator.userAgent; var temp; var m = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; if (/trident/i.test(m[1])) { temp = /\brv[ :]+(\d+)/g.exec(ua) || []; return this.browserInfoAvailable = { name:'IE', version: (temp[1] || '') }; } if (m[1] === 'Chrome') { temp = ua.match(/\bOPR\/(\d+)/); if (temp != null) return this.browserInfoAvailable = { name:'OPERA', version: temp[1] }; } m = m[2] ? [m[1], m[2]] : [ navigator.appName, navigator.appVersion, '-?' ]; if ((temp = ua.match(/version\/(\d+)/i)) != null) m.splice(1, 1, temp[1]); var name = m[0].toUpperCase(); return this.browserInfoAvailable = { name: this.isIOSDevice() || name === "NETSCAPE" ? "SAFARI" : name, version: m[1] }; }; this.userLanguage = function() { return ((navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage || "en-US").trim(); }; this.browserCurrentURL = function () { return window.location.origin + window.location.pathname; }; this.isOfficialHomepage = function () { var loc = window.location; return loc && (loc.hostname.toLowerCase() === "javatari.org") && (loc.port === "" || loc.port === "80"); }; this.isTouchDevice = function() { return ('ontouchstart' in window) || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; }; this.isMobileDevice = function() { return this.isTouchDevice() && (/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i).test(navigator.userAgent); }; this.isIOSDevice = function() { return (/ipad|iphone|ipod/i).test(navigator.userAgent); }; this.isBrowserStandaloneMode = function() { return navigator.standalone || window.matchMedia("(display-mode: standalone)").matches; }; this.onTapOrMouseDown = function(element, handler) { this.addEventsListener(element, this.isTouchDevice() ? "touchstart mousedown" : "mousedown", handler); }; this.onTapOrMouseDownWithBlock = function(element, handler) { function onTapOrMouseDown(e) { handler(e); return blockEvent(e); } this.addEventsListener(element, this.isTouchDevice() ? "touchstart mousedown" : "mousedown", onTapOrMouseDown); }; this.onTapOrMouseUpWithBlock = function(element, handler) { function onTapOrMouseUp(e) { handler(e); return blockEvent(e); } this.addEventsListener(element, this.isTouchDevice() ? "touchstart mouseup" : "mouseup", onTapOrMouseUp); }; // Will fire event 2 times (at touch start and end) for needsUIG targets this.onTapOrMouseDownWithBlockUIG = function(element, handler) { function onTapOrMouseDownUIG(e) { if (e.type === "touchend" && !e.target.jtNeedsUIG) return blockEvent(e); // If User Initiated Gesture needed on TARGET, signal if starting or ending touch var uigStart = e.type === "touchstart" && e.target.jtNeedsUIG; var uigEnd = e.type === "touchend"; // Fire original event and block handler(e, uigStart, uigEnd); return blockEvent(e); } this.addEventsListener(element, this.isTouchDevice() ? "touchstart touchend mousedown" : "mousedown", onTapOrMouseDownUIG); }; function blockEvent(e) { e.stopPropagation(); if (e.cancelable) e.preventDefault(); return false; } this.blockEvent = blockEvent; this.addEventsListener = function(element, events, handler, capture) { events = events.split(" "); for (var i = 0; i < events.length; ++i) if (events[i]) element.addEventListener(events[i], handler, capture); }; this.removeEventsListener = function(element, events, handler, capture) { events = events.split(" "); for (var i = 0; i < events.length; ++i) if (events[i]) element.removeEventListener(events[i], handler, capture); }; this.insertCSS = function(css) { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = css; document.head.appendChild(style); }; this.scaleToFitParentHeight = function(element, parent, bottomOffset) { var availHeight = parent.clientHeight - bottomOffset - 20; // bar - tolerance var height = element.clientHeight; var scale = height < availHeight ? 1 : availHeight / height; element.style.transform = "translateY(-" + ((bottomOffset / 2) | 0) + "px) scale(" + scale.toFixed(4) + ")"; // console.log("SCALE availHeight: " + availHeight + ", height: " + height + ", final: " + height * scale); }; this.scaleToFitParentWidth = function(element, parent, horizMargin) { var availWidth = parent.clientWidth - (horizMargin * 2 | 0); // margins var width = element.clientWidth; var scale = width < availWidth ? 1 : availWidth / width; var finaWidth = (width * scale) | 0; var left = Math.floor((availWidth - finaWidth) / 2 + horizMargin); element.style.left = "" + left + "px"; element.style.right = "initial"; element.style.transform = "scale(" + scale.toFixed(4) + ")"; // console.log("SCALE availWidth: " + availWidth + ", width: " + width + ", final: " + width * scale + ", left: " + left); }; this.log2 = function(x) { return Math.log(x) / Math.log(2); }; this.exp2 = function(x) { return Math.pow(2, x); }; this.performanceNow = function() { return this.performanceNow.startOffset ? Date.now() - this.performanceNow.startOffset : window.performance.now(); }; }; if (!window.performance || !window.performance.now) jt.Util.performanceNow.startOffset = Date.now(); ================================================ FILE: src/main/util/ZIP.js ================================================ /*! JSZip - A Javascript class for generating and reading zip files (c) 2009-2014 Stuart Knightley Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. JSZip uses the library pako released under the MIT license : https://github.com/nodeca/pako/blob/master/LICENSE */ !function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.lengtha)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;gc;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;cg&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;cb?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header) };s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead=hb&&(a.ins_h=(a.ins_h<=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<=hb&&(a.ins_h=(a.ins_h<4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindexk&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<q&&(p+=B[f++]<>>=w,q-=w),15>q&&(p+=B[f++]<>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<q&&(p+=B[f++]<q&&(p+=B[f++]<k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whaven;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<n;){if(0===i)break a;i--,m+=e[g++]<>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.haven;){if(0===i)break a;i--,m+=e[g++]<>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a; if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<n;){if(0===i)break a;i--,m+=e[g++]<=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++hh?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++jj){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)}); ================================================ FILE: src/runtime/embedded/index.html ================================================ Javatari
================================================ FILE: src/runtime/images/EmbeddedImages.js ================================================ // Copyright 2015 by Paulo Augusto Peccin. See license.txt distributed with this file. jt.Images.embedded = true; jt.Images.urls.logo = "data:image/png;base64,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"; jt.Images.urls.loading = "data:image/gif;base64,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"; jt.Images.urls.mouseCursor = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABL0lEQVRYw+3VP0oDQRTH8U8k+AcFFRUFERGLiFjEA1jZTo6RG6T3ArmFR9j0WlpaWBiwsNNyiwgW0Vg4CUPELhMt9guPffumeG9nf/MbvlnEYVmWo3a7PcIO1s2R3aT5KQ6wMo/GC/G5nNTWsYr6PHdgE+fJLjRxhFqMbNSxFr96K6nvYxhr7zE+Y8yUWghhNH5pNBr6/f5ksdfrXeA1xiCbBoqiUBSF6RwN7GIptwh/4wR7UyKduQZ0Op1JIc2xHTVSzzpAt9v9sdBqtczTB/6Mfz/A2AOGOYe4DCGMUqI33OAKl1MmNVsjwhmaIYTrxIBu8YA73OMZb7kG2MFhPPPH2ECJJzzG5iU+ch3DMvnfL/HcDxILztZcctPVo9stxXyYCPBDRUVFRUVFRUa+AB+1YCivg1lPAAAAAElFTkSuQmCC"; jt.Images.urls.panel = "data:image/jpeg;base64,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"; jt.Images.urls.panelSprites = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wgARCAC6AgADASEAAhEBAxEB/8QAHAABAQACAwEBAAAAAAAAAAAAAAECBgMEBQgH/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHS5HCOxsBrfXrm5o2LXDl4y0wq2JaMTKmIyxrLGIq2LiBLUsJWUiUgonAvN6qebK6njinu8BnDi2yNWzMlbRrkZysMSQUBC5CkhBKIUKXEgUkAsLzlxOHYI86nU8anXPXHDmY7QaxxnPmbXrcZyvL4QAAAAAAAAAAAB6R2LHX2FfNys6vmDoHp9IQ59pjT8qx7Rueuxkry+EAAAAAAAAAAAAekdhHB6xrlrHEdU7Y7GB1tmPA544uvW7+BFleZwgAAAAAAAAAAAD0TnRwbwdGVw+cB436cdz84PI2M9TczT9GNx8CEPN4aAAAAAAAAAAAAeidvGOv79dGx1PErGG6fqdNFj8/2M/QfXOr+IG2+BFlebwgAAAAAAAAAAAD0Ts5x1NgOha63ljiO/wDph3NENY2M7e2Hk/npt3hxcTyuKgAAAAAAAAAAAHonZyjg9U8WnHw04jL0ztU8TYzyewdjxjbPBjJXl8BQAAhQAACFAAAAD0jsw6v7jHVUAfi3RPTwLsUaf2qw7JsWuxzQuVSFEpKUUJCVcBYuNZUmMVWGRApYKB0PpaCgD5x6Zxds5doNT6h3eaNk0qs8ygJSiVMsVCyLKUYgZDAUSkGOQhlDHhTt/SagAfiucc3AX1q8nsx18Ts6QefKAAAAAAAAAAAAChkep9IAAHzjgZ8hz+tGs5VycxsOpx5/HVgAKQAAAAAAAFhQAOY9H6OAAPm+mPFHd9etc5Di7Zseqx1+tXEKAgBChCwoAJQIAoAFOTuR2vo2gAPmriOPnOTYTVRy8htWrHXwEFAAIgoAAAAgCqEAqLy1z/SAAB8vUvEd72zVxx+gbTqhxYEFgFAAAAAWFhYSgSgAGWZyfTAAB8x9g3LXjxNlPA9ePT1Ctk04AABSAKACAKEAAAAAUv1QAAfMu8n6HgfiPsnifs529QPB1g45HGIpCgAQogoBCgAlABYuVcmZn9HgAHzDtp+m4n4v66eL+nrsej2dDW83CVjjEtBEAyIJagWJQoiAEqiouVZI5Mqv0MAAfMveO12zWtmPC7xsGpHt6cAEAAAAAAABYlLQCkJSzJH1KoAHzPDucKcG0rqnpHN4Fm5apLRZEogGULBQJlURRACkCkgUpjIKfToAB83eec3GejscadlWHZNo1ksAqAUlELCyqgEqoKlLIqpYQoxtRE+kqAA+c7HX5auwGtYGdNn1kyhZBSCkpKQACgAQVZBVkWFVAkPpAKAPnjzj0OodjZY0z0KcFntadKAQUQWCkASgAABYBQhYWFD6nAAP/8QALxAAAQMCAwYFBAMBAAAAAAAAAAECEQMSBAUTBhAUITM1IjAxMlAVFiVBICM2QP/aAAgBAQABBQJVFkVzBtRpMG0SxmyqsaiDXSsmO7R+7WoWsiGENhUbFrCGEMIaQ1VtYQwtYWtFawtYW0yGCIwsYqRTEaybaco1hDCxiisYWsi1hbTLWCIwhhawhhFOYpkUy1hDC1hbTi1keJoiyZ+xKm0T8PRQqYeihiqVNq73LaepIvMa6xdo/Dm6etwqI5rea43tFNfBuc9Gmsw1WGqw1GGqw1WGqw1WGqw1WGu012muw1mGtTNWmatM1KZqsNZhqsNWmazDWYazDXYazDVpmqw1mGsw1WGpTNVhqsNVhqsNVgnPco31zn/SVSuYzqaZp7n+6YL0Lk3bS95UuQRyEmP7Ozpbq3U+Goezc3qZz/paxXMb1d37rLDpuI3U3m06xnM3Fu6k6VzHszOnurdT4ah7NydXaRysz7WU1lUWrcXIXIfuv72MktLRU57Ud8YwgVCIdmfZG9PdW6nw1H2bk6uc5rjqOcrmeZoOzPM0K2b5pTPuHMz7hzM+4MzLFqYnB5NRpMqZThHNx+FXCVnem0vfsnyxK7OAw1ucZU2kxTMextVUpySVup8NR9kkjl/uzz/TVSuYrquYs2KWqhkcfVd20qJBtJ37KlRcCYlEXDr7sy7G3pbqvU+Go+wgd187/wBPXKxi+tueU6mni8JmbHMfmNFEzSsuIa1TaXv2W452HG5tQVuYY/WRvrmXY29PdV6nw1H2CDuvtE/T2idiJHYi4qVr3bqhX97XiKO9lJPHtMn5yk6UQc6G0/XM+xs6R+qqeP4akkMTcvXxWT4HFV/t/LD7fyw+38sPt/LD7fyw+38sKzZGOtG1B9QpIbTJObTaNqi1FeUmwZgs5HRdNPfPIncpO6RFJJJ3SXElxJeSSXFxcSK4u5IpIriSVLi4RSSST13pzrfzlHD2KI0ZTHeufqi5xUpqWFOkVFMcn4d3gVMQcQhxCHEIcQcQhxCHEIcQ04hprtnXacQ04hpxCGu0Wu2NdotdoldprtNdk67DXaa7TXacQ012muka7Z12mu010OIQ10FxBrnEIcQhxBxJxJxKjqjnlNIT+bsFlzhmFwCHDZcPweCVUweXomeYXBVcxp4fAoaWXqVMLglEweXMM4axmXPbPxqeRzUVed6jX3CczaLvMkjXIp+sf2d5UTn8SvIopLm+Q7dcO5jFuTadfzDFLheY1bm43s7hRWHNCTmczmc/+3nukkk5iMGjfIcsC1TUEWSl67Sp+avRC8RZKRjuzqL8Wgi+Q/m5Glp6LSXntQv5u1RWKIsFJTMlT6PcwVWkoShKEoShKEoShKEoShKEoS0lpLSWnhJaS0lpLTwktPCS0lp4SWkoShKEoShKEoShKEoShKHhEVois8hE5tRXOpZJUczMMtr4VMP1dpe+oYLBVcWYjIKyN030a2bdm+VXkbNUWOUc1Htr0ko5jtH32ik1MIxKeHNpMO1+ExzGuybSYabTTaWNLELELELELELELCxCxCxCxCxCxCxCxCxCxCxCxCxCxCxCxpYhYhYhYhYhYhYhYhYhYhY0sQsQsQ00NNolJppsNJnkPVb8sxPC1mVWPSrVZSbVq6uZbS8s+oeuV41tSibTYlqYfF9mFIIILS0gtQVCC0gtLRGlpaWlpBaQQWlpBBaQQWkFpBBaWkFpaQQInlOT+9eZRr1GFWsulR621KfmqXJtNVatHF1zMampXzdfw8kqSpKk/wDXJJKkqSpKlyl6lylyl7i5S5S9xe7yK621NSRjobiKktpJ4tp0/Lo5Sm5CpWsY1JMyRPo1rS1pa0taWsIaWtLWlrTwkNIaQhCEIcjkcjlMIQhy3cjkcjkIjSEIQhpDS1pCENIaQ0hpDS1hDC1pYhDCGEN8iol7E5CuQSXKxINouebu5CVIRy3DE8OYdnI3xvjzY8mN0fzgj+EeUngXRuNJwjIWbjaRq/WISoWKWEmOVEye5pc0uYXMLmlzS5hc0uaXMm9hewvYXsL2F7C9hewvYX0y9hew1GGow1GF7C9hewvYXsL2F7C9hewvYXtL2F7C9hewvYXML2FzC5he3yaPUnwr7Wem0HeMR1afoM9ub9n+V//EABgRAQEAAwAAAAAAAAAAAAAAABEAIECQ/9oACAEDAQE/Ac2Z0XnN/8QAHBEAAQQDAQAAAAAAAAAAAAAAAQAQEWAgQEGQ/9oACAECAQE/AcoUKPDosKAa6H5uf//EAEIQAAECAgUGCwQJBAMAAAAAAAABMQIRAxAhMrIEBRKCg6EgIjA0QVBRgZGi0RMjYWIkMzVCY3FykqMVQJOxUlNz/9oACAEBAAY/Ah5FkUy9aWlPq4UP+Jf3Fkc+4tM27TESQ43GLm8ZfEur4kpLL8xl8SyHeMviXV8S2FV7y7vLu8sh3n1e8uby5vLu8urL8y4v7i2DeXV8S6viXN5d3jbxhlXvGXxG3l0ur4l3eWoviXN5d3l2XeXN5cXxLq+Iy+Jd3lzeXT4VZQitxcKFLxbsukpOLdl0i6FnAn0k4nrl90p16bJftQ0onrlF3GbdpiJ9MQ9Vqjjjjjl4ccccccfguOOOOOOOOOOOOXi8OOOOOOTStUMo1cKGVaplOqR9w4/Dpu7CnAQzdtP9kNa9VKZRq4UMp1TKdUj7uQkpT6uFOBJTN20xENa9V5SqfLhQX4i/Et5HKNXClTV5v2mIhrXqulyegp9CjSUk0EXoQi+m3fw4fQi+mt+HD6HO57OH0Oc+SH0Oc+SH0Oc+SH0EghtVT3/vFUlDR6K/mLAvdVlGrhQ9rTXOhO0l7Kz8yKmoLifdqzftMRDWvVSFNq4UMp1TKdUiLErhnXAvTVT6uFCjSHoqjSJjvM37TEQ1r1UhS6uFDKtUynVIuBNHESlvCyitIohDKNXChL7pbYvYaFHdqzftMRDWvVUJTxdmjhQj+Yj+YVeBOtaqdf04U4Ob9piIeqra0IqanoNKkiddJTm3ni9Tm3ni9Tm3ni9Tm3ni9Tm3ni9Tm3ni9ararFqp9XCldlWbtpiETs/sWG4Df28+jkJK/A0IDKIFfi4UGGPgaEDmbURveYjiloww1owwwwwwwwww1TVWIMMMWIMMMMMMMMMMMMMMMMMWoMMfDkftO3/wU42dEi2Cn2gn+GI+1ZJ2ewUkmcv4FKVafLvZUlk4fZKsrCS51SLYKSTOMP8AgUl/Vf4FPtL+BTN6UNJ7WD3ko5Snb1t8CyGfxLpZ4VZRq4UOLaXN5xfCrNu0xVT6rmvI2V2OIrKU6fpwpXY5MzbtMVdnVNvK2CmUauFOApmzaYuu8oT9OFODmyay+txF/cXhxxxxxxxxxxx6nqccccccccccccccccccccccvF4vF4vl/cfWbuRSGFzjxaKixRQ8TtqynVwpV7uGztFWi4y9hoUiaKmatri63ipFfoqWGJJoRUaMhlOrhQRCFIUlV7f71GZs0vxMQwwww1bcu1bckw1TDDDVMMNyCoJO6ThUnEpFH2mUauFDSEhjWSpUlCi2xGbdpiH634sQscazUmU3dhQRCcLklpDtkZq2uLqdxxxxxxx+QnWkPaTKfuwpWqiqZrmn/biLoxdLowwwxdLowwwwwwwwwwwwwwwwwwwwwwwxdGGGLoxdLoxdLpd5DSROAhlKdmjhSu2rNm0xdbfJ/onCWpVJGKeKH5Z/tQseuSGbJ/iYq3repxx+A49Tjjjj1PwX4Ljj8B6nHqfklFqUQp9XCnBzVtcXW3//xAAqEAACAgEEAQIGAwEBAAAAAAAAAREhMRBBUWHwcYEgMJGhwfFQ0eGxQP/aAAgBAQABPyGAkUuEn2+wYcKPCBTUrkkYLF+47T7C8L4oLYkMRePYetZQST+kaAuuL1DfnPtzBpNpCQlg4kYpfYb0XvO06mYgOy0NNPKGSXcjAmiaZkEkodMPeaRzMo2kLZ9xG22/UkJhJRT9z3jBtBtvrGt3uE9w3lBMZL0bIMfUDKs9Q2xf3GSPvOk95LdvUT5XuLaY1tJ47Y2De4PmD9hHDSPeKZf9o3LJtc6APufUhspzwIFMvB2AyZ6jcobLsbiVVso3JZL5E3Ks2CWwhWVwqRUYvcHTHOoIbg5baQdyV7iVyv8AqLLv8Am/YTRs0Lcn7HmR4kedHmQlf4G7/Jd/U8aF+ueNHjR4EV5Ow7jkek8yGxf1POhfqaLyo8yHD/QWmnH9p40JH+DyI5vtPGjxo86POjj+0aGwZQnJPhLTKsHyMC+01Asj0TGiFlsUA7UDyvglM4FLkjIcpFfHiPS9pF/EtisUKsjVc6RcbmWMOwg/S/41WhpNLMRprBdl7O3gbNLMBprBEvsq7zQgptHh3/FtpUzgYg32nkO8b5D2d73O5/Q7n9BJ7CbdEToglgaNaaTWBUDishDQ2RyeN0HpJS2OY/iXzsJzuVPB/kUueV2Yrw94P6MfeDlwrrWKKKYRrnsz8ZKBz7RJjKJTCaGEjMAkiKG8nASUeZ0GCTknv/EN6ieDoMgT0SSucjAk+iv+EjgOkoSjbM7T6D04VTY1KHg4+jdOmbGiEltI5/hDYkQc/wAR8QsC6QJuzoVL6hiWKuF/wvTFDFOhB+cLvyXcbUMZ7ImDAEqzfIuNhTdEbfJdJ5I+LYMfsOP4kSiOSXBLQiL6Fn2H3cZ9hDnL1wQrRUqGPix1E2MaIctkwUA4kLoeF0N6MiW5HpnFMh8MjSOiHwyHwyOiCCHwz6kdMggh8MgjpkdMjpkEdMjo9mQ+GR0yCOmQQQQR0yOmQR0yHwyHwyHwx6NCRpGjFqeYULD4XxuOOOOGWJGvGwnVsTakZHDeiQmfoonI6gYD2Jst/wAQjdAmbkuMGw0pG+BtFQS4GeyROLgmpY4uKGvMEujHYo7glJbCXZCLVoXwkJHsj0oknERPwjPY5Qi8wkKR6UcSsrghrWETnYZiB9EO6kS4slwNgTZLcDeqr0MuhM5Y1TD5CkULpm4SY/dQMnuN3wV8YARl4Fm7Dm1UciF5Nz4EpZ+kM5wyaaiVg12DI9oLcEiQyBx2hPbtqhSMdGGCTUUJoklYRoJINSC26EVYEePvMIvYfeFIXNr7xxchx1cqLnrIp5CXcWcBxVYThTbwaDFWTAhUt/kbQ7f6iuPYH8i5Py5MGN8NkeCXjuI2+lQ7p2VJFiV/kTll47mBUnlJ/wCSsSfV/JBdcji7MQg0pIIIIIIIIIIIIIIIIII0gggggggggjSCCCCCCCCCCEQRaSKOV8iyq5H5nCRbm/UVOVrIhiK3tLcELjU5spnchEhPDw0QwYE5/iYNZwl8kybSwJgYonAe+oiXb5BDQxvA9EIe5fz4aLlw2CRPwBZZZZZZZZZZZZZZZZZZZZLJekslkslkskSyRIkS1FxT2RD5CFEeokm0KRyGcPJIAg8iXcUlMZyvJTm/q1p0kknSdE9NvjwPVaM20n4pJJ+JMWjF8ibowNY4rBLOpyOe3QE4UUjGJRPPuHQYH6E8aPCtD4VoPIjxL4kkl36Ds1AnUAegE/oPAidVCf0/CU140eNHjR5keNHiR4keBHgRP6PlGRlF7D4RP5lYiSUHtUanAslEGjnaZH2AsOWG4med0/8AJHxx/wCKCPkMLS1wYxVJqwzK6fjTz1fFzkgmymkvuSyI0xX6BxB/vj2Pv0DN1nTougg2IHQYJR0luDrK8HWdR1HSdOk6zq0XQdZ1nWdZ1nWdI+PVLo0XheuS3kbmQir935DiquS77ZFNNpjytihSnDfgf1AH9RY0oiUPDJy2Veg6t8wG1sETeZIXLPWR5PUQIcnYIVbinuNJI8yKe6Pb9TsQ4Di7aPUjEjyj2DVboto4j5wX4HSWyKzgudiJA9Y+5gLXQN0aPQIGvkWYOTIph6RJygaqWWKJfMsTWQhAweIEwJ9gyvxAlydzOxnYyXJLJZLJZLL+C9bLLLLLLLLJZLJZL5JZLklydx3Hcdx2vRNu47Q2bjvHaOwdj5MlIJYzjwVhIUWanIgpZBjmdiAwZvv8BftF9feL9of7RwfeLbPLpPiZBNmdIQ+U7phzGIhKDkLlnSFAOEIhwFXkJVkvTV4dPbDAtJTXBuvRbhIj52L9kf7g/wBo3S/2BwZfUa/9fIiKBJrwJKmZEzmxXsgJKVkbBFjr4CctxPPwHg9BHRC0QRqjojSCEQQiFwQiBrRCIRCIUkEIgjRFCoQRBAlRCEiDOEEL1GkQQGkQn8i9OQhaSRmpLyRosnZilk8HIJIoagU8kE8jPK+h2i5yZDsHziN3a5IzsKMnYWjYHYW18ASVhZp0Hadp3j5RkUeTuO87vgkke5yOhJ30k24h8w7BTDuO35G4eIRtuY+sMK1Ge4bcsynidP5b/9oADAMBAAIAAwAAABCn7LNZj79uwspmxgOqXLTISDJPDIQEwMgETEiAxID7hICETwzMzMzIBEzMzMyK6ASI+IcMzMzMzMzMzMzMz3jMxM7JDMzMzMzMzMzMzM68hKDAz+zMzMzMzMzMzMzGA4DEiMuEzMzMzMzMzMzMgrCEeMtPfMzMzMzMzMzMzI66gE5Ey4wAAEAAAEAAAAAE8ABCcAfozAhELE7EaIzEhPzMQESkRAgBSGCIQMgIyAVMzHMbf0SAAATMxMCIzMwMzMxEvIOEjIyMzMzExMQESEzMRgDOTEDEQEQACAzAzI5MzMxYhMTAAOTMTARugEw4zMyAwIzMTAgExAxESEgESEzMyE/MzMyMwADMBMzMzMhMzISE4KuMBIwECMAIgAJETMwGONLDhL72jKsLfsC8YMzMwYxg6uzsQMzMznIi76tszAfEkEO2c/74+/s3qw14TMwCJCxEZ6L3SjT8h4tzz8zMsEhECgDIhMCAAg9GvANszES9lIjAxIzIjMzEwERATMz/xAAhEQACAQQDAAMBAAAAAAAAAAABEQAwMUBBECAhUFFgcP/aAAgBAwEBPxDqIzqNGjRmMxqOPj2Mz09XHGYCjd4fqjrHMsKGsc6o6xzROOaOsfUVDWO3ePm8t01j6o6x9CjrGahpEuiqhD7W4BXF/wAsP4MfIODmvHUXCoguuOypH2AdRyuh6n4N0TbjcF8z/8QAIREAAgEEAwADAQAAAAAAAAAAAREAECAhQDAxQVBRYWD/2gAIAQIBAT8QgzmwxPYkSIRCIRcqiEIHkFErE8VWdcQ5zU0G0PYT9cHuuOEa4sWHb7OtYQ9wl5oRgVNPdcQ4r2FUBw4gOd8z3XFgiqZ7rjhGM635cc0Ifk/J18+A9c3mg/oAvdV8AD6nYqgPdGMCrKUcccccdrjjjjjMZjMcZjMZjMdop3AWN8YhLzwA2DX62u2+/8QAKhABAAICAQQBAwUAAwEAAAAAAQARITFBUWFxkYEQobEwwdHh8SBAUPD/2gAIAQEAAT8Q5LvRBVHti8h5zJZCnN/mYixaLLogzSB8n1CynyQlT6E/yToa0XMiGjSFqDV+0++KYD2vZzbMFAnulZEjlEqOEBV6gBSeFXq5S/JKVKlDndZPMBWxcpCVaw6kHSsyMY5jvNd+5QWPkHUtBPkIadtu/cZ8TbWL29DKpjhujBFIF3/YjYQ0tNRSlRzugwWDVqz5loXWrRiALVq1qdGqWk9QftbBSz8Y4J7DEjDfV7GoAWT5wBMQ2wKwzxZiFkpeGSf29EAGXWFRpUXISwUxbRlyrIB0WhidUCFMtXcLI6TawZCr4bQtLHVeI/g7UEVkZYOJeyXPRG46EOsDxmENaKy3ZEHb7nce5uTfWCBwgthPWaqbsAPaNggXLuXuHiDpdHqbJcEq09IAXV2JQKDnGJsBQdvELwrsmjHBiB4dkMgsRq10qCOJrKKd73QSx+9Dm+9LCmvylxWT3RItUapRdP5I/wCxAa+5CtHB7pal4ndLq1Di0Lw3vszTenZiQ0z4Ze5X4ZnsR8MW2/aFAoHFpozvygm7L1tMda+GFMKwCT1z8pQzn4Ys5+1gBVJ5Ro/mg2Mutoqfzy5u35RfO/lM1/mn/wBVP/ioMVl8oFxfV1loHSX2QsxrohUzdSgCu58kQ0Z6/UK3/wDwEbt/jPH6mvzF4w0R+tF8XB6WniUSNxhBoXpFVyYSDEuAhqP2wVTZAyMkV7WIiWs4PcIWu4JT1lmzt/0a+lf9TUt+grAmxLCxorONHA/cCKur/DHQcZOuEDG5TTniaPMe03WIrW1xEUEgG5UwBt8Kg09CFNbXEcBSwvBh9oMaw6g6wN/md5SyPwPx/wCPXlCqvbOavHMbQLOnxAebFgTLveOm6mcTDTdaj0lypMP7iYcexKDLfSKwYox8RbKoS3HKNUKY9CuYBfSeksz0hNgrtHTWescRoOGXcnfDXLcxsOEsSi+8/A/H/j1RWyU6sc1Kjp8RILiHXp25VSrlOWZ2uznge2b5hSaDQN3FHCbsJlgplmeygKcYnFQGs/aZcczH4iOEVlVYl4U0kF2l4rPAj+0HJFpHGrZmvmUi5Y2wxXhIbx2m/SBBTIwa8b3YNRX8H4/8eihyfzA5VTzUtdbR20Xx2gGwvMTUvSeyGslJr6lBhRpuKt2GZn/nFaqLOYywoG3DOWtzmc9YXH4D4lQDlSW2ruErDSg4tmeuIOotsWAE6D3AnAJqNO6v8wAuomVdHififj/x6DQ7OuCWFl3W5aLycVxLY93FQpxf5CE1YcftDTmrT4S1vczqm43XyfmKbqIj2lf3U5/hPDV7n5hyPGe6zLtt3AFeCftdJZa6d0X71KEtzLGeebcd4AtWExtVVmCZMjzMSVUz+H/x7hYqbbRisk8x3XFXj4lIlsVy02eXwmMx6v4QyQMHPQqXjZXmW1s9xO031lY2atgD3tcQVl8R2YJrpCCYtlRsGfiJqHBKEvZE9tqNQo6u1qIJTGhZmDFnqZC8OI11gpn+BLdH0yno+mW6vU/wGf4DLdXqW6PqW6Ppn+Aynp6Mt/Qy3R9Mt0fU/wACW6PqW/oZb+hlv6GW6PqW/olur1Kf6J/gMt/Qy3R9Mt/Qy3R9S3R9S3R9S3R9S39Et/Qy3R9Mt/RP8Cf4E/wJViu0B0jnve5cl1f4hHelXGAQwGDidrF2sXaxdrF2sQKIMRG7N8QhitMiPaDyloqXR5LWElK6oJwXuj39FywGH7R0DgKsLLTBItc157yyyswSy7msCu5G1g8Y9tT0RGD0gdkF8Ey/sCA4B8E1gdsEckWexEGgXsRDNehL1ss9pdgL4IkNZaxKQIXcLMXxK6iu0ErMdpbZR4JhCPxGuj4IsQ0OtEQBhdamYUjtMTB6IkyIeJWFPZUqO7pUQtT4JasYawR10Z7RzQD2gaFB2JUgj4TA4eKIpao7EUoD1Bhso9oxCBcw7FgLxEETAbuKPePX6HeXLhrxZziXRaORqc3OcmZnAMjzkh6t67gxFXzL67swvBfGAKMYLWxcJbL1lu7fMcVYneGz5rg+r5iUqnzKkBcnzKG1S7yzCdcVliFp1zGwrpbY1FfcxtKw8yvDLzFFj7lyixPOWWwz92U7K7yzZld5iin7mUlk5ywAJ7ZYS/lmWge+WFzxdbF5zKqsHm5lj3yhDHnLHEC4pU90qn2Ikgt8wd8+2YCq7WYodvmLn5MwB3N5gkfyliHoLhUK++WmhfGYNa3snODb9AsKxo4YNPXS1vUXsM7NUYfvBzfOU6+SvL8sL+eQuomIWAcauoe6TAj52iHoVwnzhEu9hHyYTWM7D7qO7MUpXmKVO9XzKkuYpBsiZSUiJSAjNT67AZSUgJSpXzKSrgPopEMoynSUuUlJSUSkpcp0lZTpKdIDpKdJSIhzEreIu3yuSXVs0U9P0LSqvplYwPD9ox5ZjUaQm3P3lKsDm5W9Bkog0t7ZqGTaeeiPFVvfHzDLZoTUGGeI3P8A7QvKV9XcP+TCV9X9Cr+oLETf0Prv6JKiVKlVAWKgLekQFoa7wC5y/oOxhqaUZQ94CqrJZLUJSg44HMa/AgcYYQ1UMiTsl+9dI2ztk0uDIcnSMPft0lo5DKW7YNe/Ut9Z4TCVjGrm5cfOXFxfdL7vUuLj5S+6XDUuV0uZYgrVy6cy+6KOs8kYW/8AACr6Doz6lf8Ak7s77NuftDAZjIfSaCqJmtaOv6FuXTCgVFA1d7jZZcYlaRiOmgEyi1B89RdIpi1vHtBObKYmWcCR2NFkKcx9pZzKIiEKWYqdWKiiaIYcS76SyiLuwimBMaxMCNFS88QReLIIGo1eAllkrMVdJjBiHQpipsqDhwRc4zFycEHHEyNkfJFxmo4yBntHGKIviU6EcOIVNEXDqKYaLmM4Lil4Al3wLAtqoFbu4i6cwKGj9BH2A4hWsRsmRKRFpl9TlxDw0E5JwTlaYOpLtjnmPq6m1wfkfi0U4TLwOMu8d96h10F+/qYXOCrcg/xzHV/THHT9S7b9Rfl6jtu/E7g+GY978MwOXqFu1eI8a9M2ZemHIvU4KPhm3P0x6/2hh/emMy9MsdvTGmremddHylGbPxOOweJ3XqPC/TKeXtHrI7yOC8d79QBTygtMyQirX5wDaz5QJl35/oZi5YA62gNwTm0VU+8eEDlDfwRQRyv8QLvBHj7QZoOxCr8zBwF6eWViA9a/kf8ARtqVKlMtEr/iZlpT/wBETog7L/QsomlghlahrYxRXgh8E2uOvm37x2KYrKZMFiMTJhBrmFKDmUi8MhTQIa4Xd1gMA15yw3I+UprA/wCyEa/KPJCTi/yzNwfMf98crlO3uUV1xXYlWIWAY+dxKv3TgUfMeq9zfSTjM5efeGpfm4df4uFP5XDTd73C0+241tfdNxazu5nLc+YHyTzCr8rj1fm4hzzzcQf5w52dMwCGPzAnP3TvvbEAdni2NW3uZQ16wX5Xi4Jy9zSpfMNWR5lOnxzMkd+7H6FqZCmOLiDxqB1y4TFaRd3AVpdfFIFk1z8TIowtqElHRfMYWCdbgaVYu4YSmZIE5A/aEMVzBigHEr0e5Y4D8wAWjOpwKX5mOwY3mFGuZS2DynCF+ZUNgeYFSC0zMB5IUF+DSUas8wNk9z9xEG1sO5Mk2B5gxaHzHuXyS+wVrMCTJ7lGgS+cygaY5uFQIPmcV4d4AgAd4ZiFd4lNJXmAFsHzMl2J5ggqleZ00s7wUaDUVQEp7xKWweIXtUuOhRfGYM1YxzoA8wQKpR3gihZ4zN0KPma0RHn9CplS1WO0V8vKU+/jceDGrWt4liGzmLbUysYbrYqHWpjmqpWH8wQ23NutQDpMaxV2vcU/mi2/dAq4O87iAaWKcs1ZYptfc7jL6mW9WW9WW9WX1Mt6sb5uX1Mu225fUy+plrll9TL6mX1MvqZ3H3LOWUcvuY6tmdxhTVvc7qZ94HzmALTjvKG8xKeUpLwT4jvAM/QALQfMCVM36NIYMvPxKxixL1EHKsunpMcNaIzg1LQCxNh2De0UaRgjdjnzLFalM1UKIKV7o2rfaXM4eUC24eUbsvtLVbO8B/lZwuPllnIetoXFffBByeYkNYzZzeMxXoeZd0DWYBptUGvSQwGHSZtA9b3L9WfOoKNxhhCqaZhg0BxPAo1y+1wBeXmUlLj3gFV71mKvCtZhBefmVBgPFxWk07xAPuhk3X3jx0fMTC5xrPlmI5bHkTYv4tL4DR7oFMvaImSnuwQFr8oABd1tEC17foZtDhftBRF9cFiL0qEVX+IJWKGZYqz7jY4PzjI+acOjiOYMUgacEgAYiLxARtjNq5S7CVsxmZYoqBtxEOm4DQLlbyHeUBiJrjxMVJmGWqCAGi4k/dOSoO8QKRC5W8ESvU0NFTFTHEAlFMDUsWyAL1CmaPU6usSvBfWEYZqJAsuJChK0gZZTgCywweYLmjEzGgr7yl4LeZXQhGdiojBjGoWWA9o4uguOImuf0G7ne/w5uV1B0XdxxCy3ZBZCiYAAxD+jZ0hf0A2OJZdv5lMr8Qo/qdpYCrxgkKCBMhuIFAIPoyrQZoogTVW9S04RPhBZGvEWGjGxRxuUlO/MKn7Jb3JS23I1KQ8S9wAJyoPiKHN8Mvp7Uwra5EQoeo8tXxADJuLNhPiGSvPDFF0rxKC6niJ9s6xb7SvIfvM9gO1RHuYKOFwvFHvBGqOqCgFviB4cIKuuNQ9v4QrsDvUHvHtiZAD1xFnBzGwK0foGSdVEtkzxEq2+YzYrmE0/RgC6ZNSty9xlq6eYTUbn2cvH0Po/Uj9ePpxD68x0TmcQnEZ0+nP0NfV19Hj6df0D6G/0P//Z"; jt.Images.urls.controllers = "data:image/jpeg;base64,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"; jt.Images.urls.iconSprites = "data:image/png;base64,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"; jt.Images.urls.muteIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAoCAYAAAC4h3lxAAAEwklEQVRYw+2YbWhbZRTH/+fJTdLbuHWsVTc6cK2DtDcJK2GsbAzpUNEPgjAUZYgyFXUZ8wVxm+ua2bjCuo19UDZQRFQCgkw3/CgMi9M6i9Q1uUntRsigww6duOFi3tr790smMaTvXbLq/t+S53Dv+T3nPOc55wK39R9UOp22DQ4OLq/Eu9RCP9A0zVXJZLK7pqbm8UUHEI/H7xeRd0juAVBXCQBtIR6SSCRqM5nMswACAFoAsFLpqi1AyhjZbDYAYBuAWhEByYoBzDmFOjs7VTQa3SIi75IMiEhtNQrGnCJw7ty5ervd/hKA7SLSWM2KN2uAWCy2QUQCJJ8UEQ1Vllamhkvxb13XCQD9/f32ZcuWPWVZ1g4AfhGRub50cHDwDpfLNe52uzMzsR8ZGVnhdrsvl1v7lxORSKTJZrO9CGApAJC8PD4+fkzTtOsishfAKyIybXkkaYnIm4ZhHCpz6O9USnWRTGWz2R6/3399mog/TPIZACe8Xu/nU0ZA07R6AM+RrAcAEbmgadqHTqeTuVzuoZk4P93ZAdBFcgeACYfDwYGBgZ7169enJqlwD4pIUEQ2kPTE43HLMIyT01YhKagkQjIf503TdDocjh1KqYCIKBGxi8jrLpdrT39/f+0kl2IQwIaCTz6SwVgs5r+prcRk8nq9WcuyRi3L+qVooxwA3qirq9vd19enF6VNB8mgiGwqSksCMEn+uuA38SwgPopGoxrJ/TfKr4g4Se5qaGiwTNM8SLK9sPP3FTuvlPqUZMjj8VyqGgAArlmz5oNkMqkKECsLEDUisgvAKgD3Athc7DzJz0Qk1NraeuGm9EKzka7rTKfT71+8eFFZlrVfRO4uLNWS3CYitmLnReQEyVBLS8tIRdrpmUKEw+H3ABwA8FvRmbCV5PxJACGv1xuv2DwwU/X09FjNzc3HAXwMIFeucGma9rZhGGZFB5pZtuFrSbYAcJQp5ffk8/nN6XRa3ZIA0Wh0LYD9IvLIJCZLRWRfIpHY2dnZqW4pgKGhIZ9SKqiUerSkBTlPMlUUheUism/r1q2B0h6tagCmaRqapgVFZEvJ0leWZT1P8gCAP4sgGgB0JRKJ7eUgKgoQiURalFJBEXmsZOdPAwj5fL4zuVzu6MTERG9JJO4Ska5kMvlCaUtTMYBkMulSSj0N4ImSpa+VUt2GYXwHAH6/PyciR0geIpkuglhBcq9pmu1VAWhqakqJyFkAPxXt/DckQ62trWdK+6YrV64cBnCYZKZgOwHgi1Qq9fNUACR5meQYyTERGSv5f17Dusfj+ZJkiGSE5Lci0u3xePrK2XZ0dKSvXbvWC+BIIRLH8vn8gfb29quTthKjo6NDjY2N/4TYsiz6fL5LhcN3FECO5BYRUfOAOBWLxa4CyBqG8f1Uths3bvxrYGDg4JIlS37I5/Nn29rafp9yIpvBQLLSbrcHCsN8/Vwmsqp+Vmlraxtrbm5+i+SrAM5W8vvPgl1kuq5PeL3eMICdJD8BkF9UADdkGMaPmUzmtcLwMbroAABg3bp1f6xevbqX5MskT1cjpeZ9D+i6To/Hc0rTtJ0icrz48lkUADfkdruHnU7nLgC7AZzHYtbw8PADkUhk06KGCIfDNtzW/0B/A2/7MX7SZ6/PAAAAAElFTkSuQmCC"; ================================================ FILE: src/runtime/standalone/cache.manifest ================================================ CACHE MANIFEST # Version 5.0.4 # Stable CACHE: manifest.webapp images/logo-icon192.png images/logo-icon512.png NETWORK: * ================================================ FILE: src/runtime/standalone/index.base.html ================================================ Javatari
The online Atari 2600 emulator
Select Cartridge slot to load ROMs
Drag & Drop or Select Cartridge slot to load ROMs
================================================ FILE: src/runtime/standalone/index.part1.html ================================================ Javatari
The online Atari 2600 emulator
Select Cartridge slot to load ROMs
Drag & Drop or Select Cartridge slot to load ROMs
================================================ FILE: src/runtime/standalone/manifest.webapp ================================================ { "name": "Javatari", "description": "Javatari - The online Atari 2600 emulator", "display": "standalone", "background_color": "#000", "theme_color": "#363636", "icons": [{ "src": "images/logo-icon192.png", "sizes": "192x192", "type": "image/png" }, { "src": "images/logo-icon512.png", "sizes": "512x512", "type": "image/png" }] } ================================================ FILE: test/index.html ================================================ Javatari Test
================================================ FILE: test/manifest.webapp ================================================ { "name": "Javatari", "description": "Javatari - The online Atari 2600 emulator (test)", "start_url": ".", "display": "standalone", "background_color": "#000", "icons": [{ "src": "../src/runtime/images/files/logo-icon192.png", "sizes": "192x192", "type": "image/png" }, { "src": "../src/runtime/images/files/logo-icon512.png", "sizes": "512x512", "type": "image/png" }] }